From f406c0356882253fcd02f8f660088d5bf6da7d28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jorge=20Tim=C3=B3n?= Date: Tue, 22 Mar 2016 00:34:18 +0100 Subject: [PATCH] HF Assets: primitives/transaction: post-CT: Explicit multi-asset fees Fix CTransaction::GetFee() + Introduce CMutableTransaction::SetFeesFromTxRewardMap --- src/primitives/transaction.cpp | 50 +++++++++++++++++++++++++++++----- src/primitives/transaction.h | 17 +++++++++--- 2 files changed, 56 insertions(+), 11 deletions(-) diff --git a/src/primitives/transaction.cpp b/src/primitives/transaction.cpp index 8ca33f6b55..39d37813d0 100644 --- a/src/primitives/transaction.cpp +++ b/src/primitives/transaction.cpp @@ -158,8 +158,8 @@ std::string CTxOut::ToString() const return strprintf("CTxOut(nValue=%s, assetID=%s, scriptPubKey=%s)", (nValue.IsAmount() ? strprintf("%d.%08d", nValue.GetAmount() / COIN, nValue.GetAmount() % COIN) : std::string("UNKNOWN")), assetID.ToString(), scriptPubKey.ToString().substr(0,30)); } -CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), nTxFee(0), nLockTime(0) {} -CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), nTxFee(tx.nTxFee), vout(tx.vout), nLockTime(tx.nLockTime) {} +CMutableTransaction::CMutableTransaction() : nVersion(CTransaction::CURRENT_VERSION), vTxFees(std::vector()), nLockTime(0) {} +CMutableTransaction::CMutableTransaction(const CTransaction& tx) : nVersion(tx.nVersion), vin(tx.vin), vTxFees(tx.vTxFees), vout(tx.vout), nLockTime(tx.nLockTime) {} uint256 CMutableTransaction::GetHash() const { @@ -192,15 +192,15 @@ void CTransaction::UpdateHash() const hasher.Finalize((unsigned char*)&hashFull); } -CTransaction::CTransaction() : hash(0), hashFull(0), nVersion(CTransaction::CURRENT_VERSION), vin(), nTxFee(0), vout(), nLockTime(0) { } +CTransaction::CTransaction() : hash(0), hashFull(0), nVersion(CTransaction::CURRENT_VERSION), vin(), vTxFees(std::vector()), vout(), nLockTime(0) { } -CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), nTxFee(tx.nTxFee), vout(tx.vout), nLockTime(tx.nLockTime) { +CTransaction::CTransaction(const CMutableTransaction &tx) : nVersion(tx.nVersion), vin(tx.vin), vTxFees(tx.vTxFees), vout(tx.vout), nLockTime(tx.nLockTime) { UpdateHash(); } CTransaction& CTransaction::operator=(const CTransaction &tx) { *const_cast(&nVersion) = tx.nVersion; - *const_cast(&nTxFee) = tx.nTxFee; + *const_cast*>(&vTxFees) = tx.vTxFees; *const_cast*>(&vin) = tx.vin; *const_cast*>(&vout) = tx.vout; *const_cast(&nLockTime) = tx.nLockTime; @@ -217,6 +217,42 @@ double CTransaction::ComputePriority(double dPriorityInputs, unsigned int nTxSiz return dPriorityInputs / nTxSize; } +CAmountMap CTransaction::GetTxRewardMap() const +{ + assert(vTxFees.size() <= vout.size()); + CAmountMap mTxReward; + for (unsigned i = 0; i < vTxFees.size(); ++i) + if (vout[i].assetID != 0) + mTxReward[vout[i].assetID] += vTxFees[i]; + return mTxReward; +} + +void CMutableTransaction::SetFeesFromTxRewardMap(const CAmountMap& mTxReward) +{ + assert(mTxReward.size() <= vout.size()); + vTxFees.resize(mTxReward.size()); + for(CAmountMap::const_iterator it = mTxReward.begin(); it != mTxReward.end(); ++it) { + bool fFoundAsset = false; + for (unsigned i = 0; i < vout.size(); ++i) { + if (vout[i].assetID == it->first) { + vTxFees[i] = it->second; + fFoundAsset = true; + break; + } + } + if (!fFoundAsset) + assert(false && "CMutableTransaction::SetFeesFromTxRewardMap: Trying to pay fees without output."); + } +} + +CAmount CTransaction::GetFee(const CAssetID& assetID) const +{ + const CAmountMap mTxReward = GetTxRewardMap(); + if (!mTxReward.count(assetID)) + return 0; + return mTxReward.find(assetID)->second; +} + unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const { // In order to avoid disincentivizing cleaning up the UTXO set we don't count @@ -238,12 +274,12 @@ unsigned int CTransaction::CalculateModifiedSize(unsigned int nTxSize) const std::string CTransaction::ToString() const { std::string str; - str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u, fee=%u)\n", + str += strprintf("CTransaction(hash=%s, ver=%d, vin.size=%u, vout.size=%u, nLockTime=%u, vTxFees.size=%u)\n", GetHash().ToString().substr(0,10), nVersion, vin.size(), vout.size(), - nLockTime, nTxFee); + nLockTime, vTxFees.size()); for (unsigned int i = 0; i < vin.size(); i++) str += " " + vin[i].ToString() + "\n"; for (unsigned int i = 0; i < vout.size(); i++) diff --git a/src/primitives/transaction.h b/src/primitives/transaction.h index c5837f6453..86340a3909 100644 --- a/src/primitives/transaction.h +++ b/src/primitives/transaction.h @@ -267,7 +267,7 @@ public: // structure, including the hash. const int32_t nVersion; const std::vector vin; - const CAmount nTxFee; + const std::vector vTxFees; const std::vector vout; const uint32_t nLockTime; @@ -290,7 +290,7 @@ public: assert((nType != SER_GETHASH && !fOnlyWitness && fWitness) || nType == SER_GETHASH); if (!fOnlyWitness) READWRITE(*const_cast(&this->nVersion)); READWRITE(*const_cast*>(&vin)); - if (!fBitcoinTx && !fOnlyWitness) READWRITE(*const_cast(&nTxFee)); + if (!fBitcoinTx && !fOnlyWitness) READWRITE(*const_cast*>(&vTxFees)); if (!fOnlyWitness) READWRITE(*const_cast*>(&vout)); if (!fOnlyWitness) READWRITE(*const_cast(&nLockTime)); if (ser_action.ForRead()) @@ -324,6 +324,11 @@ public: // Compute priority, given priority of inputs and (optionally) tx size double ComputePriority(double dPriorityInputs, unsigned int nTxSize=0) const; + /** + * @return a CAmountMap with total fees per asset. + */ + CAmountMap GetTxRewardMap() const; + CAmount GetFee(const CAssetID& assetID) const; // Compute modified tx size for priority calculation (optionally given tx size) unsigned int CalculateModifiedSize(unsigned int nTxSize=0) const; @@ -362,7 +367,7 @@ struct CMutableTransaction { int32_t nVersion; std::vector vin; - CAmount nTxFee; + std::vector vTxFees; std::vector vout; uint32_t nLockTime; @@ -380,7 +385,7 @@ struct CMutableTransaction assert((nType != SER_GETHASH && !fOnlyWitness && fWitness) || nType == SER_GETHASH); if (!fOnlyWitness) READWRITE(this->nVersion); READWRITE(vin); - if (!fOnlyWitness) READWRITE(nTxFee); + if (!fOnlyWitness) READWRITE(vTxFees); if (!fOnlyWitness) READWRITE(vout); if (!fOnlyWitness) READWRITE(nLockTime); } @@ -394,6 +399,10 @@ struct CMutableTransaction * fly, as opposed to GetHash() in CTransaction, which uses a cached result. */ uint256 GetHash() const; + /** + * Sets the vTxFees to the cannonical representation provided + */ + void SetFeesFromTxRewardMap(const CAmountMap& mTxReward); }; #define FOREACH_TXIN(VAR, TX) \