Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- ==========================================================================================================
- // *** RELAY POLICY FILTER ***
- // Place in src/policy/policy.cpp, and call from within IsStandardTx() before returning:
- // if (IsBulkDust(tx, reason))
- // return false; // reject as nonstandard
- // ==========================================================================================================
- bool IsBulkDust(const CTransaction& tx, std::string& reason)
- {
- static constexpr int MAX_TINY_OUTPUTS = 100; // >=100 tiny outputs triggers ratio check
- static constexpr double TINY_RATIO_THRESHOLD = 0.6; // >=60% of all outputs tiny → reject
- static constexpr CAmount BASE_TINY_THRESHOLD = 4096; // starting tiny threshold (sats)
- static constexpr int64_t FIRST_TINY_HALVING_H = 1260000; // first halving of tiny threshold
- static constexpr int64_t HALVING_INTERVAL = 210000; // blocks per subsequent halving
- static constexpr CAmount MIN_TINY_FLOOR = 1; // never below 1 sat
- const int total = tx.vout.size();
- if (total == 0) return false;
- int currentHeight = chainActive.Tip() ? chainActive.Tip()->nHeight : 0;
- // Era index for TinyTx threshold, anchored at FIRST_TINY_HALVING_H (not subsidy eras)
- int era = 0;
- if (currentHeight >= FIRST_TINY_HALVING_H) {
- era = 1 + static_cast<int>((currentHeight - FIRST_TINY_HALVING_H) / HALVING_INTERVAL);
- }
- CAmount tinyThresh = BASE_TINY_THRESHOLD >> era; // halve per era
- if (tinyThresh < MIN_TINY_FLOOR) tinyThresh = MIN_TINY_FLOOR;
- int tiny = 0;
- for (const auto& out : tx.vout) {
- if (out.nValue < tinyThresh) ++tiny;
- }
- if (tiny >= MAX_TINY_OUTPUTS && (static_cast<double>(tiny) / total) >= TINY_RATIO_THRESHOLD) {
- reason = strprintf("too-many-tiny-outputs(%d of %d, %.2f%%, tiny<%d)",
- tiny, total, 100.0 * tiny / total, tinyThresh);
- return true; // flag as bulk dust (nonstandard)
- }
- return false;
- }
- // ==========================================================================================================
- // *** CONSENSUS (soft-fork, hybrid activation) ***
- // Helpers in src/consensus/tx_check.cpp; activation/enforcement in src/validation.cpp
- // Also define deployment in: src/consensus/params.h, src/chainparams.cpp, src/versionbits.*
- // ==========================================================================================================
- // -----------------------------------------------------------------------
- // --- In src/consensus/tx_check.cpp (helper only; no params needed) ---
- // -----------------------------------------------------------------------
- static constexpr CAmount BASE_TINY_THRESHOLD = 4096;
- static constexpr int64_t FIRST_TINY_HALVING_H = 1260000;
- static constexpr int64_t HALVING_INTERVAL = 210000;
- static constexpr int MAX_TINY_OUTPUTS = 100;
- static constexpr double TINY_RATIO_THRESHOLD = 0.6;
- static constexpr CAmount MIN_TINY_FLOOR = 1;
- bool IsBulkDust(const CTransaction& tx, int currentHeight) // expose via tx_check.h if needed
- {
- const int total = tx.vout.size();
- if (total == 0) return false;
- int era = 0;
- if (currentHeight >= FIRST_TINY_HALVING_H) {
- era = 1 + static_cast<int>((currentHeight - FIRST_TINY_HALVING_H) / HALVING_INTERVAL);
- }
- CAmount tinyThresh = BASE_TINY_THRESHOLD >> era;
- if (tinyThresh < MIN_TINY_FLOOR) tinyThresh = MIN_TINY_FLOOR;
- int tiny = 0;
- for (const auto& out : tx.vout) {
- if (out.nValue < tinyThresh) ++tiny;
- }
- if (tiny >= MAX_TINY_OUTPUTS && (static_cast<double>(tiny) / total) >= TINY_RATIO_THRESHOLD)
- return true;
- return false;
- }
- // -----------------------------------------------------------------------
- // --- In src/validation.cpp (enforcement with hybrid activation) ---
- // -----------------------------------------------------------------------
- #include <consensus/tx_check.h>
- #include <versionbits.h>
- const Consensus::Params& params = chainparams.GetConsensus();
- int currentHeight = chainActive.Tip() ? chainActive.Tip()->nHeight : 0;
- const bool bulk_dust_active =
- DeploymentActiveAtTip(params, Consensus::DEPLOYMENT_BULK_DUST_LIMIT) ||
- (currentHeight >= params.BulkDustActivationHeight);
- if (bulk_dust_active) {
- if (IsBulkDust(tx, currentHeight)) {
- return state.Invalid(TxValidationResult::TX_CONSENSUS, "too-many-tiny-outputs");
- }
- }
- // -----------------------------------------------------------------------
- // --- In src/consensus/params.h ---
- // -----------------------------------------------------------------------
- enum DeploymentPos {
- // ...
- DEPLOYMENT_BULK_DUST_LIMIT,
- MAX_VERSION_BITS_DEPLOYMENTS
- };
- struct Params {
- // ...
- int BulkDustActivationHeight; // height flag-day fallback
- };
- // -----------------------------------------------------------------------
- // --- In src/chainparams.cpp (per-network values; examples only) ---
- // -----------------------------------------------------------------------
- consensus.vDeployments[Consensus::DEPLOYMENT_BULK_DUST_LIMIT].bit = 12;
- consensus.vDeployments[Consensus::DEPLOYMENT_BULK_DUST_LIMIT].nStartTime = 1767225600; // 2026-01-01 UTC
- consensus.vDeployments[Consensus::DEPLOYMENT_BULK_DUST_LIMIT].nTimeout = 1838160000; // 2028-04-01 UTC
- consensus.vDeployments[Consensus::DEPLOYMENT_BULK_DUST_LIMIT].min_activation_height = 969696;
- consensus.BulkDustActivationHeight = 1021021; // flag-day fallback
Advertisement
Add Comment
Please, Sign In to add comment