diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f93aa11ef4ff1..bac9a01f251d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -373,6 +373,17 @@ jobs: file-env: './ci/test/00_setup_env_native_msan.sh' steps: + - name: Free disk space + if: ${{ needs.runners.outputs.use-cirrus-runners != 'true' }} + run: | + # Free up disk space on GitHub-hosted runners + sudo rm -rf /usr/share/dotnet || true + sudo rm -rf /usr/local/lib/android || true + sudo rm -rf /opt/ghc || true + sudo rm -rf /opt/hostedtoolcache/CodeQL || true + sudo docker image prune --all --force || true + df -h + - *CHECKOUT - name: Configure environment diff --git a/contrib/devtools/circular-dependencies.py b/contrib/devtools/circular-dependencies.py index 409d62424cc50..b742a8cea6718 100755 --- a/contrib/devtools/circular-dependencies.py +++ b/contrib/devtools/circular-dependencies.py @@ -25,7 +25,6 @@ def module_name(path): return path if path.endswith(".h"): return path[:-2] - return path if path.endswith(".c"): return path[:-2] if path.endswith(".cpp"): diff --git a/contrib/devtools/gen-manpages.py b/contrib/devtools/gen-manpages.py index f872304d180a9..3e965841724d2 100755 --- a/contrib/devtools/gen-manpages.py +++ b/contrib/devtools/gen-manpages.py @@ -93,7 +93,6 @@ footer.flush() # Call the binaries through help2man to produce a manual page for each of them. - if True: - outname = os.path.join(mandir, os.path.basename(abspath) + '.1') - print(f'Generating {outname}…') - subprocess.run([help2man, '-N', '--version-string=' + verstr, '--include=' + footer.name, '-o', outname, abspath], check=True) + outname = os.path.join(mandir, os.path.basename(abspath) + '.1') + print(f'Generating {outname}…') + subprocess.run([help2man, '-N', '--version-string=' + verstr, '--include=' + footer.name, '-o', outname, abspath], check=True) diff --git a/src/crypto/sha256.cpp b/src/crypto/sha256.cpp index 4c466d7934192..f7e06355ff8ef 100644 --- a/src/crypto/sha256.cpp +++ b/src/crypto/sha256.cpp @@ -14,8 +14,11 @@ #if !defined(DISABLE_OPTIMIZED_SHA256) #include -#if defined(__linux__) && defined(ENABLE_ARM_SHANI) +#if defined(__linux__) && (defined(ENABLE_ARM_SHANI) || defined(ENABLE_POWER8)) #include +#endif + +#if defined(__linux__) && defined(ENABLE_ARM_SHANI) #include #endif @@ -63,7 +66,6 @@ void Transform_2way(unsigned char* out, const unsigned char* in); #endif // DISABLE_OPTIMIZED_SHA256 #if defined(__linux__) && defined(ENABLE_POWER8) -#include namespace sha256_power8 { void Transform_4way(unsigned char* out, const unsigned char* in); diff --git a/src/kernel/mempool_entry.h b/src/kernel/mempool_entry.h index 9b38be4d8604d..2ce8514ac2bfe 100644 --- a/src/kernel/mempool_entry.h +++ b/src/kernel/mempool_entry.h @@ -190,6 +190,7 @@ class CTxMemPoolEntry int32_t GetTxWeight() const { return nTxWeight; } std::chrono::seconds GetTime() const { return std::chrono::seconds{nTime}; } unsigned int GetHeight() const { return entryHeight; } + unsigned int GetCachedHeight() const { return cachedHeight; } uint64_t GetSequence() const { return entry_sequence; } int32_t GetExtraWeight() const { return m_extra_weight; } int64_t GetSigOpCost() const { return sigOpCost; } diff --git a/src/node/miner.cpp b/src/node/miner.cpp index 8038ac83a41bb..f9f779ce1640a 100644 --- a/src/node/miner.cpp +++ b/src/node/miner.cpp @@ -17,17 +17,21 @@ #include #include #include +#include #include #include #include #include +#include #include #include #include #include #include +#include #include +#include namespace node { @@ -506,4 +510,149 @@ void BlockAssembler::addPackageTxs(const CTxMemPool& mempool, int& nPackagesSele nDescendantsUpdated += UpdatePackagesForAdded(mempool, ancestors, mapModifiedTx); } } + +// We want to sort transactions by coin age priority +typedef std::pair TxCoinAgePriority; + +struct TxCoinAgePriorityCompare +{ + bool operator()(const TxCoinAgePriority& a, const TxCoinAgePriority& b) + { + if (a.first == b.first) + return CompareTxMemPoolEntryByScore()(*(b.second), *(a.second)); //Reverse order to make sort less than + return a.first < b.first; + } +}; + +bool BlockAssembler::isStillDependent(const CTxMemPool& mempool, CTxMemPool::txiter iter) +{ + assert(iter != mempool.mapTx.end()); + for (const auto& parent : iter->GetMemPoolParentsConst()) { + auto parent_it = mempool.mapTx.iterator_to(parent); + if (!inBlock.count(parent_it)) { + return true; + } + } + return false; +} + +bool BlockAssembler::TestForBlock(CTxMemPool::txiter iter) +{ + uint64_t packageSize = iter->GetSizeWithAncestors(); + int64_t packageSigOps = iter->GetSigOpCostWithAncestors(); + if (!TestPackage(packageSize, packageSigOps)) { + // If the block is so close to full that no more txs will fit + // or if we've tried more than 50 times to fill remaining space + // then flag that the block is finished + if (nBlockWeight > m_options.nBlockMaxWeight - 400 || nBlockSigOpsCost > MAX_BLOCK_SIGOPS_COST - 8 || lastFewTxs > 50) { + blockFinished = true; + return false; + } + // Once we're within 4000 weight of a full block, only look at 50 more txs + // to try to fill the remaining space. + if (nBlockWeight > m_options.nBlockMaxWeight - 4000) { + ++lastFewTxs; + } + return false; + } + + CTxMemPool::setEntries package; + package.insert(iter); + if (!TestPackageTransactions(package)) { + if (nBlockSize > m_options.nBlockMaxSize - 100 || lastFewTxs > 50) { + blockFinished = true; + return false; + } + if (nBlockSize > m_options.nBlockMaxSize - 1000) { + ++lastFewTxs; + } + return false; + } + + return true; +} + +void BlockAssembler::addPriorityTxs(const CTxMemPool& mempool, int &nPackagesSelected) +{ + AssertLockHeld(mempool.cs); + + // How much of the block should be dedicated to high-priority transactions, + // included regardless of the fees they pay + uint64_t nBlockPrioritySize = gArgs.GetIntArg("-blockprioritysize", DEFAULT_BLOCK_PRIORITY_SIZE); + if (m_options.nBlockMaxSize < nBlockPrioritySize) { + nBlockPrioritySize = m_options.nBlockMaxSize; + } + + if (nBlockPrioritySize <= 0) { + return; + } + + bool fSizeAccounting = fNeedSizeAccounting; + fNeedSizeAccounting = true; + + // This vector will be sorted into a priority queue: + std::vector vecPriority; + TxCoinAgePriorityCompare pricomparer; + std::map waitPriMap; + typedef std::map::iterator waitPriIter; + double actualPriority = -1; + + vecPriority.reserve(mempool.mapTx.size()); + for (auto mi = mempool.mapTx.begin(); mi != mempool.mapTx.end(); ++mi) { + double dPriority = mi->GetPriority(nHeight); + CAmount dummy; + mempool.ApplyDeltas(mi->GetTx().GetHash(), dPriority, dummy); + vecPriority.emplace_back(dPriority, mi); + } + std::make_heap(vecPriority.begin(), vecPriority.end(), pricomparer); + + CTxMemPool::txiter iter; + while (!vecPriority.empty() && !blockFinished) { // add a tx from priority queue to fill the blockprioritysize + iter = vecPriority.front().second; + actualPriority = vecPriority.front().first; + std::pop_heap(vecPriority.begin(), vecPriority.end(), pricomparer); + vecPriority.pop_back(); + + // If tx already in block, skip + if (inBlock.count(iter)) { + assert(false); // shouldn't happen for priority txs + continue; + } + + // If tx is dependent on other mempool txs which haven't yet been included + // then put it in the waitSet + if (isStillDependent(mempool, iter)) { + waitPriMap.insert(std::make_pair(iter, actualPriority)); + continue; + } + + // If this tx fits in the block add it, otherwise keep looping + if (TestForBlock(iter)) { + AddToBlock(mempool, iter); + + ++nPackagesSelected; + + // If now that this txs is added we've surpassed our desired priority size + // or have dropped below the minimum priority threshold, then we're done adding priority txs + if (nBlockSize >= nBlockPrioritySize || actualPriority <= MINIMUM_TX_PRIORITY) { + break; + } + + // This tx was successfully added, so + // add transactions that depend on this one to the priority queue to try again + for (const auto& child : iter->GetMemPoolChildrenConst()) + { + auto child_it = mempool.mapTx.iterator_to(child); + waitPriIter wpiter = waitPriMap.find(child_it); + if (wpiter != waitPriMap.end()) { + vecPriority.emplace_back(wpiter->second, child_it); + std::push_heap(vecPriority.begin(), vecPriority.end(), pricomparer); + waitPriMap.erase(wpiter); + } + } + } + } + fNeedSizeAccounting = fSizeAccounting; +} + } // namespace node diff --git a/src/node/types.h b/src/node/types.h index a9d9a71c4ec34..a82cf1ccc5d81 100644 --- a/src/node/types.h +++ b/src/node/types.h @@ -17,7 +17,6 @@ #include #include -#include #include