Add Dogecoin current fee calculation logic

Introduces 1 COIN/kb fees, rounded up to the next 1 COIN.
Disable free transactions
Dust outputs incur a 1 COIN additional fee
Add unit tests for fee calculation
Update existing unit tests with higher transaction values so that transactions are still standard
This commit is contained in:
Ross Nicoll 2015-06-13 08:19:48 +00:00
parent 3ba610bc41
commit c81d7632e9
11 changed files with 78 additions and 19 deletions

View file

@ -7,6 +7,7 @@
#include "arith_uint256.h"
#include "dogecoin.h"
#include "main.h"
#include "util.h"
int static generateMTRandom(unsigned int s, int range)
@ -150,3 +151,15 @@ CAmount GetDogecoinBlockSubsidy(int nHeight, const Consensus::Params& consensusP
return 10000 * COIN;
}
}
int64_t GetDogecoinDustFee(const std::vector<CTxOut> &vout, CFeeRate &baseFeeRate) {
int64_t 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;
}

View file

@ -17,3 +17,5 @@ unsigned int CalculateDogecoinNextWorkRequired(const CBlockIndex* pindexLast, in
* @return True iff the PoW is correct.
*/
bool CheckAuxPowProofOfWork(const CBlockHeader& block, const Consensus::Params& params);
int64_t GetDogecoinDustFee(const std::vector<CTxOut> &vout, CFeeRate &baseFeeRate);

View file

@ -66,7 +66,7 @@ uint64_t nPruneTarget = 0;
bool fAlerts = DEFAULT_ALERTS;
/** Fees smaller than this (in satoshi) are considered zero fee (for relaying and mining) */
CFeeRate minRelayTxFee = CFeeRate(1000);
CFeeRate minRelayTxFee = CFeeRate(COIN);
CTxMemPool mempool(::minRelayTxFee);
@ -867,8 +867,10 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
}
CAmount nMinFee = ::minRelayTxFee.GetFee(nBytes);
nMinFee += GetDogecoinDustFee(tx.vout, ::minRelayTxFee);
if (fAllowFree)
// Dogecoin: Disable free transactions
/* 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
@ -876,7 +878,7 @@ CAmount GetMinRelayFee(const CTransaction& tx, unsigned int nBytes, bool fAllowF
// 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;

View file

@ -548,7 +548,7 @@ void CoinControlDialog::updateLabels(WalletModel *model, QDialog* dialog)
nBytes -= 34;
// Fee
nPayFee = CWallet::GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
nPayFee = CWallet::GetMinimumFee(txDummy, nBytes, nTxConfirmTarget, mempool);
// Allow free?
double dPriorityNeeded = mempoolEstimatePriority;

View file

@ -528,7 +528,7 @@ void SendCoinsDialog::processSendCoinsReturn(const WalletModel::SendCoinsReturn
msgParams.second = CClientUIInterface::MSG_ERROR;
break;
case WalletModel::AbsurdFee:
msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), 10000000));
msgParams.first = tr("A fee higher than %1 is considered an absurdly high fee.").arg(BitcoinUnits::formatWithUnit(model->getOptionsModel()->getDisplayUnit(), 100 * COIN));
break;
case WalletModel::PaymentRequestExpired:
msgParams.first = tr("Payment request expired.");

View file

@ -290,8 +290,8 @@ WalletModel::SendCoinsReturn WalletModel::prepareTransaction(WalletModelTransact
return TransactionCreationFailed;
}
// reject absurdly high fee > 0.1 bitcoin
if (nFeeRequired > 10000000)
// reject absurdly high fee > 100 DOGE
if (nFeeRequired > (100 * COIN))
return AbsurdFee;
}

View file

@ -184,7 +184,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));
@ -195,7 +195,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];
#ifdef ENABLE_WALLET
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey), strprintf("IsMine %d", i));

View file

@ -343,7 +343,7 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
t.vout[0].nValue = 501; // dust
BOOST_CHECK(!IsStandardTx(t, reason));
t.vout[0].nValue = 601; // not dust
t.vout[0].nValue = COIN; // not dust
BOOST_CHECK(IsStandardTx(t, reason));
t.vout[0].scriptPubKey = CScript() << OP_1;

View file

@ -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>
@ -307,4 +308,39 @@ BOOST_AUTO_TEST_CASE(coin_selection_tests)
empty_wallet();
}
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()

View file

@ -10,6 +10,7 @@
#include "coincontrol.h"
#include "consensus/consensus.h"
#include "consensus/validation.h"
#include "dogecoin.h"
#include "main.h"
#include "net.h"
#include "script/script.h"
@ -40,7 +41,7 @@ bool fPayAtLeastCustomFee = true;
* Fees smaller than this (in satoshi) are considered zero fee (for transaction creation)
* Override with -mintxfee
*/
CFeeRate CWallet::minTxFee = CFeeRate(1000);
CFeeRate CWallet::minTxFee = CFeeRate(COIN);
/** @defgroup mapWallet
*
@ -1935,7 +1936,7 @@ bool CWallet::CreateTransaction(const vector<CRecipient>& vecSend,
break;
}
CAmount nFeeNeeded = GetMinimumFee(nBytes, nTxConfirmTarget, mempool);
CAmount nFeeNeeded = GetMinimumFee(txNew, nBytes, nTxConfirmTarget, mempool);
// If we made it here and we aren't even able to meet the relay fee on the next pass, give up
// because we must be at the maximum allowed fee.
@ -2010,8 +2011,12 @@ bool CWallet::CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey)
return true;
}
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)
{
// Dogecoin: Round TX bytes up to the next 1,000 bytes
nTxBytes += 1000 - (nTxBytes % 1000);
// payTxFee is user-set "I want to pay this much"
CAmount nFeeNeeded = payTxFee.GetFee(nTxBytes);
// user selected total at least (default=true)
@ -2022,8 +2027,11 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge
nFeeNeeded = pool.estimateFee(nConfirmTarget).GetFee(nTxBytes);
// ... unless we don't have enough mempool data, in which case fall
// back to a hard-coded fee
if (nFeeNeeded == 0)
if (nFeeNeeded == 0) {
nFeeNeeded = minTxFee.GetFee(nTxBytes);
// Dogecoin: Add an increased fee for each dust output
nFeeNeeded += GetDogecoinDustFee(tx.vout, minTxFee);
}
// prevent user from paying a non-sense fee (like 1 satoshi): 0 < fee < minRelayFee
if (nFeeNeeded < ::minRelayTxFee.GetFee(nTxBytes))
nFeeNeeded = ::minRelayTxFee.GetFee(nTxBytes);
@ -2034,8 +2042,6 @@ CAmount CWallet::GetMinimumFee(unsigned int nTxBytes, unsigned int nConfirmTarge
}
DBErrors CWallet::LoadWallet(bool& fFirstRunRet)
{
if (!fFileBacked)

View file

@ -42,9 +42,9 @@ extern bool fPayAtLeastCustomFee;
//! -paytxfee default
static const CAmount DEFAULT_TRANSACTION_FEE = 0;
//! -paytxfee will warn if called with a higher fee than this amount (in satoshis) per KB
static const CAmount nHighTransactionFeeWarning = 0.01 * COIN;
static const CAmount nHighTransactionFeeWarning = 10 * COIN;
//! -maxtxfee default
static const CAmount DEFAULT_TRANSACTION_MAXFEE = 0.1 * COIN;
static const CAmount DEFAULT_TRANSACTION_MAXFEE = 100 * COIN;
//! -txconfirmtarget default
static const unsigned int DEFAULT_TX_CONFIRM_TARGET = 2;
//! -maxtxfee will warn if called with a higher fee than this amount (in satoshis)
@ -573,7 +573,7 @@ public:
bool CommitTransaction(CWalletTx& wtxNew, CReserveKey& reservekey);
static CFeeRate minTxFee;
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);
bool NewKeyPool();
bool TopUpKeyPool(unsigned int kpSize = 0);