Merge pull request #4046 from mempool/mononaut/audit-exclude-conflicts
Exclude all conflicting transactions from audit score
This commit is contained in:
		
						commit
						a13c424869
					
				@ -15,7 +15,7 @@ class Audit {
 | 
			
		||||
    const matches: string[] = []; // present in both mined block and template
 | 
			
		||||
    const added: string[] = []; // present in mined block, not in template
 | 
			
		||||
    const fresh: string[] = []; // missing, but firstSeen or lastBoosted within PROPAGATION_MARGIN
 | 
			
		||||
    const fullrbf: string[] = []; // either missing or present, and part of a fullrbf replacement
 | 
			
		||||
    const rbf: string[] = []; // either missing or present, and either part of a full-rbf replacement, or a conflict with the mined block
 | 
			
		||||
    const isCensored = {}; // missing, without excuse
 | 
			
		||||
    const isDisplaced = {};
 | 
			
		||||
    let displacedWeight = 0;
 | 
			
		||||
@ -36,8 +36,9 @@ class Audit {
 | 
			
		||||
    // look for transactions that were expected in the template, but missing from the mined block
 | 
			
		||||
    for (const txid of projectedBlocks[0].transactionIds) {
 | 
			
		||||
      if (!inBlock[txid]) {
 | 
			
		||||
        if (rbfCache.isFullRbf(txid)) {
 | 
			
		||||
          fullrbf.push(txid);
 | 
			
		||||
        // allow missing transactions which either belong to a full rbf tree, or conflict with any transaction in the mined block
 | 
			
		||||
        if (rbfCache.has(txid) && (rbfCache.isFullRbf(txid) || rbfCache.anyInSameTree(txid, (tx) => inBlock[tx.txid]))) {
 | 
			
		||||
          rbf.push(txid);
 | 
			
		||||
        } else if (mempool[txid]?.firstSeen != null && (now - (mempool[txid]?.firstSeen || 0)) <= PROPAGATION_MARGIN) {
 | 
			
		||||
          // tx is recent, may have reached the miner too late for inclusion
 | 
			
		||||
          fresh.push(txid);
 | 
			
		||||
@ -98,8 +99,8 @@ class Audit {
 | 
			
		||||
      if (inTemplate[tx.txid]) {
 | 
			
		||||
        matches.push(tx.txid);
 | 
			
		||||
      } else {
 | 
			
		||||
        if (rbfCache.isFullRbf(tx.txid)) {
 | 
			
		||||
          fullrbf.push(tx.txid);
 | 
			
		||||
        if (rbfCache.has(tx.txid)) {
 | 
			
		||||
          rbf.push(tx.txid);
 | 
			
		||||
        } else if (!isDisplaced[tx.txid]) {
 | 
			
		||||
          added.push(tx.txid);
 | 
			
		||||
        }
 | 
			
		||||
@ -147,7 +148,7 @@ class Audit {
 | 
			
		||||
      added,
 | 
			
		||||
      fresh,
 | 
			
		||||
      sigop: [],
 | 
			
		||||
      fullrbf,
 | 
			
		||||
      fullrbf: rbf,
 | 
			
		||||
      score,
 | 
			
		||||
      similarity,
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -100,6 +100,24 @@ class RbfCache {
 | 
			
		||||
    this.dirtyTrees.add(treeId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public has(txId: string): boolean {
 | 
			
		||||
    return this.txs.has(txId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public anyInSameTree(txId: string, predicate: (tx: RbfTransaction) => boolean): boolean {
 | 
			
		||||
    const tree = this.getRbfTree(txId);
 | 
			
		||||
    if (!tree) {
 | 
			
		||||
      return false;
 | 
			
		||||
    }
 | 
			
		||||
    const txs = this.getTransactionsInTree(tree);
 | 
			
		||||
    for (const tx of txs) {
 | 
			
		||||
      if (predicate(tx)) {
 | 
			
		||||
        return true;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  public getReplacedBy(txId: string): string | undefined {
 | 
			
		||||
    return this.replacedBy.get(txId);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -38,7 +38,7 @@ export default class TxView implements TransactionStripped {
 | 
			
		||||
  value: number;
 | 
			
		||||
  feerate: number;
 | 
			
		||||
  rate?: number;
 | 
			
		||||
  status?: 'found' | 'missing' | 'sigop' | 'fresh' | 'freshcpfp' | 'added' | 'censored' | 'selected' | 'fullrbf';
 | 
			
		||||
  status?: 'found' | 'missing' | 'sigop' | 'fresh' | 'freshcpfp' | 'added' | 'censored' | 'selected' | 'rbf';
 | 
			
		||||
  context?: 'projected' | 'actual';
 | 
			
		||||
  scene?: BlockScene;
 | 
			
		||||
 | 
			
		||||
@ -207,7 +207,7 @@ export default class TxView implements TransactionStripped {
 | 
			
		||||
        return auditColors.censored;
 | 
			
		||||
      case 'missing':
 | 
			
		||||
      case 'sigop':
 | 
			
		||||
      case 'fullrbf':
 | 
			
		||||
      case 'rbf':
 | 
			
		||||
        return marginalFeeColors[feeLevelIndex] || marginalFeeColors[mempoolFeeColors.length - 1];
 | 
			
		||||
      case 'fresh':
 | 
			
		||||
      case 'freshcpfp':
 | 
			
		||||
 | 
			
		||||
@ -53,7 +53,7 @@
 | 
			
		||||
          <td *ngSwitchCase="'freshcpfp'"><span class="badge badge-warning" i18n="transaction.audit.recently-cpfped">Recently CPFP'd</span></td>
 | 
			
		||||
          <td *ngSwitchCase="'added'"><span class="badge badge-warning" i18n="transaction.audit.added">Added</span></td>
 | 
			
		||||
          <td *ngSwitchCase="'selected'"><span class="badge badge-warning" i18n="transaction.audit.marginal">Marginal fee rate</span></td>
 | 
			
		||||
          <td *ngSwitchCase="'fullrbf'"><span class="badge badge-warning" i18n="transaction.audit.fullrbf">Full RBF</span></td>
 | 
			
		||||
          <td *ngSwitchCase="'rbf'"><span class="badge badge-warning" i18n="transaction.audit.conflicting">Conflicting</span></td>
 | 
			
		||||
        </ng-container>
 | 
			
		||||
      </tr>
 | 
			
		||||
    </tbody>
 | 
			
		||||
 | 
			
		||||
@ -339,7 +339,7 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
        const isSelected = {};
 | 
			
		||||
        const isFresh = {};
 | 
			
		||||
        const isSigop = {};
 | 
			
		||||
        const isFullRbf = {};
 | 
			
		||||
        const isRbf = {};
 | 
			
		||||
        this.numMissing = 0;
 | 
			
		||||
        this.numUnexpected = 0;
 | 
			
		||||
 | 
			
		||||
@ -363,7 +363,7 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
            isSigop[txid] = true;
 | 
			
		||||
          }
 | 
			
		||||
          for (const txid of blockAudit.fullrbfTxs || []) {
 | 
			
		||||
            isFullRbf[txid] = true;
 | 
			
		||||
            isRbf[txid] = true;
 | 
			
		||||
          }
 | 
			
		||||
          // set transaction statuses
 | 
			
		||||
          for (const tx of blockAudit.template) {
 | 
			
		||||
@ -381,8 +381,8 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
                }
 | 
			
		||||
              } else if (isSigop[tx.txid]) {
 | 
			
		||||
                tx.status = 'sigop';
 | 
			
		||||
              } else if (isFullRbf[tx.txid]) {
 | 
			
		||||
                tx.status = 'fullrbf';
 | 
			
		||||
              } else if (isRbf[tx.txid]) {
 | 
			
		||||
                tx.status = 'rbf';
 | 
			
		||||
              } else {
 | 
			
		||||
                tx.status = 'missing';
 | 
			
		||||
              }
 | 
			
		||||
@ -398,8 +398,8 @@ export class BlockComponent implements OnInit, OnDestroy {
 | 
			
		||||
              tx.status = 'added';
 | 
			
		||||
            } else if (inTemplate[tx.txid]) {
 | 
			
		||||
              tx.status = 'found';
 | 
			
		||||
            } else if (isFullRbf[tx.txid]) {
 | 
			
		||||
              tx.status = 'fullrbf';
 | 
			
		||||
            } else if (isRbf[tx.txid]) {
 | 
			
		||||
              tx.status = 'rbf';
 | 
			
		||||
            } else {
 | 
			
		||||
              tx.status = 'selected';
 | 
			
		||||
              isSelected[tx.txid] = true;
 | 
			
		||||
 | 
			
		||||
@ -174,7 +174,7 @@ export interface TransactionStripped {
 | 
			
		||||
  vsize: number;
 | 
			
		||||
  value: number;
 | 
			
		||||
  rate?: number; // effective fee rate
 | 
			
		||||
  status?: 'found' | 'missing' | 'sigop' | 'fresh' | 'freshcpfp' | 'added' | 'censored' | 'selected' | 'fullrbf';
 | 
			
		||||
  status?: 'found' | 'missing' | 'sigop' | 'fresh' | 'freshcpfp' | 'added' | 'censored' | 'selected' | 'rbf';
 | 
			
		||||
  context?: 'projected' | 'actual';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -89,7 +89,7 @@ export interface TransactionStripped {
 | 
			
		||||
  vsize: number;
 | 
			
		||||
  value: number;
 | 
			
		||||
  rate?: number; // effective fee rate
 | 
			
		||||
  status?: 'found' | 'missing' | 'sigop' | 'fresh' | 'freshcpfp' | 'added' | 'censored' | 'selected' | 'fullrbf';
 | 
			
		||||
  status?: 'found' | 'missing' | 'sigop' | 'fresh' | 'freshcpfp' | 'added' | 'censored' | 'selected' | 'rbf';
 | 
			
		||||
  context?: 'projected' | 'actual';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user