A proposal on GitHub I found Highly interesting and a better improvement, dealing with spammers/congestion.

I’m exploring a potential default filter or consensus-level rule (since a large number of people believe that default filters don't work) to discourage UTXO-bloat patterns without touching Script, witness data, or the block size limit.

The idea is to target “bulk dust” transactions — those that create large numbers of extremely small outputs — which are the main cause of long-term UTXO set growth.

These types of "bulk dust" transactions have been the No. 1 reason cited for wanting to expand the default OP_RETURN limit... and removing that limit obviously influenced BIP 444. So it appears to me that there is overwhelming majority support for limiting these types of "bulk dust" transactions, as they do present a legitimate concern for node runners.

Concept

Flag a transaction as “bulk dust” if:

When flagged, it would be considered nonstandard (relay policy) or invalid (if soft-forked into consensus).

TinyTx threshold (dynamic halving schedule)

I originally considered a constant definition of what was a "tiny" Tx to be 1,000 sats... but some might still just use 1,001 sats, right? Plus there very likely will be a time where there is a valid use-case of >100 outputs under 1,000 sats.

Rather than fixing the “tiny” threshold to a constant like 1,000 sats, the rule defines it as a decreasing function of block height, starting high and gradually tightening over time.

Year ---- Block Height -- TinyTx Threshold
2028 --- ~activation ---- 4096 sats
2032 --- ~1,260,000 ---- 2048 sats
2036 --- ~1,470,000 ---- 1024 sats
2040 --- ~1,680,000 ---- 512 sats
… -- every 210,000 blocks -- … until 1 sat floor

This gradual halving ensures the definition of "tiny" stays relevant as Bitcoin’s value rises.
For example, if 1 sat = $1 someday, having 100 outputs worth <1,000 sats each would no longer represent spam — but rather normal payments.
By then, the TinyTx limit would already have adjusted down automatically.

Patterns this would limit

These use cases rely on cheap, numerous outputs — making them several times more costly under this rule.

Non-goals / unaffected

Why a ratio and a count?

Requiring both (tiny_count >= 100) and (tiny_ratio >= 60%) helps avoid false positives, such as legitimate custodial payouts or consolidation transactions with mixed values.
It specifically filters transactions that are mostly dust, rather than merely containing some.

Inquiry

Intent

This proposal doesn’t censor any monetary transaction or prevent inscriptions; it simply prices storage according to resource cost.
It keeps the chain “light and nimble” for everyday payments while allowing future flexibility — because the TinyTx definition decreases automatically in line with halvings and Bitcoin’s long-term value growth.

CODE SKETCHES
(with minimal syntax highlighting here: https://pastebin.com/9qdQCH83)

RELAY POLICY FILTER sketch —

// 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) sketch —

// 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

--
You received this message because you are subscribed to the Google Groups "Bitcoin Development Mailing List" group.
To unsubscribe from this group and stop receiving emails from it, send an email to bitcoindev+unsubscribe@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/bitcoindev/b0dee827-c2fe-4a68-9b41-f1447ba3c1d3n%40googlegroups.com.