Merge #8580: Make CTransaction actually immutable
81e3228 Make CTransaction actually immutable (Pieter Wuille) 42fd8de Make DecodeHexTx return a CMutableTransaction (Pieter Wuille) c3f5673 Make CWalletTx store a CTransactionRef instead of inheriting (Pieter Wuille) a188353 Switch GetTransaction to returning a CTransactionRef (Pieter Wuille)
This commit is contained in:
parent
1e62969fa6
commit
525c049316
@ -19,7 +19,7 @@ static void addCoin(const CAmount& nValue, const CWallet& wallet, vector<COutput
|
||||
tx.nLockTime = nextLockTime++; // so all transactions get different hashes
|
||||
tx.vout.resize(nInput + 1);
|
||||
tx.vout[nInput].nValue = nValue;
|
||||
CWalletTx* wtx = new CWalletTx(&wallet, tx);
|
||||
CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx)));
|
||||
|
||||
int nAge = 6 * 24;
|
||||
COutput output(wtx, nInput, nAge, true, true);
|
||||
|
@ -11,13 +11,14 @@
|
||||
class CBlock;
|
||||
class CScript;
|
||||
class CTransaction;
|
||||
class CMutableTransaction;
|
||||
class uint256;
|
||||
class UniValue;
|
||||
|
||||
// core_read.cpp
|
||||
CScript ParseScript(const std::string& s);
|
||||
std::string ScriptToAsmStr(const CScript& script, const bool fAttemptSighashDecode = false);
|
||||
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx);
|
||||
bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx);
|
||||
bool DecodeHexBlk(CBlock&, const std::string& strHexBlk);
|
||||
uint256 ParseHashUV(const UniValue& v, const std::string& strName);
|
||||
uint256 ParseHashStr(const std::string&, const std::string& strName);
|
||||
|
@ -90,7 +90,7 @@ CScript ParseScript(const std::string& s)
|
||||
return result;
|
||||
}
|
||||
|
||||
bool DecodeHexTx(CTransaction& tx, const std::string& strHexTx)
|
||||
bool DecodeHexTx(CMutableTransaction& tx, const std::string& strHexTx)
|
||||
{
|
||||
if (!IsHex(strHexTx))
|
||||
return false;
|
||||
|
@ -608,7 +608,7 @@ static int CommandLineRawTx(int argc, char* argv[])
|
||||
argv++;
|
||||
}
|
||||
|
||||
CTransaction txDecodeTmp;
|
||||
CMutableTransaction tx;
|
||||
int startArg;
|
||||
|
||||
if (!fCreateBlank) {
|
||||
@ -621,15 +621,13 @@ static int CommandLineRawTx(int argc, char* argv[])
|
||||
if (strHexTx == "-") // "-" implies standard input
|
||||
strHexTx = readStdin();
|
||||
|
||||
if (!DecodeHexTx(txDecodeTmp, strHexTx))
|
||||
if (!DecodeHexTx(tx, strHexTx))
|
||||
throw std::runtime_error("invalid transaction encoding");
|
||||
|
||||
startArg = 2;
|
||||
} else
|
||||
startArg = 1;
|
||||
|
||||
CMutableTransaction tx(txDecodeTmp);
|
||||
|
||||
for (int i = startArg; i < argc; i++) {
|
||||
std::string arg = argv[i];
|
||||
std::string key, value;
|
||||
|
@ -510,19 +510,19 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
|
||||
CAmount nMinFee = GetMinCollateralFee();
|
||||
uint256 nExpectedHash = GetHash();
|
||||
|
||||
CTransaction txCollateral;
|
||||
CTransactionRef txCollateral;
|
||||
uint256 nBlockHash;
|
||||
|
||||
// RETRIEVE TRANSACTION IN QUESTION
|
||||
|
||||
if(!GetTransaction(nCollateralHash, txCollateral, Params().GetConsensus(), nBlockHash, true)){
|
||||
strError = strprintf("Can't find collateral tx %s", txCollateral.ToString());
|
||||
strError = strprintf("Can't find collateral tx %s", txCollateral->ToString());
|
||||
LogPrintf("CGovernanceObject::IsCollateralValid -- %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
|
||||
if(txCollateral.vout.size() < 1) {
|
||||
strError = strprintf("tx vout size less than 1 | %d", txCollateral.vout.size());
|
||||
if(txCollateral->vout.size() < 1) {
|
||||
strError = strprintf("tx vout size less than 1 | %d", txCollateral->vout.size());
|
||||
LogPrintf("CGovernanceObject::IsCollateralValid -- %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@ -532,7 +532,7 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
|
||||
CScript findScript;
|
||||
findScript << OP_RETURN << ToByteVector(nExpectedHash);
|
||||
|
||||
DBG( cout << "IsCollateralValid: txCollateral.vout.size() = " << txCollateral.vout.size() << endl; );
|
||||
DBG( cout << "IsCollateralValid: txCollateral->vout.size() = " << txCollateral->vout.size() << endl; );
|
||||
|
||||
DBG( cout << "IsCollateralValid: findScript = " << ScriptToAsmStr( findScript, false ) << endl; );
|
||||
|
||||
@ -540,13 +540,13 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
|
||||
|
||||
|
||||
bool foundOpReturn = false;
|
||||
BOOST_FOREACH(const CTxOut o, txCollateral.vout) {
|
||||
BOOST_FOREACH(const CTxOut o, txCollateral->vout) {
|
||||
DBG( cout << "IsCollateralValid txout : " << o.ToString()
|
||||
<< ", o.nValue = " << o.nValue
|
||||
<< ", o.scriptPubKey = " << ScriptToAsmStr( o.scriptPubKey, false )
|
||||
<< endl; );
|
||||
if(!o.scriptPubKey.IsPayToPublicKeyHash() && !o.scriptPubKey.IsUnspendable()) {
|
||||
strError = strprintf("Invalid Script %s", txCollateral.ToString());
|
||||
strError = strprintf("Invalid Script %s", txCollateral->ToString());
|
||||
LogPrintf ("CGovernanceObject::IsCollateralValid -- %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
@ -561,7 +561,7 @@ bool CGovernanceObject::IsCollateralValid(std::string& strError, bool& fMissingC
|
||||
}
|
||||
|
||||
if(!foundOpReturn){
|
||||
strError = strprintf("Couldn't find opReturn %s in %s", nExpectedHash.ToString(), txCollateral.ToString());
|
||||
strError = strprintf("Couldn't find opReturn %s in %s", nExpectedHash.ToString(), txCollateral->ToString());
|
||||
LogPrintf ("CGovernanceObject::IsCollateralValid -- %s\n", strError);
|
||||
return false;
|
||||
}
|
||||
|
@ -608,7 +608,7 @@ bool CInstantSend::ResolveConflicts(const CTxLockCandidate& txLockCandidate)
|
||||
}
|
||||
} // FOREACH
|
||||
// No conflicts were found so far, check to see if it was already included in block
|
||||
CTransaction txTmp;
|
||||
CTransactionRef txTmp;
|
||||
uint256 hashBlock;
|
||||
if(GetTransaction(txHash, txTmp, Params().GetConsensus(), hashBlock, true) && hashBlock != uint256()) {
|
||||
LogPrint("instantsend", "CInstantSend::ResolveConflicts -- Done, %s is included in block %s\n", txHash.ToString(), hashBlock.ToString());
|
||||
|
@ -1611,7 +1611,7 @@ bool static ProcessMessage(CNode* pfrom, string strCommand, CDataStream& vRecv,
|
||||
|
||||
deque<COutPoint> vWorkQueue;
|
||||
vector<uint256> vEraseQueue;
|
||||
CTransaction tx;
|
||||
CMutableTransaction tx;
|
||||
CTxLockRequest txLockRequest;
|
||||
CDarksendBroadcastTx dstx;
|
||||
int nInvType = MSG_TX;
|
||||
|
@ -84,29 +84,15 @@ std::string CMutableTransaction::ToString() const
|
||||
return str;
|
||||
}
|
||||
|
||||
void CTransaction::UpdateHash() const
|
||||
uint256 CTransaction::ComputeHash() const
|
||||
{
|
||||
*const_cast<uint256*>(&hash) = SerializeHash(*this);
|
||||
return SerializeHash(*this);
|
||||
}
|
||||
|
||||
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0) { }
|
||||
|
||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime) {
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vin(std::move(tx.vin)), vout(std::move(tx.vout)), nLockTime(tx.nLockTime) {
|
||||
UpdateHash();
|
||||
}
|
||||
|
||||
CTransaction& CTransaction::operator=(const CTransaction &tx) {
|
||||
*const_cast<int*>(&nVersion) = tx.nVersion;
|
||||
*const_cast<std::vector<CTxIn>*>(&vin) = tx.vin;
|
||||
*const_cast<std::vector<CTxOut>*>(&vout) = tx.vout;
|
||||
*const_cast<unsigned int*>(&nLockTime) = tx.nLockTime;
|
||||
*const_cast<uint256*>(&hash) = tx.hash;
|
||||
return *this;
|
||||
}
|
||||
/* For backward compatibility, the hash is initialized to 0. TODO: remove the need for this default constructor entirely. */
|
||||
CTransaction::CTransaction() : nVersion(CTransaction::CURRENT_VERSION), vin(), vout(), nLockTime(0), hash() {}
|
||||
CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vout(tx.vout), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
|
||||
CTransaction::CTransaction(CMutableTransaction &&tx) : nVersion(tx.nVersion), vin(std::move(tx.vin)), vout(std::move(tx.vout)), nLockTime(tx.nLockTime), hash(ComputeHash()) {}
|
||||
|
||||
CAmount CTransaction::GetValueOut() const
|
||||
{
|
||||
|
@ -207,11 +207,6 @@ struct CMutableTransaction;
|
||||
*/
|
||||
class CTransaction
|
||||
{
|
||||
private:
|
||||
/** Memory only. */
|
||||
const uint256 hash;
|
||||
void UpdateHash() const;
|
||||
|
||||
public:
|
||||
// Default transaction version.
|
||||
static const int32_t CURRENT_VERSION=1;
|
||||
@ -232,6 +227,13 @@ public:
|
||||
const std::vector<CTxOut> vout;
|
||||
const uint32_t nLockTime;
|
||||
|
||||
private:
|
||||
/** Memory only. */
|
||||
const uint256 hash;
|
||||
|
||||
uint256 ComputeHash() const;
|
||||
|
||||
public:
|
||||
/** Construct a CTransaction that qualifies as IsNull() */
|
||||
CTransaction();
|
||||
|
||||
@ -239,20 +241,16 @@ public:
|
||||
CTransaction(const CMutableTransaction &tx);
|
||||
CTransaction(CMutableTransaction &&tx);
|
||||
|
||||
CTransaction& operator=(const CTransaction& tx);
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
READWRITE(*const_cast<int32_t*>(&this->nVersion));
|
||||
READWRITE(*const_cast<std::vector<CTxIn>*>(&vin));
|
||||
READWRITE(*const_cast<std::vector<CTxOut>*>(&vout));
|
||||
READWRITE(*const_cast<uint32_t*>(&nLockTime));
|
||||
if (ser_action.ForRead())
|
||||
UpdateHash();
|
||||
template <typename Stream>
|
||||
inline void Serialize(Stream& s) const {
|
||||
s << this->nVersion;
|
||||
s << vin;
|
||||
s << vout;
|
||||
s << nLockTime;
|
||||
}
|
||||
|
||||
/** This deserializing constructor is provided instead of an Unserialize method.
|
||||
* Unserialize is not possible, since it would require overwriting const fields. */
|
||||
template <typename Stream>
|
||||
CTransaction(deserialize_type, Stream& s) : CTransaction(CMutableTransaction(deserialize, s)) {}
|
||||
|
||||
@ -274,7 +272,7 @@ public:
|
||||
|
||||
// Compute modified tx size for priority calculation (optionally given tx size)
|
||||
unsigned int CalculateModifiedSize(unsigned int nTxSize=0) const;
|
||||
|
||||
|
||||
/**
|
||||
* Get the total transaction size in bytes, including witness data.
|
||||
* "Total Size" defined in BIP141 and BIP144.
|
||||
|
@ -155,8 +155,8 @@ void CPrivateSendClient::ProcessMessage(CNode* pfrom, std::string& strCommand, C
|
||||
}
|
||||
|
||||
int nMsgSessionID;
|
||||
CTransaction txNew;
|
||||
vRecv >> nMsgSessionID >> txNew;
|
||||
vRecv >> nMsgSessionID;
|
||||
CTransaction txNew(deserialize, vRecv);
|
||||
|
||||
if(nSessionID != nMsgSessionID) {
|
||||
LogPrint("privatesend", "DSFINALTX -- message doesn't match current PrivateSend session: nSessionID: %d nMsgSessionID: %d\n", nSessionID, nMsgSessionID);
|
||||
@ -1091,7 +1091,7 @@ bool CPrivateSendClient::PrepareDenominate(int nMinRounds, int nMaxRounds, std::
|
||||
std::vector<COutput>::iterator it2 = vCoins.begin();
|
||||
while (it2 != vCoins.end()) {
|
||||
// we have matching inputs
|
||||
if ((*it2).tx->vout[(*it2).i].nValue == nValueDenom) {
|
||||
if ((*it2).tx->tx->vout[(*it2).i].nValue == nValueDenom) {
|
||||
// add new input in resulting vector
|
||||
vecTxDSInRet.push_back(*it);
|
||||
// remove corresponting items from initial vectors
|
||||
|
@ -39,8 +39,8 @@ void CPrivateSendServer::ProcessMessage(CNode* pfrom, std::string& strCommand, C
|
||||
}
|
||||
|
||||
int nDenom;
|
||||
CTransaction txCollateral;
|
||||
vRecv >> nDenom >> txCollateral;
|
||||
vRecv >> nDenom;
|
||||
CTransaction txCollateral(deserialize, vRecv);
|
||||
|
||||
LogPrint("privatesend", "DSACCEPT -- nDenom %d (%s) txCollateral %s", nDenom, CPrivateSend::GetDenominationsToString(nDenom), txCollateral.ToString());
|
||||
|
||||
|
@ -524,14 +524,14 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
|
||||
nQuantity++;
|
||||
|
||||
// Amount
|
||||
nAmount += out.tx->vout[out.i].nValue;
|
||||
nAmount += out.tx->tx->vout[out.i].nValue;
|
||||
|
||||
// Priority
|
||||
dPriorityInputs += (double)out.tx->vout[out.i].nValue * (out.nDepth+1);
|
||||
dPriorityInputs += (double)out.tx->tx->vout[out.i].nValue * (out.nDepth+1);
|
||||
|
||||
// Bytes
|
||||
CTxDestination address;
|
||||
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, address))
|
||||
if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, address))
|
||||
{
|
||||
CPubKey pubkey;
|
||||
CKeyID *keyid = boost::get<CKeyID>(&address);
|
||||
@ -731,7 +731,7 @@ void CoinControlDialog::updateView()
|
||||
CAmount nSum = 0;
|
||||
int nChildren = 0;
|
||||
BOOST_FOREACH(const COutput& out, coins.second) {
|
||||
nSum += out.tx->vout[out.i].nValue;
|
||||
nSum += out.tx->tx->vout[out.i].nValue;
|
||||
nChildren++;
|
||||
|
||||
CCoinControlWidgetItem *itemOutput;
|
||||
@ -743,7 +743,7 @@ void CoinControlDialog::updateView()
|
||||
// address
|
||||
CTxDestination outputAddress;
|
||||
QString sAddress = "";
|
||||
if(ExtractDestination(out.tx->vout[out.i].scriptPubKey, outputAddress))
|
||||
if(ExtractDestination(out.tx->tx->vout[out.i].scriptPubKey, outputAddress))
|
||||
{
|
||||
sAddress = QString::fromStdString(CBitcoinAddress(outputAddress).ToString());
|
||||
|
||||
@ -770,9 +770,9 @@ void CoinControlDialog::updateView()
|
||||
}
|
||||
|
||||
// amount
|
||||
itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->vout[out.i].nValue));
|
||||
itemOutput->setToolTip(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->vout[out.i].nValue));
|
||||
itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.tx->vout[out.i].nValue)); // padding so that sorting works correctly
|
||||
itemOutput->setText(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->tx->vout[out.i].nValue));
|
||||
itemOutput->setToolTip(COLUMN_AMOUNT, BitcoinUnits::format(nDisplayUnit, out.tx->tx->vout[out.i].nValue));
|
||||
itemOutput->setData(COLUMN_AMOUNT, Qt::UserRole, QVariant((qlonglong)out.tx->tx->vout[out.i].nValue)); // padding so that sorting works correctly
|
||||
|
||||
// date
|
||||
itemOutput->setText(COLUMN_DATE, GUIUtil::dateTimeStr(out.tx->GetTxTime()));
|
||||
@ -781,7 +781,7 @@ void CoinControlDialog::updateView()
|
||||
|
||||
|
||||
// PrivateSend rounds
|
||||
COutPoint outpoint = COutPoint(out.tx->GetHash(), out.i);
|
||||
COutPoint outpoint = COutPoint(out.tx->tx->GetHash(), out.i);
|
||||
int nRounds = pwalletMain->GetOutpointPrivateSendRounds(outpoint);
|
||||
|
||||
if (nRounds >= 0 || fDebug) itemOutput->setText(COLUMN_PRIVATESEND_ROUNDS, QString::number(nRounds));
|
||||
|
@ -29,10 +29,10 @@ QString TransactionDesc::FormatTxStatus(const CWalletTx& wtx)
|
||||
AssertLockHeld(cs_main);
|
||||
if (!CheckFinalTx(wtx))
|
||||
{
|
||||
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
|
||||
return tr("Open for %n more block(s)", "", wtx.nLockTime - chainActive.Height());
|
||||
if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
|
||||
return tr("Open for %n more block(s)", "", wtx.tx->nLockTime - chainActive.Height());
|
||||
else
|
||||
return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.nLockTime));
|
||||
return tr("Open until %1").arg(GUIUtil::dateTimeStr(wtx.tx->nLockTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -157,7 +157,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
// Coinbase
|
||||
//
|
||||
CAmount nUnmatured = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
nUnmatured += wallet->GetCredit(txout, ISMINE_ALL);
|
||||
strHTML += "<b>" + tr("Credit") + ":</b> ";
|
||||
if (wtx.IsInMainChain())
|
||||
@ -176,14 +176,14 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
else
|
||||
{
|
||||
isminetype fAllFromMe = ISMINE_SPENDABLE;
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
{
|
||||
isminetype mine = wallet->IsMine(txin);
|
||||
if(fAllFromMe > mine) fAllFromMe = mine;
|
||||
}
|
||||
|
||||
isminetype fAllToMe = ISMINE_SPENDABLE;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
{
|
||||
isminetype mine = wallet->IsMine(txout);
|
||||
if(fAllToMe > mine) fAllToMe = mine;
|
||||
@ -197,7 +197,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
//
|
||||
// Debit
|
||||
//
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
{
|
||||
// Ignore change
|
||||
isminetype toSelf = wallet->IsMine(txout);
|
||||
@ -236,7 +236,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
strHTML += "<b>" + tr("Total credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, nValue) + "<br>";
|
||||
}
|
||||
|
||||
CAmount nTxFee = nDebit - wtx.GetValueOut();
|
||||
CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
|
||||
if (nTxFee > 0)
|
||||
strHTML += "<b>" + tr("Transaction fee") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -nTxFee) + "<br>";
|
||||
}
|
||||
@ -245,10 +245,10 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
//
|
||||
// Mixed debit transaction
|
||||
//
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
if (wallet->IsMine(txin))
|
||||
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
if (wallet->IsMine(txout))
|
||||
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
|
||||
}
|
||||
@ -266,7 +266,7 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
|
||||
strHTML += "<b>" + tr("Transaction ID") + ":</b> " + rec->getTxID() + "<br>";
|
||||
strHTML += "<b>" + tr("Output index") + ":</b> " + QString::number(rec->getOutputIndex()) + "<br>";
|
||||
strHTML += "<b>" + tr("Transaction total size") + ":</b> " + QString::number(wtx.GetTotalSize()) + " bytes<br>";
|
||||
strHTML += "<b>" + tr("Transaction total size") + ":</b> " + QString::number(wtx.tx->GetTotalSize()) + " bytes<br>";
|
||||
|
||||
// Message from normal dash:URI (dash:XyZ...?message=example)
|
||||
Q_FOREACH (const PAIRTYPE(std::string, std::string)& r, wtx.vOrderForm)
|
||||
@ -300,20 +300,20 @@ QString TransactionDesc::toHTML(CWallet *wallet, CWalletTx &wtx, TransactionReco
|
||||
if (fDebug)
|
||||
{
|
||||
strHTML += "<hr><br>" + tr("Debug information") + "<br><br>";
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
if(wallet->IsMine(txin))
|
||||
strHTML += "<b>" + tr("Debit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, -wallet->GetDebit(txin, ISMINE_ALL)) + "<br>";
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
if(wallet->IsMine(txout))
|
||||
strHTML += "<b>" + tr("Credit") + ":</b> " + BitcoinUnits::formatHtmlWithUnit(unit, wallet->GetCredit(txout, ISMINE_ALL)) + "<br>";
|
||||
|
||||
strHTML += "<br><b>" + tr("Transaction") + ":</b><br>";
|
||||
strHTML += GUIUtil::HtmlEscape(wtx.ToString(), true);
|
||||
strHTML += GUIUtil::HtmlEscape(wtx.tx->ToString(), true);
|
||||
|
||||
strHTML += "<br><b>" + tr("Inputs") + ":</b>";
|
||||
strHTML += "<ul>";
|
||||
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
{
|
||||
COutPoint prevout = txin.prevout;
|
||||
|
||||
|
@ -51,7 +51,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||
//
|
||||
// Credit
|
||||
//
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
{
|
||||
isminetype mine = wallet->IsMine(txout);
|
||||
if(mine)
|
||||
@ -89,7 +89,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||
int nFromMe = 0;
|
||||
bool involvesWatchAddress = false;
|
||||
isminetype fAllFromMe = ISMINE_SPENDABLE;
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
{
|
||||
if(wallet->IsMine(txin)) {
|
||||
fAllFromMeDenom = fAllFromMeDenom && wallet->IsDenominated(txin.prevout);
|
||||
@ -103,7 +103,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||
isminetype fAllToMe = ISMINE_SPENDABLE;
|
||||
bool fAllToMeDenom = true;
|
||||
int nToMe = 0;
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout) {
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout) {
|
||||
if(wallet->IsMine(txout)) {
|
||||
fAllToMeDenom = fAllToMeDenom && CPrivateSend::IsDenominatedAmount(txout.nValue);
|
||||
nToMe++;
|
||||
@ -132,7 +132,7 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||
{
|
||||
sub.type = TransactionRecord::PrivateSend;
|
||||
CTxDestination address;
|
||||
if (ExtractDestination(wtx.vout[0].scriptPubKey, address))
|
||||
if (ExtractDestination(wtx.tx->vout[0].scriptPubKey, address))
|
||||
{
|
||||
// Sent to Dash Address
|
||||
sub.address = CBitcoinAddress(address).ToString();
|
||||
@ -145,14 +145,14 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
|
||||
for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++)
|
||||
{
|
||||
const CTxOut& txout = wtx.vout[nOut];
|
||||
const CTxOut& txout = wtx.tx->vout[nOut];
|
||||
sub.idx = parts.size();
|
||||
|
||||
if(CPrivateSend::IsCollateralAmount(txout.nValue)) sub.type = TransactionRecord::PrivateSendMakeCollaterals;
|
||||
if(CPrivateSend::IsDenominatedAmount(txout.nValue)) sub.type = TransactionRecord::PrivateSendCreateDenominations;
|
||||
if(nDebit - wtx.GetValueOut() == CPrivateSend::GetCollateralAmount()) sub.type = TransactionRecord::PrivateSendCollateralPayment;
|
||||
if(nDebit - wtx.tx->GetValueOut() == CPrivateSend::GetCollateralAmount()) sub.type = TransactionRecord::PrivateSendCollateralPayment;
|
||||
}
|
||||
}
|
||||
|
||||
@ -168,11 +168,11 @@ QList<TransactionRecord> TransactionRecord::decomposeTransaction(const CWallet *
|
||||
//
|
||||
// Debit
|
||||
//
|
||||
CAmount nTxFee = nDebit - wtx.GetValueOut();
|
||||
CAmount nTxFee = nDebit - wtx.tx->GetValueOut();
|
||||
|
||||
for (unsigned int nOut = 0; nOut < wtx.vout.size(); nOut++)
|
||||
for (unsigned int nOut = 0; nOut < wtx.tx->vout.size(); nOut++)
|
||||
{
|
||||
const CTxOut& txout = wtx.vout[nOut];
|
||||
const CTxOut& txout = wtx.tx->vout[nOut];
|
||||
TransactionRecord sub(hash, nTime);
|
||||
sub.idx = parts.size();
|
||||
sub.involvesWatchAddress = involvesWatchAddress;
|
||||
@ -252,15 +252,15 @@ void TransactionRecord::updateStatus(const CWalletTx &wtx)
|
||||
|
||||
if (!CheckFinalTx(wtx))
|
||||
{
|
||||
if (wtx.nLockTime < LOCKTIME_THRESHOLD)
|
||||
if (wtx.tx->nLockTime < LOCKTIME_THRESHOLD)
|
||||
{
|
||||
status.status = TransactionStatus::OpenUntilBlock;
|
||||
status.open_for = wtx.nLockTime - chainActive.Height();
|
||||
status.open_for = wtx.tx->nLockTime - chainActive.Height();
|
||||
}
|
||||
else
|
||||
{
|
||||
status.status = TransactionStatus::OpenUntilDate;
|
||||
status.open_for = wtx.nLockTime;
|
||||
status.open_for = wtx.tx->nLockTime;
|
||||
}
|
||||
}
|
||||
// For generated transactions, determine maturity
|
||||
|
@ -80,7 +80,7 @@ CAmount WalletModel::getBalance(const CCoinControl *coinControl) const
|
||||
wallet->AvailableCoins(vCoins, true, coinControl);
|
||||
BOOST_FOREACH(const COutput& out, vCoins)
|
||||
if(out.fSpendable)
|
||||
nBalance += out.tx->vout[out.i].nValue;
|
||||
nBalance += out.tx->tx->vout[out.i].nValue;
|
||||
|
||||
return nBalance;
|
||||
}
|
||||
@ -319,12 +319,12 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
|
||||
transaction.reassignAmounts(nChangePosRet);
|
||||
|
||||
if(recipients[0].fUseInstantSend) {
|
||||
if(newTx->GetValueOut() > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) {
|
||||
if(newTx->tx->GetValueOut() > sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)*COIN) {
|
||||
Q_EMIT message(tr("Send Coins"), tr("InstantSend doesn't support sending values that high yet. Transactions are currently limited to %1 DASH.").arg(sporkManager.GetSporkValue(SPORK_5_INSTANTSEND_MAX_VALUE)),
|
||||
CClientUIInterface::MSG_ERROR);
|
||||
return TransactionCreationFailed;
|
||||
}
|
||||
if(newTx->vin.size() > CTxLockRequest::WARN_MANY_INPUTS) {
|
||||
if(newTx->tx->vin.size() > CTxLockRequest::WARN_MANY_INPUTS) {
|
||||
Q_EMIT message(tr("Send Coins"), tr("Used way too many inputs (>%1) for this InstantSend transaction, fees could be huge.").arg(CTxLockRequest::WARN_MANY_INPUTS),
|
||||
CClientUIInterface::MSG_WARNING);
|
||||
}
|
||||
@ -682,7 +682,7 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
|
||||
int nDepth = wallet->mapWallet[outpoint.hash].GetDepthInMainChain();
|
||||
if (nDepth < 0) continue;
|
||||
COutput out(&wallet->mapWallet[outpoint.hash], outpoint.n, nDepth, true, true);
|
||||
if (outpoint.n < out.tx->vout.size() && wallet->IsMine(out.tx->vout[outpoint.n]) == ISMINE_SPENDABLE)
|
||||
if (outpoint.n < out.tx->tx->vout.size() && wallet->IsMine(out.tx->tx->vout[outpoint.n]) == ISMINE_SPENDABLE)
|
||||
vCoins.push_back(out);
|
||||
}
|
||||
|
||||
@ -690,14 +690,14 @@ void WalletModel::listCoins(std::map<QString, std::vector<COutput> >& mapCoins)
|
||||
{
|
||||
COutput cout = out;
|
||||
|
||||
while (wallet->IsChange(cout.tx->vout[cout.i]) && cout.tx->vin.size() > 0 && wallet->IsMine(cout.tx->vin[0]))
|
||||
while (wallet->IsChange(cout.tx->tx->vout[cout.i]) && cout.tx->tx->vin.size() > 0 && wallet->IsMine(cout.tx->tx->vin[0]))
|
||||
{
|
||||
if (!wallet->mapWallet.count(cout.tx->vin[0].prevout.hash)) break;
|
||||
cout = COutput(&wallet->mapWallet[cout.tx->vin[0].prevout.hash], cout.tx->vin[0].prevout.n, 0, true, true);
|
||||
if (!wallet->mapWallet.count(cout.tx->tx->vin[0].prevout.hash)) break;
|
||||
cout = COutput(&wallet->mapWallet[cout.tx->tx->vin[0].prevout.hash], cout.tx->tx->vin[0].prevout.n, 0, true, true);
|
||||
}
|
||||
|
||||
CTxDestination address;
|
||||
if(!out.fSpendable || !ExtractDestination(cout.tx->vout[cout.i].scriptPubKey, address))
|
||||
if(!out.fSpendable || !ExtractDestination(cout.tx->tx->vout[cout.i].scriptPubKey, address))
|
||||
continue;
|
||||
mapCoins[QString::fromStdString(CBitcoinAddress(address).ToString())].push_back(out);
|
||||
}
|
||||
|
@ -63,7 +63,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
|
||||
if (out.amount() <= 0) continue;
|
||||
if (i == nChangePosRet)
|
||||
i++;
|
||||
subtotal += walletTransaction->vout[i].nValue;
|
||||
subtotal += walletTransaction->tx->vout[i].nValue;
|
||||
i++;
|
||||
}
|
||||
rcp.amount = subtotal;
|
||||
@ -72,7 +72,7 @@ void WalletModelTransaction::reassignAmounts(int nChangePosRet)
|
||||
{
|
||||
if (i == nChangePosRet)
|
||||
i++;
|
||||
rcp.amount = walletTransaction->vout[i].nValue;
|
||||
rcp.amount = walletTransaction->tx->vout[i].nValue;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
@ -366,7 +366,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
|
||||
if (!ParseHashStr(hashStr, hash))
|
||||
return RESTERR(req, HTTP_BAD_REQUEST, "Invalid hash: " + hashStr);
|
||||
|
||||
CTransaction tx;
|
||||
CTransactionRef tx;
|
||||
uint256 hashBlock = uint256();
|
||||
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
|
||||
return RESTERR(req, HTTP_NOT_FOUND, hashStr + " not found");
|
||||
@ -391,7 +391,7 @@ static bool rest_tx(HTTPRequest* req, const std::string& strURIPart)
|
||||
|
||||
case RF_JSON: {
|
||||
UniValue objTx(UniValue::VOBJ);
|
||||
TxToJSON(tx, hashBlock, objTx);
|
||||
TxToJSON(*tx, hashBlock, objTx);
|
||||
string strJSON = objTx.write() + "\n";
|
||||
req->WriteHeader("Content-Type", "application/json");
|
||||
req->WriteReply(HTTP_OK, strJSON);
|
||||
|
@ -230,19 +230,19 @@ UniValue getrawtransaction(const JSONRPCRequest& request)
|
||||
}
|
||||
}
|
||||
|
||||
CTransaction tx;
|
||||
CTransactionRef tx;
|
||||
uint256 hashBlock;
|
||||
if (!GetTransaction(hash, tx, Params().GetConsensus(), hashBlock, true))
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "No information available about transaction");
|
||||
|
||||
string strHex = EncodeHexTx(tx);
|
||||
string strHex = EncodeHexTx(*tx);
|
||||
|
||||
if (!fVerbose)
|
||||
return strHex;
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
result.push_back(Pair("hex", strHex));
|
||||
TxToJSON(tx, hashBlock, result);
|
||||
TxToJSON(*tx, hashBlock, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -307,7 +307,7 @@ UniValue gettxoutproof(const JSONRPCRequest& request)
|
||||
|
||||
if (pblockindex == NULL)
|
||||
{
|
||||
CTransaction tx;
|
||||
CTransactionRef tx;
|
||||
if (!GetTransaction(oneTxid, tx, Params().GetConsensus(), hashBlock, false) || hashBlock.IsNull())
|
||||
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Transaction not yet in block");
|
||||
if (!mapBlockIndex.count(hashBlock))
|
||||
@ -539,13 +539,13 @@ UniValue decoderawtransaction(const JSONRPCRequest& request)
|
||||
LOCK(cs_main);
|
||||
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR));
|
||||
|
||||
CTransaction tx;
|
||||
CMutableTransaction mtx;
|
||||
|
||||
if (!DecodeHexTx(tx, request.params[0].get_str()))
|
||||
if (!DecodeHexTx(mtx, request.params[0].get_str()))
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
||||
|
||||
UniValue result(UniValue::VOBJ);
|
||||
TxToJSON(tx, uint256(), result);
|
||||
TxToJSON(CTransaction(std::move(mtx)), uint256(), result);
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -896,9 +896,10 @@ UniValue sendrawtransaction(const JSONRPCRequest& request)
|
||||
RPCTypeCheck(request.params, boost::assign::list_of(UniValue::VSTR)(UniValue::VBOOL)(UniValue::VBOOL));
|
||||
|
||||
// parse hex string from parameter
|
||||
CTransaction tx;
|
||||
if (!DecodeHexTx(tx, request.params[0].get_str()))
|
||||
CMutableTransaction mtx;
|
||||
if (!DecodeHexTx(mtx, request.params[0].get_str()))
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
||||
CTransaction tx(std::move(mtx));
|
||||
uint256 hashTx = tx.GetHash();
|
||||
|
||||
bool fLimitFree = false;
|
||||
|
@ -76,8 +76,7 @@ int dashconsensus_verify_script(const unsigned char *scriptPubKey, unsigned int
|
||||
{
|
||||
try {
|
||||
TxInputStream stream(SER_NETWORK, PROTOCOL_VERSION, txTo, txToLen);
|
||||
CTransaction tx;
|
||||
stream >> tx;
|
||||
CTransaction tx(deserialize, stream);
|
||||
if (nIn >= tx.vin.size())
|
||||
return set_error(err, dashconsensus_ERR_TX_INDEX);
|
||||
if (GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION) != txToLen)
|
||||
|
@ -114,16 +114,14 @@ BOOST_AUTO_TEST_CASE(bloom_create_insert_key)
|
||||
BOOST_AUTO_TEST_CASE(bloom_match)
|
||||
{
|
||||
// Random real transaction (b4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b)
|
||||
CTransaction tx;
|
||||
CDataStream stream(ParseHex("01000000010b26e9b7735eb6aabdf358bab62f9816a21ba9ebdb719d5299e88607d722c190000000008b4830450220070aca44506c5cef3a16ed519d7c3c39f8aab192c4e1c90d065f37b8a4af6141022100a8e160b856c2d43d27d8fba71e5aef6405b8643ac4cb7cb3c462aced7f14711a0141046d11fee51b0e60666d5049a9101a72741df480b96ee26488a4d3466b95c9a40ac5eeef87e10a5cd336c19a84565f80fa6c547957b7700ff4dfbdefe76036c339ffffffff021bff3d11000000001976a91404943fdd508053c75000106d3bc6e2754dbcff1988ac2f15de00000000001976a914a266436d2965547608b9e15d9032a7b9d64fa43188ac00000000"), SER_DISK, CLIENT_VERSION);
|
||||
stream >> tx;
|
||||
CTransaction tx(deserialize, stream);
|
||||
|
||||
// and one which spends it (e2769b09e784f32f62ef849763d4f45b98e07ba658647343b915ff832b110436)
|
||||
unsigned char ch[] = {0x01, 0x00, 0x00, 0x00, 0x01, 0x6b, 0xff, 0x7f, 0xcd, 0x4f, 0x85, 0x65, 0xef, 0x40, 0x6d, 0xd5, 0xd6, 0x3d, 0x4f, 0xf9, 0x4f, 0x31, 0x8f, 0xe8, 0x20, 0x27, 0xfd, 0x4d, 0xc4, 0x51, 0xb0, 0x44, 0x74, 0x01, 0x9f, 0x74, 0xb4, 0x00, 0x00, 0x00, 0x00, 0x8c, 0x49, 0x30, 0x46, 0x02, 0x21, 0x00, 0xda, 0x0d, 0xc6, 0xae, 0xce, 0xfe, 0x1e, 0x06, 0xef, 0xdf, 0x05, 0x77, 0x37, 0x57, 0xde, 0xb1, 0x68, 0x82, 0x09, 0x30, 0xe3, 0xb0, 0xd0, 0x3f, 0x46, 0xf5, 0xfc, 0xf1, 0x50, 0xbf, 0x99, 0x0c, 0x02, 0x21, 0x00, 0xd2, 0x5b, 0x5c, 0x87, 0x04, 0x00, 0x76, 0xe4, 0xf2, 0x53, 0xf8, 0x26, 0x2e, 0x76, 0x3e, 0x2d, 0xd5, 0x1e, 0x7f, 0xf0, 0xbe, 0x15, 0x77, 0x27, 0xc4, 0xbc, 0x42, 0x80, 0x7f, 0x17, 0xbd, 0x39, 0x01, 0x41, 0x04, 0xe6, 0xc2, 0x6e, 0xf6, 0x7d, 0xc6, 0x10, 0xd2, 0xcd, 0x19, 0x24, 0x84, 0x78, 0x9a, 0x6c, 0xf9, 0xae, 0xa9, 0x93, 0x0b, 0x94, 0x4b, 0x7e, 0x2d, 0xb5, 0x34, 0x2b, 0x9d, 0x9e, 0x5b, 0x9f, 0xf7, 0x9a, 0xff, 0x9a, 0x2e, 0xe1, 0x97, 0x8d, 0xd7, 0xfd, 0x01, 0xdf, 0xc5, 0x22, 0xee, 0x02, 0x28, 0x3d, 0x3b, 0x06, 0xa9, 0xd0, 0x3a, 0xcf, 0x80, 0x96, 0x96, 0x8d, 0x7d, 0xbb, 0x0f, 0x91, 0x78, 0xff, 0xff, 0xff, 0xff, 0x02, 0x8b, 0xa7, 0x94, 0x0e, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xba, 0xde, 0xec, 0xfd, 0xef, 0x05, 0x07, 0x24, 0x7f, 0xc8, 0xf7, 0x42, 0x41, 0xd7, 0x3b, 0xc0, 0x39, 0x97, 0x2d, 0x7b, 0x88, 0xac, 0x40, 0x94, 0xa8, 0x02, 0x00, 0x00, 0x00, 0x00, 0x19, 0x76, 0xa9, 0x14, 0xc1, 0x09, 0x32, 0x48, 0x3f, 0xec, 0x93, 0xed, 0x51, 0xf5, 0xfe, 0x95, 0xe7, 0x25, 0x59, 0xf2, 0xcc, 0x70, 0x43, 0xf9, 0x88, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00};
|
||||
vector<unsigned char> vch(ch, ch + sizeof(ch) -1);
|
||||
CDataStream spendStream(vch, SER_DISK, CLIENT_VERSION);
|
||||
CTransaction spendingTx;
|
||||
spendStream >> spendingTx;
|
||||
CTransaction spendingTx(deserialize, spendStream);
|
||||
|
||||
CBloomFilter filter(10, 0.000001, 0, BLOOM_UPDATE_ALL);
|
||||
filter.insert(uint256S("0xb4749f017444b051c44dfd2720e88f314ff94f3dd6d56d40ef65854fcd7fff6b"));
|
||||
|
@ -240,7 +240,7 @@ class TestBuilder
|
||||
{
|
||||
private:
|
||||
CScript scriptPubKey;
|
||||
CTransaction creditTx;
|
||||
CTransactionRef creditTx;
|
||||
CMutableTransaction spendTx;
|
||||
bool havePush;
|
||||
std::vector<unsigned char> push;
|
||||
@ -267,11 +267,11 @@ public:
|
||||
TestBuilder(const CScript& script_, const std::string& comment_, int flags_, bool P2SH = false) : scriptPubKey(script_), havePush(false), comment(comment_), flags(flags_), scriptError(SCRIPT_ERR_OK)
|
||||
{
|
||||
if (P2SH) {
|
||||
creditTx = BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(script_)) << OP_EQUAL);
|
||||
creditTx = MakeTransactionRef(BuildCreditingTransaction(CScript() << OP_HASH160 << ToByteVector(CScriptID(script_)) << OP_EQUAL));
|
||||
} else {
|
||||
creditTx = BuildCreditingTransaction(script_);
|
||||
creditTx = MakeTransactionRef(BuildCreditingTransaction(script_));
|
||||
}
|
||||
spendTx = BuildSpendingTransaction(CScript(), creditTx);
|
||||
spendTx = BuildSpendingTransaction(CScript(), *creditTx);
|
||||
}
|
||||
|
||||
TestBuilder& ScriptError(ScriptError_t err)
|
||||
@ -359,7 +359,7 @@ public:
|
||||
{
|
||||
TestBuilder copy = *this; // Make a copy so we can rollback the push.
|
||||
DoPush();
|
||||
DoTest(creditTx.vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, comment, scriptError);
|
||||
DoTest(creditTx->vout[0].scriptPubKey, spendTx.vin[0].scriptSig, flags, comment, scriptError);
|
||||
*this = copy;
|
||||
return *this;
|
||||
}
|
||||
@ -369,7 +369,7 @@ public:
|
||||
DoPush();
|
||||
UniValue array(UniValue::VARR);
|
||||
array.push_back(FormatScript(spendTx.vin[0].scriptSig));
|
||||
array.push_back(FormatScript(creditTx.vout[0].scriptPubKey));
|
||||
array.push_back(FormatScript(creditTx->vout[0].scriptPubKey));
|
||||
array.push_back(FormatScriptFlags(flags));
|
||||
array.push_back(FormatScriptError((ScriptError_t)scriptError));
|
||||
array.push_back(comment);
|
||||
@ -383,7 +383,7 @@ public:
|
||||
|
||||
const CScript& GetScriptPubKey()
|
||||
{
|
||||
return creditTx.vout[0].scriptPubKey;
|
||||
return creditTx->vout[0].scriptPubKey;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -21,10 +21,10 @@ protected:
|
||||
bool boolval;
|
||||
std::string stringval;
|
||||
const char* charstrval;
|
||||
CTransaction txval;
|
||||
CTransactionRef txval;
|
||||
public:
|
||||
CSerializeMethodsTestSingle() = default;
|
||||
CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, CTransaction txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), charstrval(charstrvalin), txval(txvalin){}
|
||||
CSerializeMethodsTestSingle(int intvalin, bool boolvalin, std::string stringvalin, const char* charstrvalin, CTransaction txvalin) : intval(intvalin), boolval(boolvalin), stringval(std::move(stringvalin)), charstrval(charstrvalin), txval(MakeTransactionRef(txvalin)){}
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
@ -42,7 +42,7 @@ public:
|
||||
boolval == rhs.boolval && \
|
||||
stringval == rhs.stringval && \
|
||||
strcmp(charstrval, rhs.charstrval) == 0 && \
|
||||
txval == rhs.txval;
|
||||
*txval == *rhs.txval;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -184,7 +184,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
||||
std::string raw_tx, raw_script, sigHashHex;
|
||||
int nIn, nHashType;
|
||||
uint256 sh;
|
||||
CTransaction tx;
|
||||
CTransactionRef tx;
|
||||
CScript scriptCode = CScript();
|
||||
|
||||
try {
|
||||
@ -199,7 +199,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
||||
stream >> tx;
|
||||
|
||||
CValidationState state;
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(*tx, state), strTest);
|
||||
BOOST_CHECK(state.IsValid());
|
||||
|
||||
std::vector<unsigned char> raw = ParseHex(raw_script);
|
||||
@ -209,7 +209,7 @@ BOOST_AUTO_TEST_CASE(sighash_from_data)
|
||||
continue;
|
||||
}
|
||||
|
||||
sh = SignatureHash(scriptCode, tx, nIn, nHashType);
|
||||
sh = SignatureHash(scriptCode, *tx, nIn, nHashType);
|
||||
BOOST_CHECK_MESSAGE(sh.GetHex() == sigHashHex, strTest);
|
||||
}
|
||||
}
|
||||
|
@ -135,8 +135,7 @@ BOOST_AUTO_TEST_CASE(tx_valid)
|
||||
|
||||
string transaction = test[1].get_str();
|
||||
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransaction tx;
|
||||
stream >> tx;
|
||||
CTransaction tx(deserialize, stream);
|
||||
|
||||
CValidationState state;
|
||||
BOOST_CHECK_MESSAGE(CheckTransaction(tx, state), strTest);
|
||||
@ -210,8 +209,7 @@ BOOST_AUTO_TEST_CASE(tx_invalid)
|
||||
|
||||
string transaction = test[1].get_str();
|
||||
CDataStream stream(ParseHex(transaction), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CTransaction tx;
|
||||
stream >> tx;
|
||||
CTransaction tx(deserialize, stream);
|
||||
|
||||
CValidationState state;
|
||||
fValid = CheckTransaction(tx, state) && state.IsValid();
|
||||
|
@ -1096,7 +1096,7 @@ bool GetAddressUnspent(uint160 addressHash, int type,
|
||||
}
|
||||
|
||||
/** Return transaction in txOut, and if it was found inside a block, its hash is placed in hashBlock */
|
||||
bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow)
|
||||
bool GetTransaction(const uint256 &hash, CTransactionRef &txOut, const Consensus::Params& consensusParams, uint256 &hashBlock, bool fAllowSlow)
|
||||
{
|
||||
CBlockIndex *pindexSlow = NULL;
|
||||
|
||||
@ -1105,7 +1105,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::P
|
||||
CTransactionRef ptx = mempool.get(hash);
|
||||
if (ptx)
|
||||
{
|
||||
txOut = *ptx;
|
||||
txOut = ptx;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -1124,7 +1124,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::P
|
||||
return error("%s: Deserialize or I/O error - %s", __func__, e.what());
|
||||
}
|
||||
hashBlock = header.GetHash();
|
||||
if (txOut.GetHash() != hash)
|
||||
if (txOut->GetHash() != hash)
|
||||
return error("%s: txid mismatch", __func__);
|
||||
return true;
|
||||
}
|
||||
@ -1143,7 +1143,7 @@ bool GetTransaction(const uint256 &hash, CTransaction &txOut, const Consensus::P
|
||||
if (ReadBlockFromDisk(block, pindexSlow, consensusParams)) {
|
||||
for (const auto& tx : block.vtx) {
|
||||
if (tx->GetHash() == hash) {
|
||||
txOut = *tx;
|
||||
txOut = tx;
|
||||
hashBlock = pindexSlow->GetBlockHash();
|
||||
return true;
|
||||
}
|
||||
@ -4505,10 +4505,9 @@ bool LoadMempool(void)
|
||||
file >> num;
|
||||
double prioritydummy = 0;
|
||||
while (num--) {
|
||||
CTransaction tx;
|
||||
int64_t nTime;
|
||||
int64_t nFeeDelta;
|
||||
file >> tx;
|
||||
CTransaction tx(deserialize, file);
|
||||
file >> nTime;
|
||||
file >> nFeeDelta;
|
||||
|
||||
|
@ -285,7 +285,7 @@ bool IsInitialBlockDownload();
|
||||
*/
|
||||
std::string GetWarnings(const std::string& strFor);
|
||||
/** Retrieve a transaction (from memory pool, or from disk, if possible) */
|
||||
bool GetTransaction(const uint256 &hash, CTransaction &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false);
|
||||
bool GetTransaction(const uint256 &hash, CTransactionRef &tx, const Consensus::Params& params, uint256 &hashBlock, bool fAllowSlow = false);
|
||||
/** Find the best known block, and make it the tip of the block chain */
|
||||
bool ActivateBestChain(CValidationState& state, const CChainParams& chainparams, const CBlock* pblock = NULL);
|
||||
|
||||
|
@ -268,11 +268,11 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
|
||||
"2. \"txoutproof\" (string, required) The hex output from gettxoutproof that contains the transaction\n"
|
||||
);
|
||||
|
||||
CTransaction tx;
|
||||
CMutableTransaction tx;
|
||||
if (!DecodeHexTx(tx, request.params[0].get_str()))
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
||||
uint256 hashTx = tx.GetHash();
|
||||
CWalletTx wtx(pwalletMain,tx);
|
||||
CWalletTx wtx(pwalletMain, MakeTransactionRef(std::move(tx)));
|
||||
|
||||
CDataStream ssMB(ParseHexV(request.params[1], "proof"), SER_NETWORK, PROTOCOL_VERSION);
|
||||
CMerkleBlock merkleBlock;
|
||||
@ -305,7 +305,7 @@ UniValue importprunedfunds(const JSONRPCRequest& request)
|
||||
|
||||
LOCK2(cs_main, pwalletMain->cs_wallet);
|
||||
|
||||
if (pwalletMain->IsMine(tx)) {
|
||||
if (pwalletMain->IsMine(wtx)) {
|
||||
pwalletMain->AddToWallet(wtx, false);
|
||||
return NullUniValue;
|
||||
}
|
||||
|
@ -658,10 +658,10 @@ UniValue getreceivedbyaddress(const JSONRPCRequest& request)
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
|
||||
continue;
|
||||
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
if (txout.scriptPubKey == scriptPubKey)
|
||||
if (wtx.GetDepthInMainChain(fAddLockConf) >= nMinDepth)
|
||||
nAmount += txout.nValue;
|
||||
@ -714,10 +714,10 @@ UniValue getreceivedbyaccount(const JSONRPCRequest& request)
|
||||
for (map<uint256, CWalletTx>::iterator it = pwalletMain->mapWallet.begin(); it != pwalletMain->mapWallet.end(); ++it)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
|
||||
continue;
|
||||
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
{
|
||||
CTxDestination address;
|
||||
if (ExtractDestination(txout.scriptPubKey, address) && IsMine(*pwalletMain, address) && setAddress.count(address))
|
||||
@ -1153,14 +1153,14 @@ UniValue ListReceived(const UniValue& params, bool fByAccounts)
|
||||
{
|
||||
const CWalletTx& wtx = (*it).second;
|
||||
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(wtx))
|
||||
if (wtx.IsCoinBase() || !CheckFinalTx(*wtx.tx))
|
||||
continue;
|
||||
|
||||
int nDepth = wtx.GetDepthInMainChain(fAddLockConf);
|
||||
if (nDepth < nMinDepth)
|
||||
continue;
|
||||
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, wtx.tx->vout)
|
||||
{
|
||||
CTxDestination address;
|
||||
if (!ExtractDestination(txout.scriptPubKey, address))
|
||||
@ -1800,7 +1800,7 @@ UniValue gettransaction(const JSONRPCRequest& request)
|
||||
CAmount nCredit = wtx.GetCredit(filter);
|
||||
CAmount nDebit = wtx.GetDebit(filter);
|
||||
CAmount nNet = nCredit - nDebit;
|
||||
CAmount nFee = (wtx.IsFromMe(filter) ? wtx.GetValueOut() - nDebit : 0);
|
||||
CAmount nFee = (wtx.IsFromMe(filter) ? wtx.tx->GetValueOut() - nDebit : 0);
|
||||
|
||||
entry.push_back(Pair("amount", ValueFromAmount(nNet - nFee)));
|
||||
if (wtx.IsFromMe(filter))
|
||||
@ -2531,7 +2531,7 @@ UniValue listunspent(const JSONRPCRequest& request)
|
||||
continue;
|
||||
|
||||
CTxDestination address;
|
||||
const CScript& scriptPubKey = out.tx->vout[out.i].scriptPubKey;
|
||||
const CScript& scriptPubKey = out.tx->tx->vout[out.i].scriptPubKey;
|
||||
bool fValidAddress = ExtractDestination(scriptPubKey, address);
|
||||
|
||||
if (setAddress.size() && (!fValidAddress || !setAddress.count(address)))
|
||||
@ -2556,7 +2556,7 @@ UniValue listunspent(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
entry.push_back(Pair("scriptPubKey", HexStr(scriptPubKey.begin(), scriptPubKey.end())));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(out.tx->vout[out.i].nValue)));
|
||||
entry.push_back(Pair("amount", ValueFromAmount(out.tx->tx->vout[out.i].nValue)));
|
||||
entry.push_back(Pair("confirmations", out.nDepth));
|
||||
entry.push_back(Pair("spendable", out.fSpendable));
|
||||
entry.push_back(Pair("solvable", out.fSolvable));
|
||||
@ -2669,17 +2669,16 @@ UniValue fundrawtransaction(const JSONRPCRequest& request)
|
||||
}
|
||||
|
||||
// parse hex string from parameter
|
||||
CTransaction origTx;
|
||||
if (!DecodeHexTx(origTx, request.params[0].get_str()))
|
||||
CMutableTransaction tx;
|
||||
if (!DecodeHexTx(tx, request.params[0].get_str()))
|
||||
throw JSONRPCError(RPC_DESERIALIZATION_ERROR, "TX decode failed");
|
||||
|
||||
if (origTx.vout.size() == 0)
|
||||
if (tx.vout.size() == 0)
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "TX must have at least one output");
|
||||
|
||||
if (changePosition != -1 && (changePosition < 0 || (unsigned int)changePosition > origTx.vout.size()))
|
||||
if (changePosition != -1 && (changePosition < 0 || (unsigned int)changePosition > tx.vout.size()))
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "changePosition out of bounds");
|
||||
|
||||
CMutableTransaction tx(origTx);
|
||||
CAmount nFeeOut;
|
||||
string strFailReason;
|
||||
|
||||
|
@ -86,7 +86,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
|
||||
{
|
||||
CMutableTransaction tx(wtx);
|
||||
--tx.nLockTime; // Just to change the hash :)
|
||||
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
|
||||
wtx.SetTx(MakeTransactionRef(std::move(tx)));
|
||||
}
|
||||
pwalletMain->AddToWallet(wtx);
|
||||
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
||||
@ -96,7 +96,7 @@ BOOST_AUTO_TEST_CASE(acc_orderupgrade)
|
||||
{
|
||||
CMutableTransaction tx(wtx);
|
||||
--tx.nLockTime; // Just to change the hash :)
|
||||
*static_cast<CTransaction*>(&wtx) = CTransaction(tx);
|
||||
wtx.SetTx(MakeTransactionRef(std::move(tx)));
|
||||
}
|
||||
pwalletMain->AddToWallet(wtx);
|
||||
vpwtx.push_back(&pwalletMain->mapWallet[wtx.GetHash()]);
|
||||
|
@ -42,7 +42,7 @@ static void add_coin(const CAmount& nValue, int nAge = 6*24, bool fIsFromMe = fa
|
||||
// so stop vin being empty, and cache a non-zero Debit to fake out IsFromMe()
|
||||
tx.vin.resize(1);
|
||||
}
|
||||
CWalletTx* wtx = new CWalletTx(&wallet, tx);
|
||||
CWalletTx* wtx = new CWalletTx(&wallet, MakeTransactionRef(std::move(tx)));
|
||||
if (fIsFromMe)
|
||||
{
|
||||
wtx->fDebitCached = true;
|
||||
|
@ -81,17 +81,17 @@ struct CompareValueOnly
|
||||
|
||||
std::string COutput::ToString() const
|
||||
{
|
||||
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->vout[i].nValue));
|
||||
return strprintf("COutput(%s, %d, %d) [%s]", tx->GetHash().ToString(), i, nDepth, FormatMoney(tx->tx->vout[i].nValue));
|
||||
}
|
||||
|
||||
int COutput::Priority() const
|
||||
{
|
||||
BOOST_FOREACH(CAmount d, CPrivateSend::GetStandardDenominations())
|
||||
if(tx->vout[i].nValue == d) return 10000;
|
||||
if(tx->vout[i].nValue < 1*COIN) return 20000;
|
||||
if(tx->tx->vout[i].nValue == d) return 10000;
|
||||
if(tx->tx->vout[i].nValue < 1*COIN) return 20000;
|
||||
|
||||
//nondenom return largest first
|
||||
return -(tx->vout[i].nValue/COIN);
|
||||
return -(tx->tx->vout[i].nValue/COIN);
|
||||
}
|
||||
|
||||
const CWalletTx* CWallet::GetWalletTx(const uint256& hash) const
|
||||
@ -578,7 +578,7 @@ set<uint256> CWallet::GetConflicts(const uint256& txid) const
|
||||
|
||||
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range;
|
||||
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
{
|
||||
if (mapTxSpends.count(txin.prevout) <= 1)
|
||||
continue; // No conflict if zero or one spends
|
||||
@ -731,7 +731,7 @@ void CWallet::AddToSpends(const uint256& wtxid)
|
||||
if (thisTx.IsCoinBase()) // Coinbases don't spend anything!
|
||||
return;
|
||||
|
||||
BOOST_FOREACH(const CTxIn& txin, thisTx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, thisTx.tx->vin)
|
||||
AddToSpends(txin.prevout, wtxid);
|
||||
}
|
||||
|
||||
@ -1005,7 +1005,7 @@ bool CWallet::GetAccountPubkey(CPubKey &pubKey, std::string strAccount, bool bFo
|
||||
for (map<uint256, CWalletTx>::iterator it = mapWallet.begin();
|
||||
it != mapWallet.end() && account.vchPubKey.IsValid();
|
||||
++it)
|
||||
BOOST_FOREACH(const CTxOut& txout, (*it).second.vout)
|
||||
BOOST_FOREACH(const CTxOut& txout, (*it).second.tx->vout)
|
||||
if (txout.scriptPubKey == scriptPubKey) {
|
||||
bForceNew = true;
|
||||
break;
|
||||
@ -1103,8 +1103,8 @@ bool CWallet::AddToWallet(const CWalletTx& wtxIn, bool fFlushOnClose)
|
||||
wtxIn.hashBlock.ToString());
|
||||
}
|
||||
AddToSpends(hash);
|
||||
for(int i = 0; i < wtx.vout.size(); ++i) {
|
||||
if (IsMine(wtx.vout[i]) && !IsSpent(hash, i)) {
|
||||
for(int i = 0; i < wtx.tx->vout.size(); ++i) {
|
||||
if (IsMine(wtx.tx->vout[i]) && !IsSpent(hash, i)) {
|
||||
setWalletUTXO.insert(COutPoint(hash, i));
|
||||
}
|
||||
}
|
||||
@ -1175,7 +1175,7 @@ bool CWallet::LoadToWallet(const CWalletTx& wtxIn)
|
||||
wtx.BindWallet(this);
|
||||
wtxOrdered.insert(make_pair(wtx.nOrderPos, TxPair(&wtx, (CAccountingEntry*)0)));
|
||||
AddToSpends(hash);
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin) {
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin) {
|
||||
if (mapWallet.count(txin.prevout.hash)) {
|
||||
CWalletTx& prevtx = mapWallet[txin.prevout.hash];
|
||||
if (prevtx.nIndex == -1 && !prevtx.hashUnset()) {
|
||||
@ -1214,7 +1214,7 @@ bool CWallet::AddToWalletIfInvolvingMe(const CTransaction& tx, const CBlockIndex
|
||||
if (fExisted && !fUpdate) return false;
|
||||
if (fExisted || IsMine(tx) || IsFromMe(tx))
|
||||
{
|
||||
CWalletTx wtx(this,tx);
|
||||
CWalletTx wtx(this, MakeTransactionRef(tx));
|
||||
|
||||
// Get merkle branch if transaction was found in a block
|
||||
if (posInBlock != -1)
|
||||
@ -1273,7 +1273,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx)
|
||||
}
|
||||
// If a transaction changes 'conflicted' state, that changes the balance
|
||||
// available of the outputs it spends. So force those to be recomputed
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
{
|
||||
if (mapWallet.count(txin.prevout.hash))
|
||||
mapWallet[txin.prevout.hash].MarkDirty();
|
||||
@ -1337,7 +1337,7 @@ void CWallet::MarkConflicted(const uint256& hashBlock, const uint256& hashTx)
|
||||
}
|
||||
// If a transaction changes 'conflicted' state, that changes the balance
|
||||
// available of the outputs it spends. So force those to be recomputed
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
{
|
||||
if (mapWallet.count(txin.prevout.hash))
|
||||
mapWallet[txin.prevout.hash].MarkDirty();
|
||||
@ -1378,8 +1378,8 @@ isminetype CWallet::IsMine(const CTxIn &txin) const
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
if (txin.prevout.n < prev.vout.size())
|
||||
return IsMine(prev.vout[txin.prevout.n]);
|
||||
if (txin.prevout.n < prev.tx->vout.size())
|
||||
return IsMine(prev.tx->vout[txin.prevout.n]);
|
||||
}
|
||||
}
|
||||
return ISMINE_NO;
|
||||
@ -1393,9 +1393,9 @@ CAmount CWallet::GetDebit(const CTxIn &txin, const isminefilter& filter) const
|
||||
if (mi != mapWallet.end())
|
||||
{
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
if (txin.prevout.n < prev.vout.size())
|
||||
if (IsMine(prev.vout[txin.prevout.n]) & filter)
|
||||
return prev.vout[txin.prevout.n].nValue;
|
||||
if (txin.prevout.n < prev.tx->vout.size())
|
||||
if (IsMine(prev.tx->vout[txin.prevout.n]) & filter)
|
||||
return prev.tx->vout[txin.prevout.n].nValue;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
@ -1426,27 +1426,27 @@ int CWallet::GetRealOutpointPrivateSendRounds(const COutPoint& outpoint, int nRo
|
||||
|
||||
|
||||
// bounds check
|
||||
if (nout >= wtx->vout.size()) {
|
||||
if (nout >= wtx->tx->vout.size()) {
|
||||
// should never actually hit this
|
||||
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, -4);
|
||||
return -4;
|
||||
}
|
||||
|
||||
if (CPrivateSend::IsCollateralAmount(wtx->vout[nout].nValue)) {
|
||||
if (CPrivateSend::IsCollateralAmount(wtx->tx->vout[nout].nValue)) {
|
||||
mDenomWtxes[hash].vout[nout].nRounds = -3;
|
||||
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
|
||||
return mDenomWtxes[hash].vout[nout].nRounds;
|
||||
}
|
||||
|
||||
//make sure the final output is non-denominate
|
||||
if (!CPrivateSend::IsDenominatedAmount(wtx->vout[nout].nValue)) { //NOT DENOM
|
||||
if (!CPrivateSend::IsDenominatedAmount(wtx->tx->vout[nout].nValue)) { //NOT DENOM
|
||||
mDenomWtxes[hash].vout[nout].nRounds = -2;
|
||||
LogPrint("privatesend", "GetRealOutpointPrivateSendRounds UPDATED %s %3d %3d\n", hash.ToString(), nout, mDenomWtxes[hash].vout[nout].nRounds);
|
||||
return mDenomWtxes[hash].vout[nout].nRounds;
|
||||
}
|
||||
|
||||
bool fAllDenoms = true;
|
||||
BOOST_FOREACH(CTxOut out, wtx->vout) {
|
||||
BOOST_FOREACH(CTxOut out, wtx->tx->vout) {
|
||||
fAllDenoms = fAllDenoms && CPrivateSend::IsDenominatedAmount(out.nValue);
|
||||
}
|
||||
|
||||
@ -1460,7 +1460,7 @@ int CWallet::GetRealOutpointPrivateSendRounds(const COutPoint& outpoint, int nRo
|
||||
int nShortest = -10; // an initial value, should be no way to get this by calculations
|
||||
bool fDenomFound = false;
|
||||
// only denoms here so let's look up
|
||||
BOOST_FOREACH(CTxIn txinNext, wtx->vin) {
|
||||
BOOST_FOREACH(CTxIn txinNext, wtx->tx->vin) {
|
||||
if (IsMine(txinNext)) {
|
||||
int n = GetRealOutpointPrivateSendRounds(txinNext.prevout, nRounds + 1);
|
||||
// denom found, find the shortest chain or initially assign nShortest with the first found value
|
||||
@ -1495,8 +1495,8 @@ bool CWallet::IsDenominated(const COutPoint& outpoint) const
|
||||
map<uint256, CWalletTx>::const_iterator mi = mapWallet.find(outpoint.hash);
|
||||
if (mi != mapWallet.end()) {
|
||||
const CWalletTx& prev = (*mi).second;
|
||||
if (outpoint.n < prev.vout.size()) {
|
||||
return CPrivateSend::IsDenominatedAmount(prev.vout[outpoint.n].nValue);
|
||||
if (outpoint.n < prev.tx->vout.size()) {
|
||||
return CPrivateSend::IsDenominatedAmount(prev.tx->vout[outpoint.n].nValue);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1749,14 +1749,14 @@ void CWalletTx::GetAmounts(list<COutputEntry>& listReceived,
|
||||
CAmount nDebit = GetDebit(filter);
|
||||
if (nDebit > 0) // debit>0 means we signed/sent this transaction
|
||||
{
|
||||
CAmount nValueOut = GetValueOut();
|
||||
CAmount nValueOut = tx->GetValueOut();
|
||||
nFee = nDebit - nValueOut;
|
||||
}
|
||||
|
||||
// Sent/received.
|
||||
for (unsigned int i = 0; i < vout.size(); ++i)
|
||||
for (unsigned int i = 0; i < tx->vout.size(); ++i)
|
||||
{
|
||||
const CTxOut& txout = vout[i];
|
||||
const CTxOut& txout = tx->vout[i];
|
||||
isminetype fIsMine = pwallet->IsMine(txout);
|
||||
// Only need to handle txouts if AT LEAST one of these is true:
|
||||
// 1) they debit from us (sent)
|
||||
@ -1943,7 +1943,7 @@ set<uint256> CWalletTx::GetConflicts() const
|
||||
|
||||
CAmount CWalletTx::GetDebit(const isminefilter& filter) const
|
||||
{
|
||||
if (vin.empty())
|
||||
if (tx->vin.empty())
|
||||
return 0;
|
||||
|
||||
CAmount debit = 0;
|
||||
@ -2033,11 +2033,11 @@ CAmount CWalletTx::GetAvailableCredit(bool fUseCache) const
|
||||
|
||||
CAmount nCredit = 0;
|
||||
uint256 hashTx = GetHash();
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
for (unsigned int i = 0; i < tx->vout.size(); i++)
|
||||
{
|
||||
if (!pwallet->IsSpent(hashTx, i))
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
const CTxOut &txout = tx->vout[i];
|
||||
nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
||||
@ -2076,11 +2076,11 @@ CAmount CWalletTx::GetAvailableWatchOnlyCredit(const bool& fUseCache) const
|
||||
return nAvailableWatchCreditCached;
|
||||
|
||||
CAmount nCredit = 0;
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
for (unsigned int i = 0; i < tx->vout.size(); i++)
|
||||
{
|
||||
if (!pwallet->IsSpent(GetHash(), i))
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
const CTxOut &txout = tx->vout[i];
|
||||
nCredit += pwallet->GetCredit(txout, ISMINE_WATCH_ONLY);
|
||||
if (!MoneyRange(nCredit))
|
||||
throw std::runtime_error(std::string(__func__) + ": value out of range");
|
||||
@ -2106,9 +2106,9 @@ CAmount CWalletTx::GetAnonymizedCredit(bool fUseCache) const
|
||||
|
||||
CAmount nCredit = 0;
|
||||
uint256 hashTx = GetHash();
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
for (unsigned int i = 0; i < tx->vout.size(); i++)
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
const CTxOut &txout = tx->vout[i];
|
||||
const COutPoint outpoint = COutPoint(hashTx, i);
|
||||
|
||||
if(pwallet->IsSpent(hashTx, i) || !pwallet->IsDenominated(outpoint)) continue;
|
||||
@ -2150,11 +2150,11 @@ CAmount CWalletTx::GetDenominatedCredit(bool unconfirmed, bool fUseCache) const
|
||||
|
||||
CAmount nCredit = 0;
|
||||
uint256 hashTx = GetHash();
|
||||
for (unsigned int i = 0; i < vout.size(); i++)
|
||||
for (unsigned int i = 0; i < tx->vout.size(); i++)
|
||||
{
|
||||
const CTxOut &txout = vout[i];
|
||||
const CTxOut &txout = tx->vout[i];
|
||||
|
||||
if(pwallet->IsSpent(hashTx, i) || !CPrivateSend::IsDenominatedAmount(vout[i].nValue)) continue;
|
||||
if(pwallet->IsSpent(hashTx, i) || !CPrivateSend::IsDenominatedAmount(tx->vout[i].nValue)) continue;
|
||||
|
||||
nCredit += pwallet->GetCredit(txout, ISMINE_SPENDABLE);
|
||||
if (!MoneyRange(nCredit))
|
||||
@ -2207,23 +2207,23 @@ bool CWalletTx::IsTrusted() const
|
||||
return false;
|
||||
|
||||
// Trusted if all inputs are from us and are in the mempool:
|
||||
BOOST_FOREACH(const CTxIn& txin, vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, tx->vin)
|
||||
{
|
||||
// Transactions not sent by us: not trusted
|
||||
const CWalletTx* parent = pwallet->GetWalletTx(txin.prevout.hash);
|
||||
if (parent == NULL)
|
||||
return false;
|
||||
const CTxOut& parentOut = parent->vout[txin.prevout.n];
|
||||
const CTxOut& parentOut = parent->tx->vout[txin.prevout.n];
|
||||
if (pwallet->IsMine(parentOut) != ISMINE_SPENDABLE)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWalletTx::IsEquivalentTo(const CWalletTx& tx) const
|
||||
bool CWalletTx::IsEquivalentTo(const CWalletTx& _tx) const
|
||||
{
|
||||
CMutableTransaction tx1 = *this;
|
||||
CMutableTransaction tx2 = tx;
|
||||
CMutableTransaction tx1 = *this->tx;
|
||||
CMutableTransaction tx2 = *_tx.tx;
|
||||
for (unsigned int i = 0; i < tx1.vin.size(); i++) tx1.vin[i].scriptSig = CScript();
|
||||
for (unsigned int i = 0; i < tx2.vin.size(); i++) tx2.vin[i].scriptSig = CScript();
|
||||
return CTransaction(tx1) == CTransaction(tx2);
|
||||
@ -2386,7 +2386,7 @@ CAmount CWallet::GetNormalizedAnonymizedBalance() const
|
||||
if (it->second.GetDepthInMainChain() < 0) continue;
|
||||
|
||||
int nRounds = GetOutpointPrivateSendRounds(outpoint);
|
||||
nTotal += it->second.vout[outpoint.n].nValue * nRounds / privateSendClient.nPrivateSendRounds;
|
||||
nTotal += it->second.tx->vout[outpoint.n].nValue * nRounds / privateSendClient.nPrivateSendRounds;
|
||||
}
|
||||
|
||||
return nTotal;
|
||||
@ -2543,26 +2543,26 @@ void CWallet::AvailableCoins(vector<COutput>& vCoins, bool fOnlyConfirmed, const
|
||||
if (nDepth == 0 && !pcoin->InMempool())
|
||||
continue;
|
||||
|
||||
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
|
||||
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
|
||||
bool found = false;
|
||||
if(nCoinType == ONLY_DENOMINATED) {
|
||||
found = CPrivateSend::IsDenominatedAmount(pcoin->vout[i].nValue);
|
||||
found = CPrivateSend::IsDenominatedAmount(pcoin->tx->vout[i].nValue);
|
||||
} else if(nCoinType == ONLY_NONDENOMINATED) {
|
||||
if (CPrivateSend::IsCollateralAmount(pcoin->vout[i].nValue)) continue; // do not use collateral amounts
|
||||
found = !CPrivateSend::IsDenominatedAmount(pcoin->vout[i].nValue);
|
||||
if (CPrivateSend::IsCollateralAmount(pcoin->tx->vout[i].nValue)) continue; // do not use collateral amounts
|
||||
found = !CPrivateSend::IsDenominatedAmount(pcoin->tx->vout[i].nValue);
|
||||
} else if(nCoinType == ONLY_1000) {
|
||||
found = pcoin->vout[i].nValue == 1000*COIN;
|
||||
found = pcoin->tx->vout[i].nValue == 1000*COIN;
|
||||
} else if(nCoinType == ONLY_PRIVATESEND_COLLATERAL) {
|
||||
found = CPrivateSend::IsCollateralAmount(pcoin->vout[i].nValue);
|
||||
found = CPrivateSend::IsCollateralAmount(pcoin->tx->vout[i].nValue);
|
||||
} else {
|
||||
found = true;
|
||||
}
|
||||
if(!found) continue;
|
||||
|
||||
isminetype mine = IsMine(pcoin->vout[i]);
|
||||
isminetype mine = IsMine(pcoin->tx->vout[i]);
|
||||
if (!(IsSpent(wtxid, i)) && mine != ISMINE_NO &&
|
||||
(!IsLockedCoin((*it).first, i) || nCoinType == ONLY_1000) &&
|
||||
(pcoin->vout[i].nValue > 0 || fIncludeZeroValue) &&
|
||||
(pcoin->tx->vout[i].nValue > 0 || fIncludeZeroValue) &&
|
||||
(!coinControl || !coinControl->HasSelected() || coinControl->fAllowOtherInputs || coinControl->IsSelected(COutPoint((*it).first, i))))
|
||||
vCoins.push_back(COutput(pcoin, i, nDepth,
|
||||
((mine & ISMINE_SPENDABLE) != ISMINE_NO) ||
|
||||
@ -2632,8 +2632,8 @@ bool less_then_denom (const COutput& out1, const COutput& out2)
|
||||
bool found2 = false;
|
||||
BOOST_FOREACH(CAmount d, CPrivateSend::GetStandardDenominations()) // loop through predefined denoms
|
||||
{
|
||||
if(pcoin1->vout[out1.i].nValue == d) found1 = true;
|
||||
if(pcoin2->vout[out2.i].nValue == d) found2 = true;
|
||||
if(pcoin1->tx->vout[out1.i].nValue == d) found1 = true;
|
||||
if(pcoin2->tx->vout[out2.i].nValue == d) found2 = true;
|
||||
}
|
||||
return (!found1 && found2);
|
||||
}
|
||||
@ -2676,7 +2676,7 @@ bool CWallet::SelectCoinsMinConf(const CAmount& nTargetValue, int nConfMine, int
|
||||
continue;
|
||||
|
||||
int i = output.i;
|
||||
CAmount n = pcoin->vout[i].nValue;
|
||||
CAmount n = pcoin->tx->vout[i].nValue;
|
||||
if (tryDenom == 0 && CPrivateSend::IsDenominatedAmount(n)) continue; // we don't want denom values on first run
|
||||
|
||||
pair<CAmount,pair<const CWalletTx*,unsigned int> > coin = make_pair(n,make_pair(pcoin, i));
|
||||
@ -2784,7 +2784,7 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
|
||||
// make sure it's actually anonymized
|
||||
if(nRounds < privateSendClient.nPrivateSendRounds) continue;
|
||||
}
|
||||
nValueRet += out.tx->vout[out.i].nValue;
|
||||
nValueRet += out.tx->tx->vout[out.i].nValue;
|
||||
setCoinsRet.insert(make_pair(out.tx, out.i));
|
||||
}
|
||||
|
||||
@ -2801,7 +2801,7 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
|
||||
BOOST_FOREACH(const COutput& out, vCoins)
|
||||
{
|
||||
//make sure it's the denom we're looking for, round the amount up to smallest denom
|
||||
if(out.tx->vout[out.i].nValue == nDenom && nValueRet + nDenom < nTargetValue + nSmallestDenom) {
|
||||
if(out.tx->tx->vout[out.i].nValue == nDenom && nValueRet + nDenom < nTargetValue + nSmallestDenom) {
|
||||
COutPoint outpoint = COutPoint(out.tx->GetHash(),out.i);
|
||||
int nRounds = GetOutpointPrivateSendRounds(outpoint);
|
||||
// make sure it's actually anonymized
|
||||
@ -2827,9 +2827,9 @@ bool CWallet::SelectCoins(const vector<COutput>& vAvailableCoins, const CAmount&
|
||||
{
|
||||
const CWalletTx* pcoin = &it->second;
|
||||
// Clearly invalid input, fail
|
||||
if (pcoin->vout.size() <= outpoint.n)
|
||||
if (pcoin->tx->vout.size() <= outpoint.n)
|
||||
return false;
|
||||
nValueFromPresetInputs += pcoin->vout[outpoint.n].nValue;
|
||||
nValueFromPresetInputs += pcoin->tx->vout[outpoint.n].nValue;
|
||||
setPresetCoins.insert(make_pair(pcoin, outpoint.n));
|
||||
} else
|
||||
return false; // TODO: Allow non-wallet inputs
|
||||
@ -2894,10 +2894,10 @@ bool CWallet::FundTransaction(CMutableTransaction& tx, CAmount& nFeeRet, bool ov
|
||||
return false;
|
||||
|
||||
if (nChangePosInOut != -1)
|
||||
tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.vout[nChangePosInOut]);
|
||||
tx.vout.insert(tx.vout.begin() + nChangePosInOut, wtx.tx->vout[nChangePosInOut]);
|
||||
|
||||
// Add new txins (keeping original txin scriptSig/order)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtx.tx->vin)
|
||||
{
|
||||
if (!coinControl.IsSelected(txin.prevout))
|
||||
{
|
||||
@ -2944,7 +2944,7 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
|
||||
{
|
||||
// masternode-like input should not be selected by AvailableCoins now anyway
|
||||
//if(out.tx->vout[out.i].nValue == 1000*COIN) continue;
|
||||
if(nValueRet + out.tx->vout[out.i].nValue <= nValueMax){
|
||||
if(nValueRet + out.tx->tx->vout[out.i].nValue <= nValueMax){
|
||||
|
||||
CTxIn txin = CTxIn(out.tx->GetHash(), out.i);
|
||||
|
||||
@ -2953,7 +2953,7 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
|
||||
if(nRounds < nPrivateSendRoundsMin) continue;
|
||||
|
||||
BOOST_FOREACH(int nBit, vecBits) {
|
||||
if(out.tx->vout[out.i].nValue == vecPrivateSendDenominations[nBit]) {
|
||||
if(out.tx->tx->vout[out.i].nValue == vecPrivateSendDenominations[nBit]) {
|
||||
if(nValueRet >= nValueMin) {
|
||||
//randomly reduce the max amount we'll submit (for anonymity)
|
||||
nValueMax -= insecure_rand.rand32(nValueMax/5);
|
||||
@ -2961,8 +2961,8 @@ bool CWallet::SelectCoinsByDenominations(int nDenom, CAmount nValueMin, CAmount
|
||||
int r = insecure_rand.rand32(vCoins.size());
|
||||
if((int)vecTxDSInRet.size() > r) return true;
|
||||
}
|
||||
nValueRet += out.tx->vout[out.i].nValue;
|
||||
vecTxDSInRet.push_back(CTxDSIn(txin, out.tx->vout[out.i].scriptPubKey));
|
||||
nValueRet += out.tx->tx->vout[out.i].nValue;
|
||||
vecTxDSInRet.push_back(CTxDSIn(txin, out.tx->tx->vout[out.i].scriptPubKey));
|
||||
vCoinsRet.push_back(out);
|
||||
nDenomResult |= 1 << nBit;
|
||||
}
|
||||
@ -3020,31 +3020,31 @@ bool CWallet::SelectCoinsGrouppedByAddresses(std::vector<CompactTallyItem>& vecT
|
||||
if(wtx.IsCoinBase() && wtx.GetBlocksToMaturity() > 0) continue;
|
||||
if(fSkipUnconfirmed && !wtx.IsTrusted()) continue;
|
||||
|
||||
for (unsigned int i = 0; i < wtx.vout.size(); i++) {
|
||||
for (unsigned int i = 0; i < wtx.tx->vout.size(); i++) {
|
||||
CTxDestination txdest;
|
||||
if (!ExtractDestination(wtx.vout[i].scriptPubKey, txdest)) continue;
|
||||
if (!ExtractDestination(wtx.tx->vout[i].scriptPubKey, txdest)) continue;
|
||||
|
||||
isminefilter mine = ::IsMine(*this, txdest);
|
||||
if(!(mine & filter)) continue;
|
||||
|
||||
if(IsSpent(outpoint.hash, i) || IsLockedCoin(outpoint.hash, i)) continue;
|
||||
|
||||
if(fSkipDenominated && CPrivateSend::IsDenominatedAmount(wtx.vout[i].nValue)) continue;
|
||||
if(fSkipDenominated && CPrivateSend::IsDenominatedAmount(wtx.tx->vout[i].nValue)) continue;
|
||||
|
||||
if(fAnonymizable) {
|
||||
// ignore collaterals
|
||||
if(CPrivateSend::IsCollateralAmount(wtx.vout[i].nValue)) continue;
|
||||
if(fMasterNode && wtx.vout[i].nValue == 1000*COIN) continue;
|
||||
if(CPrivateSend::IsCollateralAmount(wtx.tx->vout[i].nValue)) continue;
|
||||
if(fMasterNode && wtx.tx->vout[i].nValue == 1000*COIN) continue;
|
||||
// ignore outputs that are 10 times smaller then the smallest denomination
|
||||
// otherwise they will just lead to higher fee / lower priority
|
||||
if(wtx.vout[i].nValue <= nSmallestDenom/10) continue;
|
||||
if(wtx.tx->vout[i].nValue <= nSmallestDenom/10) continue;
|
||||
// ignore anonymized
|
||||
if(GetOutpointPrivateSendRounds(COutPoint(outpoint.hash, i)) >= privateSendClient.nPrivateSendRounds) continue;
|
||||
}
|
||||
|
||||
CompactTallyItem& item = mapTally[txdest];
|
||||
item.txdest = txdest;
|
||||
item.nAmount += wtx.vout[i].nValue;
|
||||
item.nAmount += wtx.tx->vout[i].nValue;
|
||||
item.vecTxIn.push_back(CTxIn(outpoint.hash, i));
|
||||
}
|
||||
}
|
||||
@ -3097,19 +3097,19 @@ bool CWallet::SelectCoinsDark(CAmount nValueMin, CAmount nValueMax, std::vector<
|
||||
BOOST_FOREACH(const COutput& out, vCoins)
|
||||
{
|
||||
//do not allow inputs less than 1/10th of minimum value
|
||||
if(out.tx->vout[out.i].nValue < nValueMin/10) continue;
|
||||
if(out.tx->tx->vout[out.i].nValue < nValueMin/10) continue;
|
||||
//do not allow collaterals to be selected
|
||||
if(CPrivateSend::IsCollateralAmount(out.tx->vout[out.i].nValue)) continue;
|
||||
if(fMasterNode && out.tx->vout[out.i].nValue == 1000*COIN) continue; //masternode input
|
||||
if(CPrivateSend::IsCollateralAmount(out.tx->tx->vout[out.i].nValue)) continue;
|
||||
if(fMasterNode && out.tx->tx->vout[out.i].nValue == 1000*COIN) continue; //masternode input
|
||||
|
||||
if(nValueRet + out.tx->vout[out.i].nValue <= nValueMax){
|
||||
if(nValueRet + out.tx->tx->vout[out.i].nValue <= nValueMax){
|
||||
CTxIn txin = CTxIn(out.tx->GetHash(),out.i);
|
||||
|
||||
int nRounds = GetOutpointPrivateSendRounds(txin.prevout);
|
||||
if(nRounds >= nPrivateSendRoundsMax) continue;
|
||||
if(nRounds < nPrivateSendRoundsMin) continue;
|
||||
|
||||
nValueRet += out.tx->vout[out.i].nValue;
|
||||
nValueRet += out.tx->tx->vout[out.i].nValue;
|
||||
vecTxInRet.push_back(txin);
|
||||
}
|
||||
}
|
||||
@ -3125,10 +3125,10 @@ bool CWallet::GetCollateralTxDSIn(CTxDSIn& txdsinRet, CAmount& nValueRet) const
|
||||
|
||||
BOOST_FOREACH(const COutput& out, vCoins)
|
||||
{
|
||||
if(CPrivateSend::IsCollateralAmount(out.tx->vout[out.i].nValue))
|
||||
if(CPrivateSend::IsCollateralAmount(out.tx->tx->vout[out.i].nValue))
|
||||
{
|
||||
txdsinRet = CTxDSIn(CTxIn(out.tx->GetHash(), out.i), out.tx->vout[out.i].scriptPubKey);
|
||||
nValueRet = out.tx->vout[out.i].nValue;
|
||||
txdsinRet = CTxDSIn(CTxIn(out.tx->tx->GetHash(), out.i), out.tx->tx->vout[out.i].scriptPubKey);
|
||||
nValueRet = out.tx->tx->vout[out.i].nValue;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -3172,7 +3172,7 @@ bool CWallet::GetOutpointAndKeysFromOutput(const COutput& out, COutPoint& outpoi
|
||||
CScript pubScript;
|
||||
|
||||
outpointRet = COutPoint(out.tx->GetHash(), out.i);
|
||||
pubScript = out.tx->vout[out.i].scriptPubKey; // the inputs PubKey
|
||||
pubScript = out.tx->tx->vout[out.i].scriptPubKey; // the inputs PubKey
|
||||
|
||||
CTxDestination address1;
|
||||
ExtractDestination(pubScript, address1);
|
||||
@ -3204,13 +3204,13 @@ int CWallet::CountInputsWithAmount(CAmount nInputAmount)
|
||||
if (pcoin->IsTrusted()){
|
||||
int nDepth = pcoin->GetDepthInMainChain(false);
|
||||
|
||||
for (unsigned int i = 0; i < pcoin->vout.size(); i++) {
|
||||
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++) {
|
||||
COutput out = COutput(pcoin, i, nDepth, true, true);
|
||||
COutPoint outpoint = COutPoint(out.tx->GetHash(), out.i);
|
||||
|
||||
if(out.tx->vout[out.i].nValue != nInputAmount) continue;
|
||||
if(!CPrivateSend::IsDenominatedAmount(pcoin->vout[i].nValue)) continue;
|
||||
if(IsSpent(out.tx->GetHash(), i) || IsMine(pcoin->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(outpoint)) continue;
|
||||
if(out.tx->tx->vout[out.i].nValue != nInputAmount) continue;
|
||||
if(!CPrivateSend::IsDenominatedAmount(pcoin->tx->vout[i].nValue)) continue;
|
||||
if(IsSpent(out.tx->GetHash(), i) || IsMine(pcoin->tx->vout[i]) != ISMINE_SPENDABLE || !IsDenominated(outpoint)) continue;
|
||||
|
||||
nTotal++;
|
||||
}
|
||||
@ -3264,11 +3264,11 @@ bool CWallet::CreateCollateralTransaction(CMutableTransaction& txCollateral, std
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CWallet::GetBudgetSystemCollateralTX(CTransaction& tx, uint256 hash, CAmount amount, bool fUseInstantSend)
|
||||
bool CWallet::GetBudgetSystemCollateralTX(CTransactionRef& tx, uint256 hash, CAmount amount, bool fUseInstantSend)
|
||||
{
|
||||
CWalletTx wtx;
|
||||
if(GetBudgetSystemCollateralTX(wtx, hash, amount, fUseInstantSend)){
|
||||
tx = (CTransaction)wtx;
|
||||
tx = wtx.tx;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -3304,8 +3304,8 @@ bool CWallet::ConvertList(std::vector<CTxIn> vecTxIn, std::vector<CAmount>& vecA
|
||||
BOOST_FOREACH(CTxIn txin, vecTxIn) {
|
||||
if (mapWallet.count(txin.prevout.hash)) {
|
||||
CWalletTx& wtx = mapWallet[txin.prevout.hash];
|
||||
if(txin.prevout.n < wtx.vout.size()){
|
||||
vecAmounts.push_back(wtx.vout[txin.prevout.n].nValue);
|
||||
if(txin.prevout.n < wtx.tx->vout.size()){
|
||||
vecAmounts.push_back(wtx.tx->vout[txin.prevout.n].nValue);
|
||||
}
|
||||
} else {
|
||||
LogPrintf("CWallet::ConvertList -- Couldn't find transaction\n");
|
||||
@ -3458,7 +3458,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||
|
||||
BOOST_FOREACH(PAIRTYPE(const CWalletTx*, unsigned int) pcoin, setCoins)
|
||||
{
|
||||
CAmount nCredit = pcoin.first->vout[pcoin.second].nValue;
|
||||
CAmount nCredit = pcoin.first->tx->vout[pcoin.second].nValue;
|
||||
//The coin age after the next block (depth+1) is used instead of the current,
|
||||
//reflecting an assumption the user would accept a bit more delay for
|
||||
//a chance at a free transaction.
|
||||
@ -3574,7 +3574,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||
BOOST_FOREACH(const PAIRTYPE(const CWalletTx*,unsigned int)& coin, setCoins){
|
||||
CTxIn txin = CTxIn(coin.first->GetHash(),coin.second,CScript(),
|
||||
std::numeric_limits<unsigned int>::max()-1);
|
||||
vecTxDSInTmp.push_back(CTxDSIn(txin, coin.first->vout[coin.second].scriptPubKey));
|
||||
vecTxDSInTmp.push_back(CTxDSIn(txin, coin.first->tx->vout[coin.second].scriptPubKey));
|
||||
txNew.vin.push_back(txin);
|
||||
}
|
||||
|
||||
@ -3626,16 +3626,16 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt
|
||||
}
|
||||
|
||||
// Embed the constructed transaction data in wtxNew.
|
||||
*static_cast<CTransaction*>(&wtxNew) = CTransaction(txNew);
|
||||
wtxNew.SetTx(MakeTransactionRef(std::move(txNew)));
|
||||
|
||||
// Limit size
|
||||
if (nBytes >= MAX_STANDARD_TX_SIZE)
|
||||
if (::GetSerializeSize(wtxNew, SER_NETWORK, PROTOCOL_VERSION) >= MAX_STANDARD_TX_SIZE)
|
||||
{
|
||||
strFailReason = _("Transaction too large");
|
||||
return false;
|
||||
}
|
||||
|
||||
dPriority = wtxNew.ComputePriority(dPriority, nBytes);
|
||||
dPriority = wtxNew.tx->ComputePriority(dPriority, nBytes);
|
||||
|
||||
// Allow to override the default confirmation target over the CoinControl instance
|
||||
int currentConfirmationTarget = nTxConfirmTarget;
|
||||
@ -3694,7 +3694,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
|
||||
{
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
LogPrintf("CommitTransaction:\n%s", wtxNew.ToString());
|
||||
LogPrintf("CommitTransaction:\n%s", wtxNew.tx->ToString());
|
||||
{
|
||||
// Take key pair from key pool so it won't be used again
|
||||
reservekey.KeepKey();
|
||||
@ -3705,7 +3705,7 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey, CCon
|
||||
|
||||
// Notify that old coins are spent
|
||||
set<uint256> updated_hahes;
|
||||
BOOST_FOREACH(const CTxIn& txin, wtxNew.vin)
|
||||
BOOST_FOREACH(const CTxIn& txin, wtxNew.tx->vin)
|
||||
{
|
||||
// notify only once
|
||||
if(updated_hahes.find(txin.prevout.hash) != updated_hahes.end()) continue;
|
||||
@ -3806,8 +3806,8 @@ DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
|
||||
{
|
||||
LOCK2(cs_main, cs_wallet);
|
||||
for (auto& pair : mapWallet) {
|
||||
for(int i = 0; i < pair.second.vout.size(); ++i) {
|
||||
if (IsMine(pair.second.vout[i]) && !IsSpent(pair.first, i)) {
|
||||
for(int i = 0; i < pair.second.tx->vout.size(); ++i) {
|
||||
if (IsMine(pair.second.tx->vout[i]) && !IsSpent(pair.first, i)) {
|
||||
setWalletUTXO.insert(COutPoint(pair.first, i));
|
||||
}
|
||||
}
|
||||
@ -4167,15 +4167,15 @@ std::map<CTxDestination, CAmount> CWallet::GetAddressBalances()
|
||||
if (nDepth < (pcoin->IsFromMe(ISMINE_ALL) ? 0 : 1))
|
||||
continue;
|
||||
|
||||
for (unsigned int i = 0; i < pcoin->vout.size(); i++)
|
||||
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++)
|
||||
{
|
||||
CTxDestination addr;
|
||||
if (!IsMine(pcoin->vout[i]))
|
||||
if (!IsMine(pcoin->tx->vout[i]))
|
||||
continue;
|
||||
if(!ExtractDestination(pcoin->vout[i].scriptPubKey, addr))
|
||||
if(!ExtractDestination(pcoin->tx->vout[i].scriptPubKey, addr))
|
||||
continue;
|
||||
|
||||
CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->vout[i].nValue;
|
||||
CAmount n = IsSpent(walletEntry.first, i) ? 0 : pcoin->tx->vout[i].nValue;
|
||||
|
||||
if (!balances.count(addr))
|
||||
balances[addr] = 0;
|
||||
@ -4197,16 +4197,16 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||
{
|
||||
CWalletTx *pcoin = &walletEntry.second;
|
||||
|
||||
if (pcoin->vin.size() > 0)
|
||||
if (pcoin->tx->vin.size() > 0)
|
||||
{
|
||||
bool any_mine = false;
|
||||
// group all input addresses with each other
|
||||
BOOST_FOREACH(CTxIn txin, pcoin->vin)
|
||||
BOOST_FOREACH(CTxIn txin, pcoin->tx->vin)
|
||||
{
|
||||
CTxDestination address;
|
||||
if(!IsMine(txin)) /* If this input isn't mine, ignore it */
|
||||
continue;
|
||||
if(!ExtractDestination(mapWallet[txin.prevout.hash].vout[txin.prevout.n].scriptPubKey, address))
|
||||
if(!ExtractDestination(mapWallet[txin.prevout.hash].tx->vout[txin.prevout.n].scriptPubKey, address))
|
||||
continue;
|
||||
grouping.insert(address);
|
||||
any_mine = true;
|
||||
@ -4215,7 +4215,7 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||
// group change with input addresses
|
||||
if (any_mine)
|
||||
{
|
||||
BOOST_FOREACH(CTxOut txout, pcoin->vout)
|
||||
BOOST_FOREACH(CTxOut txout, pcoin->tx->vout)
|
||||
if (IsChange(txout))
|
||||
{
|
||||
CTxDestination txoutAddr;
|
||||
@ -4232,11 +4232,11 @@ set< set<CTxDestination> > CWallet::GetAddressGroupings()
|
||||
}
|
||||
|
||||
// group lone addrs by themselves
|
||||
for (unsigned int i = 0; i < pcoin->vout.size(); i++)
|
||||
if (IsMine(pcoin->vout[i]))
|
||||
for (unsigned int i = 0; i < pcoin->tx->vout.size(); i++)
|
||||
if (IsMine(pcoin->tx->vout[i]))
|
||||
{
|
||||
CTxDestination address;
|
||||
if(!ExtractDestination(pcoin->vout[i].scriptPubKey, address))
|
||||
if(!ExtractDestination(pcoin->tx->vout[i].scriptPubKey, address))
|
||||
continue;
|
||||
grouping.insert(address);
|
||||
groupings.insert(grouping);
|
||||
@ -4530,7 +4530,7 @@ void CWallet::GetKeyBirthTimes(std::map<CKeyID, int64_t> &mapKeyBirth) const {
|
||||
if (blit != mapBlockIndex.end() && chainActive.Contains(blit->second)) {
|
||||
// ... which are already in a block
|
||||
int nHeight = blit->second->nHeight;
|
||||
BOOST_FOREACH(const CTxOut &txout, wtx.vout) {
|
||||
BOOST_FOREACH(const CTxOut &txout, wtx.tx->vout) {
|
||||
// iterate over all their outputs
|
||||
CAffectedKeysVisitor(*this, vAffected).Process(txout.scriptPubKey);
|
||||
BOOST_FOREACH(const CKeyID &keyid, vAffected) {
|
||||
|
@ -200,13 +200,14 @@ struct COutputEntry
|
||||
};
|
||||
|
||||
/** A transaction with a merkle branch linking it to the block chain. */
|
||||
class CMerkleTx : public CTransaction
|
||||
class CMerkleTx
|
||||
{
|
||||
private:
|
||||
/** Constant used in hashBlock to indicate tx has been abandoned */
|
||||
static const uint256 ABANDON_HASH;
|
||||
|
||||
public:
|
||||
CTransactionRef tx;
|
||||
uint256 hashBlock;
|
||||
|
||||
/* An nIndex == -1 means that hashBlock (in nonzero) refers to the earliest
|
||||
@ -218,26 +219,37 @@ public:
|
||||
|
||||
CMerkleTx()
|
||||
{
|
||||
SetTx(MakeTransactionRef());
|
||||
Init();
|
||||
}
|
||||
|
||||
CMerkleTx(const CTransaction& txIn) : CTransaction(txIn)
|
||||
CMerkleTx(CTransactionRef arg)
|
||||
{
|
||||
SetTx(std::move(arg));
|
||||
Init();
|
||||
}
|
||||
|
||||
/** Helper conversion operator to allow passing CMerkleTx where CTransaction is expected.
|
||||
* TODO: adapt callers and remove this operator. */
|
||||
operator const CTransaction&() const { return *tx; }
|
||||
|
||||
void Init()
|
||||
{
|
||||
hashBlock = uint256();
|
||||
nIndex = -1;
|
||||
}
|
||||
|
||||
void SetTx(CTransactionRef arg)
|
||||
{
|
||||
tx = std::move(arg);
|
||||
}
|
||||
|
||||
ADD_SERIALIZE_METHODS;
|
||||
|
||||
template <typename Stream, typename Operation>
|
||||
inline void SerializationOp(Stream& s, Operation ser_action) {
|
||||
std::vector<uint256> vMerkleBranch; // For compatibility with older versions.
|
||||
READWRITE(*(CTransaction*)this);
|
||||
READWRITE(tx);
|
||||
READWRITE(hashBlock);
|
||||
READWRITE(vMerkleBranch);
|
||||
READWRITE(nIndex);
|
||||
@ -260,6 +272,9 @@ public:
|
||||
bool hashUnset() const { return (hashBlock.IsNull() || hashBlock == ABANDON_HASH); }
|
||||
bool isAbandoned() const { return (hashBlock == ABANDON_HASH); }
|
||||
void setAbandoned() { hashBlock = ABANDON_HASH; }
|
||||
|
||||
const uint256& GetHash() const { return tx->GetHash(); }
|
||||
bool IsCoinBase() const { return tx->IsCoinBase(); }
|
||||
};
|
||||
|
||||
/**
|
||||
@ -312,17 +327,7 @@ public:
|
||||
Init(NULL);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn, const CMerkleTx& txIn) : CMerkleTx(txIn)
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
|
||||
CWalletTx(const CWallet* pwalletIn, const CTransaction& txIn) : CMerkleTx(txIn)
|
||||
CWalletTx(const CWallet* pwalletIn, CTransactionRef arg) : CMerkleTx(std::move(arg))
|
||||
{
|
||||
Init(pwalletIn);
|
||||
}
|
||||
@ -883,7 +888,7 @@ public:
|
||||
CAmount GetNeedsToBeAnonymizedBalance(CAmount nMinBalance = 0) const;
|
||||
CAmount GetDenominatedBalance(bool unconfirmed=false) const;
|
||||
|
||||
bool GetBudgetSystemCollateralTX(CTransaction& tx, uint256 hash, CAmount amount, bool fUseInstantSend);
|
||||
bool GetBudgetSystemCollateralTX(CTransactionRef& tx, uint256 hash, CAmount amount, bool fUseInstantSend);
|
||||
bool GetBudgetSystemCollateralTX(CWalletTx& tx, uint256 hash, CAmount amount, bool fUseInstantSend);
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user