diff --git a/src/init.cpp b/src/init.cpp index d8d8a856c4..bdc4ee623e 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -510,6 +510,7 @@ void SetupServerArgs() gArgs.AddArg("-regtest-minttoken-simulate-mainnet", "Simulate mainnet for minttokens on regtest - default behavior on regtest is to allow anyone to mint mintable tokens for ease of testing", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS); gArgs.AddArg("-simulatemainnet", "Configure the regtest network to mainnet target timespan and spacing ", ArgsManager::ALLOW_ANY | ArgsManager::DEBUG_ONLY, OptionsCategory::OPTIONS); gArgs.AddArg("-dexstats", strprintf("Enable storing live dex data in DB (default: %u)", DEFAULT_DEXSTATS), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); + gArgs.AddArg("-blocktimeordering", strprintf("Whether to order transactions by time, otherwise ordered by fee (default: %u)", DEFAULT_FEE_ORDERING), ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS); #ifdef USE_UPNP #if USE_UPNP gArgs.AddArg("-upnp", "Use UPnP to map the listening port (default: 1 when listening and no -proxy)", ArgsManager::ALLOW_ANY, OptionsCategory::CONNECTION); diff --git a/src/miner.cpp b/src/miner.cpp index e6a426b649..48cc0079de 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -216,7 +216,14 @@ std::unique_ptr BlockAssembler::CreateNewBlock(const CScript& sc if (!blockTime) { UpdateTime(pblock, consensus, pindexPrev); // update time before tx packaging } - addPackageTxs(nPackagesSelected, nDescendantsUpdated, nHeight, mnview); + + const auto timeOrdering = gArgs.GetBoolArg("-blocktimeordering", DEFAULT_FEE_ORDERING); + if (timeOrdering) { + addPackageTxs(nPackagesSelected, nDescendantsUpdated, nHeight, mnview); + } else { + addPackageTxs(nPackagesSelected, nDescendantsUpdated, nHeight, mnview); + } + // TXs for the creationTx field in new tokens created via token split if (nHeight >= chainparams.GetConsensus().FortCanningCrunchHeight) { @@ -483,6 +490,7 @@ void BlockAssembler::SortForBlock(const CTxMemPool::setEntries& package, std::ve // Each time through the loop, we compare the best transaction in // mapModifiedTxs with the next transaction in the mempool to decide what // transaction package to work on next. +template void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated, int nHeight, CCustomCSView &view) { // mapModifiedTx will store sorted packages after they are modified @@ -495,7 +503,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda // and modifying them for their already included ancestors UpdatePackagesForAdded(inBlock, mapModifiedTx); - CTxMemPool::indexed_transaction_set::index::type::iterator mi = mempool.mapTx.get().begin(); + auto mi = mempool.mapTx.get().begin(); CTxMemPool::txiter iter; // Limit the number of attempts to add transactions to the block when it is @@ -510,10 +518,10 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda // Copy of the view CCoinsViewCache coinsView(&::ChainstateActive().CoinsTip()); - while (mi != mempool.mapTx.get().end() || !mapModifiedTx.empty()) + while (mi != mempool.mapTx.get().end() || !mapModifiedTx.empty()) { // First try to find a new transaction in mapTx to evaluate. - if (mi != mempool.mapTx.get().end() && + if (mi != mempool.mapTx.get().end() && SkipMapTxEntry(mempool.mapTx.project<0>(mi), mapModifiedTx, failedTx)) { ++mi; continue; @@ -524,7 +532,7 @@ void BlockAssembler::addPackageTxs(int &nPackagesSelected, int &nDescendantsUpda bool fUsingModified = false; modtxscoreiter modit = mapModifiedTx.get().begin(); - if (mi == mempool.mapTx.get().end()) { + if (mi == mempool.mapTx.get().end()) { // We're out of entries in mapTx; use the entry from mapModifiedTx iter = modit->iter; fUsingModified = true; diff --git a/src/miner.h b/src/miner.h index 254a9a1018..9d583047e7 100644 --- a/src/miner.h +++ b/src/miner.h @@ -190,6 +190,7 @@ class BlockAssembler /** Add transactions based on feerate including unconfirmed ancestors * Increments nPackagesSelected / nDescendantsUpdated with corresponding * statistics from the package selection (for logging statistics). */ + template void addPackageTxs(int &nPackagesSelected, int &nDescendantsUpdated, int nHeight, CCustomCSView &view) EXCLUSIVE_LOCKS_REQUIRED(mempool.cs); // helper functions for addPackageTxs() diff --git a/src/policy/fees.cpp b/src/policy/fees.cpp index 6af72cf3a7..c4e69981f2 100644 --- a/src/policy/fees.cpp +++ b/src/policy/fees.cpp @@ -10,6 +10,7 @@ #include #include #include +#include static constexpr double INF_FEERATE = 1e99; @@ -787,6 +788,11 @@ CFeeRate CBlockPolicyEstimator::estimateSmartFee(int confTarget, FeeCalculation { LOCK(m_cs_fee_estimator); + // If block ordering by time is enabled return 0 to let fallback or discard fee be used. + if (gArgs.GetBoolArg("-blocktimeordering", DEFAULT_FEE_ORDERING)) { + return 0; + } + if (feeCalc) { feeCalc->desiredTarget = confTarget; feeCalc->returnedTarget = confTarget; diff --git a/src/rpc/mining.cpp b/src/rpc/mining.cpp index 2189f7dff2..2729afa8f2 100644 --- a/src/rpc/mining.cpp +++ b/src/rpc/mining.cpp @@ -979,6 +979,8 @@ static UniValue estimatesmartfee(const JSONRPCRequest& request) CFeeRate feeRate = ::feeEstimator.estimateSmartFee(conf_target, &feeCalc, conservative); if (feeRate != CFeeRate(0)) { result.pushKV("feerate", ValueFromAmount(feeRate.GetFeePerK())); + } else if (gArgs.GetBoolArg("-blocktimeordering", DEFAULT_FEE_ORDERING)) { + result.pushKV("feerate", ValueFromAmount(DEFAULT_TRANSACTION_MINFEE)); } else { errors.push_back("Insufficient data or no feerate found"); result.pushKV("errors", errors); diff --git a/src/validation.h b/src/validation.h index f0a16ae4ad..2a7e12ac5c 100644 --- a/src/validation.h +++ b/src/validation.h @@ -133,6 +133,8 @@ static const bool DEFAULT_FEEFILTER = true; static const bool DEFAULT_DEXSTATS = false; /** Default for tracking amount negated by negative interest in attributes */ static const bool DEFAULT_NEGATIVE_INTEREST = false; +/** Default for using TX fee ordering in blocks */ +static const bool DEFAULT_FEE_ORDERING = false; /** Maximum number of headers to announce when relaying blocks with headers message.*/ static const unsigned int MAX_BLOCKS_TO_ANNOUNCE = 8; diff --git a/test/functional/feature_loan_vault.py b/test/functional/feature_loan_vault.py index 8271a31890..2d8ad7638f 100755 --- a/test/functional/feature_loan_vault.py +++ b/test/functional/feature_loan_vault.py @@ -81,13 +81,12 @@ def move_to_fork(self): def setup_loanschemes(self): self.nodes[0].createloanscheme(175, 3, 'LOAN0001') + self.nodes[0].generate(1) self.nodes[0].createloanscheme(150, 2.5, 'LOAN000A') self.nodes[0].createloanscheme(200, 2, 'LOAN0002') self.nodes[0].createloanscheme(350, 1.5, 'LOAN0003') self.nodes[0].createloanscheme(550, 1.5, 'LOAN0004') self.nodes[0].generate(1) - self.nodes[0].setdefaultloanscheme('LOAN0001') - self.nodes[0].generate(1) def create_vaults(self): owner_addr_0 = self.nodes[0].getnewaddress('', 'legacy') diff --git a/test/lint/lint-circular-dependencies.sh b/test/lint/lint-circular-dependencies.sh index 968a839eff..e9944d5c7d 100755 --- a/test/lint/lint-circular-dependencies.sh +++ b/test/lint/lint-circular-dependencies.sh @@ -67,9 +67,9 @@ EXPECTED_CIRCULAR_DEPENDENCIES=( "masternodes/mn_checks -> validation -> wallet/wallet -> masternodes/mn_checks" "net_processing -> validation -> net_processing" "policy/fees -> txmempool -> policy/fees" - "policy/fees -> txmempool -> validation -> policy/fees" - "policy/fees -> txmempool -> validation -> wallet/wallet -> policy/fees" - "policy/fees -> txmempool -> validation -> wallet/wallet -> util/fees -> policy/fees" + "policy/fees -> validation -> policy/fees" + "policy/fees -> validation -> wallet/wallet -> policy/fees" + "policy/fees -> validation -> wallet/wallet -> util/fees -> policy/fees" "pos -> pos_kernel -> pos" "pos -> validation -> pos" "pos -> validation -> txdb -> pos"