aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRoss Nicoll <[email protected]>2018-01-07 22:56:53 +0000
committerRoss Nicoll <[email protected]>2018-09-19 21:09:16 +0100
commit18850d359bbc4d3333d9f1ac33607242d205c2ce (patch)
tree45cb5ac9949143efb71ddd7f3f7f4cf8c152df2d /src
parentVerify when doing 'backupwallet' that destination is not the same path of the... (diff)
downloaddiscoin-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.cpp44
-rw-r--r--src/dogecoin.h3
-rw-r--r--src/policy/policy.h2
-rw-r--r--src/qt/coincontroldialog.cpp2
-rw-r--r--src/test/script_P2SH_tests.cpp4
-rw-r--r--src/validation.cpp2
-rw-r--r--src/validation.h6
-rw-r--r--src/wallet/rpcwallet.cpp6
-rw-r--r--src/wallet/test/wallet_tests.cpp38
-rw-r--r--src/wallet/wallet.cpp25
-rw-r--r--src/wallet/wallet.h15
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();