diff options
| author | Ross Nicoll <[email protected]> | 2018-01-07 22:56:53 +0000 |
|---|---|---|
| committer | Ross Nicoll <[email protected]> | 2018-09-19 21:09:16 +0100 |
| commit | 18850d359bbc4d3333d9f1ac33607242d205c2ce (patch) | |
| tree | 45cb5ac9949143efb71ddd7f3f7f4cf8c152df2d /src | |
| parent | Verify when doing 'backupwallet' that destination is not the same path of the... (diff) | |
| download | discoin-18850d359bbc4d3333d9f1ac33607242d205c2ce.tar.xz discoin-18850d359bbc4d3333d9f1ac33607242d205c2ce.zip | |
Add Dogecoin current fee calculation logic (#1413)
Introduces 1 COIN/kb fees, rounded up to the next 1 COIN.
Diffstat (limited to 'src')
| -rw-r--r-- | src/dogecoin.cpp | 44 | ||||
| -rw-r--r-- | src/dogecoin.h | 3 | ||||
| -rw-r--r-- | src/policy/policy.h | 2 | ||||
| -rw-r--r-- | src/qt/coincontroldialog.cpp | 2 | ||||
| -rw-r--r-- | src/test/script_P2SH_tests.cpp | 4 | ||||
| -rw-r--r-- | src/validation.cpp | 2 | ||||
| -rw-r--r-- | src/validation.h | 6 | ||||
| -rw-r--r-- | src/wallet/rpcwallet.cpp | 6 | ||||
| -rw-r--r-- | src/wallet/test/wallet_tests.cpp | 38 | ||||
| -rw-r--r-- | src/wallet/wallet.cpp | 25 | ||||
| -rw-r--r-- | src/wallet/wallet.h | 15 |
11 files changed, 123 insertions, 24 deletions
diff --git a/src/dogecoin.cpp b/src/dogecoin.cpp index f06849d61..b34437ca0 100644 --- a/src/dogecoin.cpp +++ b/src/dogecoin.cpp @@ -5,9 +5,12 @@ #include <boost/random/uniform_int.hpp> #include <boost/random/mersenne_twister.hpp> +#include "policy/policy.h" #include "arith_uint256.h" #include "dogecoin.h" +#include "txmempool.h" #include "util.h" +#include "validation.h" int static generateMTRandom(unsigned int s, int range) { @@ -142,3 +145,44 @@ CAmount GetDogecoinBlockSubsidy(int nHeight, const Consensus::Params& consensusP return 10000 * COIN; } } + +CAmount GetDogecoinMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree) +{ + { + LOCK(mempool.cs); + uint256 hash = tx.GetHash(); + double dPriorityDelta = 0; + CAmount nFeeDelta = 0; + mempool.ApplyDeltas(hash, dPriorityDelta, nFeeDelta); + if (dPriorityDelta > 0 || nFeeDelta > 0) + return 0; + } + + CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes); + nMinFee += GetDogecoinDustFee(tx.vout, ::minRelayTxFee); + + if (fAllowFree) + { + // There is a free transaction area in blocks created by most miners, + // * If we are relaying we allow transactions up to DEFAULT_BLOCK_PRIORITY_SIZE - 1000 + // to be considered to fall into this category. We don't want to encourage sending + // multiple transactions instead of one big transaction to avoid fees. + if (nBytes < (DEFAULT_BLOCK_PRIORITY_SIZE - 1000)) + nMinFee = 0; + } + + if (!MoneyRange(nMinFee)) + nMinFee = MAX_MONEY; + return nMinFee; +} + +CAmount GetDogecoinDustFee(const std::vector<CTxOut> &vout, CFeeRate &baseFeeRate) { + CAmount nFee = 0; + + // To limit dust spam, add base fee for each output less than DUST_SOFT_LIMIT + BOOST_FOREACH(const CTxOut& txout, vout) + if (txout.IsDust(::minRelayTxFee)) + nFee += baseFeeRate.GetFeePerK(); + + return nFee; +} diff --git a/src/dogecoin.h b/src/dogecoin.h index e466d1e98..3bc63635d 100644 --- a/src/dogecoin.h +++ b/src/dogecoin.h @@ -17,3 +17,6 @@ unsigned int CalculateDogecoinNextWorkRequired(const CBlockIndex* pindexLast, in * @return True iff the PoW is correct. */ bool CheckAuxPowProofOfWork(const CBlockHeader& block, const Consensus::Params& params); + +CAmount GetDogecoinMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowFree); +CAmount GetDogecoinDustFee(const std::vector<CTxOut> &vout, CFeeRate &baseFeeRate); diff --git a/src/policy/policy.h b/src/policy/policy.h index 9b1323ac2..a7fc8b78e 100644 --- a/src/policy/policy.h +++ b/src/policy/policy.h @@ -17,7 +17,7 @@ class CCoinsViewCache; /** Default for -blockmaxsize, which controls the maximum size of block the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_SIZE = 750000; /** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/ -static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0; +static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 27000; /** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/ static const unsigned int DEFAULT_BLOCK_MAX_WEIGHT = 3000000; /** Default for -blockmintxfee, which sets the minimum feerate for a transaction in blocks created by mining code **/ diff --git a/src/qt/coincontroldialog.cpp b/src/qt/coincontroldialog.cpp index d4fd8bd37..becc14551 100644 --- a/src/qt/coincontroldialog.cpp +++ b/src/qt/coincontroldialog.cpp @@ -521,7 +521,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog) nBytes -= 34; // Fee - nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool); + nPayFee = CWallet::GetMinimumFee(txDummy, nBytes, nTxConfirmTarget, mempool); if (nPayFee > 0 && coinControl->nMinimumTotalFee > nPayFee) nPayFee = coinControl->nMinimumTotalFee; diff --git a/src/test/script_P2SH_tests.cpp b/src/test/script_P2SH_tests.cpp index f8fd8cc30..0d1eb050b 100644 --- a/src/test/script_P2SH_tests.cpp +++ b/src/test/script_P2SH_tests.cpp @@ -181,7 +181,7 @@ BOOST_AUTO_TEST_CASE(set) for (int i = 0; i < 4; i++) { txFrom.vout[i].scriptPubKey = outer[i]; - txFrom.vout[i].nValue = CENT; + txFrom.vout[i].nValue = COIN; } BOOST_CHECK(IsStandardTx(txFrom, reason)); @@ -192,7 +192,7 @@ BOOST_AUTO_TEST_CASE(set) txTo[i].vout.resize(1); txTo[i].vin[0].prevout.n = i; txTo[i].vin[0].prevout.hash = txFrom.GetHash(); - txTo[i].vout[0].nValue = 1*CENT; + txTo[i].vout[0].nValue = 1*COIN; txTo[i].vout[0].scriptPubKey = inner[i]; BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i)); } diff --git a/src/validation.cpp b/src/validation.cpp index e4ae9c045..1eebf3c71 100644 --- a/src/validation.cpp +++ b/src/validation.cpp @@ -768,7 +768,7 @@ bool AcceptToMemoryPoolWorker(CTxMemPool& pool, CValidationState& state, const C // Continuously rate-limit free (really, very-low-fee) transactions // This mitigates 'penny-flooding' -- sending thousands of free transactions just to // be annoying or make others' transactions take longer to confirm. - if (fLimitFree && nModifiedFees < ::minRelayTxFee.GetFee(nSize)) + if (fLimitFree && nModifiedFees < GetDogecoinMinRelayFee(tx, nSize, !fLimitFree)) { static CCriticalSection csFreeLimiter; static double dFreeCount; diff --git a/src/validation.h b/src/validation.h index 35eef1582..707ada3ee 100644 --- a/src/validation.h +++ b/src/validation.h @@ -52,11 +52,11 @@ static const bool DEFAULT_WHITELISTRELAY = true; /** Default for DEFAULT_WHITELISTFORCERELAY. */ static const bool DEFAULT_WHITELISTFORCERELAY = true; /** Default for -minrelaytxfee, minimum relay fee for transactions */ -static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = 1000; +static const unsigned int DEFAULT_MIN_RELAY_TX_FEE = COIN; //! -maxtxfee default -static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN; +static const CAmount DEFAULT_TRANSACTION_MAXFEE = 400 * COIN; //! Discourage users to set fees higher than this amount (in satoshis) per kB -static const CAmount HIGH_TX_FEE_PER_KB = 0.01 * COIN; +static const CAmount HIGH_TX_FEE_PER_KB = 10 * COIN; //! -maxtxfee will warn if called with a higher fee than this amount (in satoshis) static const CAmount HIGH_MAX_TX_FEE = 100 * HIGH_TX_FEE_PER_KB; /** Default for -limitancestorcount, max number of in-mempool ancestors */ diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp index d6b6d0142..ec00160c6 100644 --- a/src/wallet/rpcwallet.cpp +++ b/src/wallet/rpcwallet.cpp @@ -2829,7 +2829,7 @@ UniValue bumpfee(const JSONRPCRequest& request) } } else if (options.exists("totalFee")) { totalFee = options["totalFee"].get_int64(); - CAmount requiredFee = CWallet::GetRequiredFee(maxNewTxSize); + CAmount requiredFee = CWallet::GetRequiredFee(*wtx.tx, maxNewTxSize); if (totalFee < requiredFee ) { throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Insufficient totalFee (cannot be less than required fee %s)", @@ -2866,11 +2866,11 @@ UniValue bumpfee(const JSONRPCRequest& request) } else { // if user specified a confirm target then don't consider any global payTxFee if (specifiedConfirmTarget) { - nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool, CAmount(0)); + nNewFee = CWallet::GetMinimumFee(*wtx.tx, maxNewTxSize, newConfirmTarget, mempool, CAmount(0)); } // otherwise use the regular wallet logic to select payTxFee or default confirm target else { - nNewFee = CWallet::GetMinimumFee(maxNewTxSize, newConfirmTarget, mempool); + nNewFee = CWallet::GetMinimumFee(*wtx.tx, maxNewTxSize, newConfirmTarget, mempool); } nNewFeeRate = CFeeRate(nNewFee, maxNewTxSize); diff --git a/src/wallet/test/wallet_tests.cpp b/src/wallet/test/wallet_tests.cpp index 2fbcc3414..c6e10f34f 100644 --- a/src/wallet/test/wallet_tests.cpp +++ b/src/wallet/test/wallet_tests.cpp @@ -2,6 +2,7 @@ // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. +#include "txmempool.h" #include "wallet/wallet.h" #include <set> @@ -434,7 +435,7 @@ BOOST_FIXTURE_TEST_CASE(rescan, TestChain240Setup) // greater or equal than key birthday. Previously there was a bug where // importwallet RPC would start the scan at the latest block with timestamp less // than or equal to key birthday. -BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) +BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain240Setup) { CWallet *pwalletMainBackup = ::pwalletMain; LOCK(cs_main); @@ -490,4 +491,39 @@ BOOST_FIXTURE_TEST_CASE(importwallet_rescan, TestChain100Setup) ::pwalletMain = pwalletMainBackup; } +BOOST_AUTO_TEST_CASE(GetMinimumFee_test) +{ + uint64_t value = 1000 * COIN; // 1,000 DOGE + + CMutableTransaction tx; + CTxMemPool pool(payTxFee); + CTxOut txout1(value, (CScript)vector<unsigned char>(24, 0)); + tx.vout.push_back(txout1); + + int64_t nMinTxFee = COIN; + + BOOST_CHECK_EQUAL(CWallet::GetMinimumFee(tx, 250, 0, pool), nMinTxFee); + BOOST_CHECK_EQUAL(CWallet::GetMinimumFee(tx, 1000, 0, pool), 2 * nMinTxFee); + BOOST_CHECK_EQUAL(CWallet::GetMinimumFee(tx, 1999, 0, pool), 2 * nMinTxFee); +} + +BOOST_AUTO_TEST_CASE(GetMinimumFee_dust_test) +{ + // Derived from main net TX 3d6ec3ae2aca3ae0a6c65074fd8ee888cd7ed262f2cbaa25d33861989324a14e + CMutableTransaction tx; + CTxMemPool pool(payTxFee); + CTxOut txout1(139496846, (CScript)vector<unsigned char>(24, 0)); // Regular output + CTxOut txout2(15499649, (CScript)vector<unsigned char>(24, 0)); // Dust output + tx.vout.push_back(txout1); + tx.vout.push_back(txout2); + + int64_t nMinTxFee = COIN; + + // Confirm dust penalty fees are added on + + BOOST_CHECK_EQUAL(CWallet::GetMinimumFee(tx, 963, 0, pool), 2 * nMinTxFee); + BOOST_CHECK_EQUAL(CWallet::GetMinimumFee(tx, 1000, 0, pool), 3 * nMinTxFee); + BOOST_CHECK_EQUAL(CWallet::GetMinimumFee(tx, 1999, 0, pool), 3 * nMinTxFee); +} + BOOST_AUTO_TEST_SUITE_END() diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 0e09dc70d..b34cbae3a 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -8,6 +8,7 @@ #include "base58.h" #include "checkpoints.h" #include "chain.h" +#include "dogecoin.h" #include "wallet/coincontrol.h" #include "consensus/consensus.h" #include "consensus/validation.h" @@ -2636,7 +2637,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend, CWalletTx& wt break; } - CAmount nFeeNeeded = GetMinimumFee(nBytes, currentConfirmationTarget, mempool); + CAmount nFeeNeeded = GetMinimumFee(txNew, nBytes, currentConfirmationTarget, mempool); if (coinControl && nFeeNeeded > 0 && coinControl->nMinimumTotalFee > nFeeNeeded) { nFeeNeeded = coinControl->nMinimumTotalFee; } @@ -2805,18 +2806,30 @@ bool CWallet::AddAccountingEntry(const CAccountingEntry& acentry, CWalletDB *pwa return true; } +CAmount CWallet::GetRequiredFee(const CMutableTransaction& tx, unsigned int nTxBytes) +{ + // Dogecoin: Round TX bytes up to the next 1,000 bytes + nTxBytes += 1000 - (nTxBytes % 1000); + + // Dogecoin: Add an increased fee for each dust output + return std::max(minTxFee.GetFee(nTxBytes) + GetDogecoinDustFee(tx.vout, minTxFee), ::minRelayTxFee.GetFee(nTxBytes)); +} + CAmount CWallet::GetRequiredFee(unsigned int nTxBytes) { + // Dogecoin: Round TX bytes up to the next 1,000 bytes + nTxBytes += 1000 - (nTxBytes % 1000); + return std::max(minTxFee.GetFee(nTxBytes), ::minRelayTxFee.GetFee(nTxBytes)); } -CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) +CAmount CWallet::GetMinimumFee(const CMutableTransaction& tx, unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool) { // payTxFee is the user-set global for desired feerate - return GetMinimumFee(nTxBytes, nConfirmTarget, pool, payTxFee.GetFee(nTxBytes)); + return GetMinimumFee(tx, nTxBytes, nConfirmTarget, pool, payTxFee.GetFee(nTxBytes)); } -CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee) +CAmount CWallet::GetMinimumFee(const CMutableTransaction& tx, unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee) { CAmount nFeeNeeded = targetFee; // User didn't set: use -txconfirmtarget to estimate... @@ -2828,7 +2841,7 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge nFeeNeeded = fallbackFee.GetFee(nTxBytes); } // prevent user from paying a fee below minRelayTxFee or minTxFee - nFeeNeeded = std::max(nFeeNeeded, GetRequiredFee(nTxBytes)); + nFeeNeeded = std::max(nFeeNeeded, GetRequiredFee(tx, nTxBytes)); // But always obey the maximum if (nFeeNeeded > maxTxFee) nFeeNeeded = maxTxFee; @@ -2836,8 +2849,6 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge } - - DBErrors CWallet::LoadWallet(bool& fFirstRunRet) { if (!fFileBacked) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 8cf4a83ae..16588721c 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -47,11 +47,11 @@ static const unsigned int DEFAULT_KEYPOOL_SIZE = 100; //! -paytxfee default static const CAmount DEFAULT_TRANSACTION_FEE = 0; //! -fallbackfee default -static const CAmount DEFAULT_FALLBACK_FEE = 20000; +static const CAmount DEFAULT_FALLBACK_FEE = COIN * 20; //! -mintxfee default -static const CAmount DEFAULT_TRANSACTION_MINFEE = 1000; +static const CAmount DEFAULT_TRANSACTION_MINFEE = COIN; //! minimum recommended increment for BIP 125 replacement txs -static const CAmount WALLET_INCREMENTAL_RELAY_FEE = 5000; +static const CAmount WALLET_INCREMENTAL_RELAY_FEE = COIN * 5; //! target minimum change amount static const CAmount MIN_CHANGE = CENT; //! final minimum change amount after paying for fees @@ -749,16 +749,21 @@ public: * Estimate the minimum fee considering user set parameters * and the required fee */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); + static CAmount GetMinimumFee(const CMutableTransaction& tx, unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool); /** * Estimate the minimum fee considering required fee and targetFee or if 0 * then fee estimation for nConfirmTarget */ - static CAmount GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee); + static CAmount GetMinimumFee(const CMutableTransaction& tx, unsigned int nTxBytes, unsigned int nConfirmTarget, const CTxMemPool& pool, CAmount targetFee); /** * Return the minimum required fee taking into account the * floating relay fee and user set minimum transaction fee */ + static CAmount GetRequiredFee(const CMutableTransaction& tx, unsigned int nTxBytes); + /** + * Return the minimum required fee taking into account the + * floating relay fee and user set minimum transaction fee, but not the Dogecoin dust fee. + */ static CAmount GetRequiredFee(unsigned int nTxBytes); bool NewKeyPool(); |