Merge pull request #5958 from mempool/mononaut/standardize-ephemeral-dust

This commit is contained in:
wiz
2025-07-11 23:41:35 -10:00
committed by GitHub
5 changed files with 45 additions and 5 deletions

View File

@@ -328,7 +328,7 @@ export class Common {
}
if (vout.value < (dustSize * DUST_RELAY_TX_FEE)) {
// under minimum output size
return true;
return !Common.isStandardEphemeralDust(tx, height);
}
}
}
@@ -407,6 +407,26 @@ export class Common {
return false;
}
// Ephemeral dust is a new concept that allows a single dust output in a transaction, provided the transaction is zero fee
static EPHEMERAL_DUST_STANDARDNESS_ACTIVATION_HEIGHT = {
'testnet4': 90_500,
'testnet': 4_550_000,
'signet': 260_000,
'': 905_000,
};
static isStandardEphemeralDust(tx: TransactionExtended, height?: number): boolean {
if (
tx.fee === 0
&& (height == null || (
this.EPHEMERAL_DUST_STANDARDNESS_ACTIVATION_HEIGHT[config.MEMPOOL.NETWORK]
&& height >= this.EPHEMERAL_DUST_STANDARDNESS_ACTIVATION_HEIGHT[config.MEMPOOL.NETWORK]
))
) {
return true;
}
return false;
}
static getNonWitnessSize(tx: TransactionExtended): number {
let weight = tx.weight;
let hasWitness = false;

View File

@@ -750,7 +750,7 @@ export class TrackerComponent implements OnInit, OnDestroy {
checkAccelerationEligibility() {
if (this.tx) {
this.tx.flags = getTransactionFlags(this.tx, null, null, this.tx.status?.block_time, this.stateService.network);
this.tx.flags = getTransactionFlags(this.tx, null, null, this.tx.status?.block_height || (this.stateService.latestBlockHeight + 1), this.stateService.network);
const replaceableInputs = (this.tx.flags & (TransactionFlags.sighash_none | TransactionFlags.sighash_acp)) > 0n;
const highSigop = (this.tx.sigops * 20) > this.tx.weight;
this.eligibleForAcceleration = !replaceableInputs && !highSigop;

View File

@@ -211,7 +211,7 @@ export class TransactionRawComponent implements OnInit, OnDestroy {
replaceUrl: true
});
this.transaction.flags = getTransactionFlags(this.transaction, this.cpfpInfo, null, null, this.stateService.network);
this.transaction.flags = getTransactionFlags(this.transaction, this.cpfpInfo, null, this.transaction.status?.block_height || (this.stateService.latestBlockHeight + 1), this.stateService.network);
this.filters = this.transaction.flags ? toFilters(this.transaction.flags).filter(f => f.txPage) : [];
if (this.transaction.sigops >= 0) {
this.adjustedVsize = Math.max(this.transaction.weight / 4, this.transaction.sigops * 5);

View File

@@ -930,7 +930,7 @@ export class TransactionComponent implements OnInit, AfterViewInit, OnDestroy {
this.segwitEnabled = !this.tx.status.confirmed || isFeatureActive(this.stateService.network, this.tx.status.block_height, 'segwit');
this.taprootEnabled = !this.tx.status.confirmed || isFeatureActive(this.stateService.network, this.tx.status.block_height, 'taproot');
this.rbfEnabled = !this.tx.status.confirmed || isFeatureActive(this.stateService.network, this.tx.status.block_height, 'rbf');
this.tx.flags = getTransactionFlags(this.tx, null, null, this.tx.status?.block_time, this.stateService.network);
this.tx.flags = getTransactionFlags(this.tx, null, null, this.tx.status?.block_height || (this.stateService.latestBlockHeight + 1), this.stateService.network);
this.filters = this.tx.flags ? toFilters(this.tx.flags).filter(f => f.txPage) : [];
this.checkAccelerationEligibility();
} else {

View File

@@ -437,7 +437,7 @@ export function isNonStandard(tx: Transaction, height?: number, network?: string
}
if (vout.value < (dustSize * DUST_RELAY_TX_FEE)) {
// under minimum output size
return true;
return !isStandardEphemeralDust(tx, height, network);
}
}
}
@@ -497,6 +497,26 @@ function isNonStandardAnchor(tx: Transaction, height?: number, network?: string)
return false;
}
// Ephemeral dust is a new concept that allows a single dust output in a transaction, provided the transaction is zero fee
const EPHEMERAL_DUST_STANDARDNESS_ACTIVATION_HEIGHT = {
'testnet4': 90_500,
'testnet': 4_550_000,
'signet': 260_000,
'': 905_000,
};
function isStandardEphemeralDust(tx: Transaction, height?: number, network?: string): boolean {
if (
tx.fee === 0
&& (height == null || (
EPHEMERAL_DUST_STANDARDNESS_ACTIVATION_HEIGHT[network]
&& height >= EPHEMERAL_DUST_STANDARDNESS_ACTIVATION_HEIGHT[network]
))
) {
return true;
}
return false;
}
// A witness program is any valid scriptpubkey that consists of a 1-byte push opcode
// followed by a data push between 2 and 40 bytes.
// https://github.com/bitcoin/bitcoin/blob/2c79abc7ad4850e9e3ba32a04c530155cda7f980/src/script/script.cpp#L224-L240