From 61f24562fdeea946b59684274c169da34796f324 Mon Sep 17 00:00:00 2001 From: Mononaut Date: Fri, 24 Mar 2023 09:49:02 +0900 Subject: [PATCH] tighten sanity checks in block audit --- backend/src/api/audit.ts | 68 ++++++++++++++++++++++------------------ 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/backend/src/api/audit.ts b/backend/src/api/audit.ts index d0d677740..639066af0 100644 --- a/backend/src/api/audit.ts +++ b/backend/src/api/audit.ts @@ -39,17 +39,19 @@ class Audit { } else { isCensored[txid] = true; } - displacedWeight += mempool[txid].weight; + displacedWeight += mempool[txid]?.weight || 0; } else { - matchedWeight += mempool[txid].weight; + matchedWeight += mempool[txid]?.weight || 0; } - projectedWeight += mempool[txid].weight; + projectedWeight += mempool[txid]?.weight || 0; inTemplate[txid] = true; } - displacedWeight += (4000 - transactions[0].weight); - projectedWeight += transactions[0].weight; - matchedWeight += transactions[0].weight; + if (transactions[0]) { + displacedWeight += (4000 - transactions[0].weight); + projectedWeight += transactions[0].weight; + matchedWeight += transactions[0].weight; + } // we can expect an honest miner to include 'displaced' transactions in place of recent arrivals and censored txs // these displaced transactions should occupy the first N weight units of the next projected block @@ -59,19 +61,22 @@ class Audit { let failures = 0; while (projectedBlocks[1] && index < projectedBlocks[1].transactionIds.length && failures < 500) { const txid = projectedBlocks[1].transactionIds[index]; - const fits = (mempool[txid].weight - displacedWeightRemaining) < 4000; - const feeMatches = mempool[txid].effectiveFeePerVsize >= lastFeeRate; - if (fits || feeMatches) { - isDisplaced[txid] = true; - if (fits) { - lastFeeRate = Math.min(lastFeeRate, mempool[txid].effectiveFeePerVsize); + const tx = mempool[txid]; + if (tx) { + const fits = (tx.weight - displacedWeightRemaining) < 4000; + const feeMatches = tx.effectiveFeePerVsize >= lastFeeRate; + if (fits || feeMatches) { + isDisplaced[txid] = true; + if (fits) { + lastFeeRate = Math.min(lastFeeRate, tx.effectiveFeePerVsize); + } + if (tx.firstSeen == null || (now - (tx?.firstSeen || 0)) > PROPAGATION_MARGIN) { + displacedWeightRemaining -= tx.weight; + } + failures = 0; + } else { + failures++; } - if (mempool[txid].firstSeen == null || (now - (mempool[txid]?.firstSeen || 0)) > PROPAGATION_MARGIN) { - displacedWeightRemaining -= mempool[txid].weight; - } - failures = 0; - } else { - failures++; } index++; } @@ -108,20 +113,23 @@ class Audit { index = projectedBlocks[0].transactionIds.length - 1; while (index >= 0) { const txid = projectedBlocks[0].transactionIds[index]; - if (overflowWeightRemaining > 0) { - if (isCensored[txid]) { - delete isCensored[txid]; - } - if (mempool[txid].effectiveFeePerVsize > maxOverflowRate) { - maxOverflowRate = mempool[txid].effectiveFeePerVsize; - rateThreshold = (Math.ceil(maxOverflowRate * 100) / 100) + 0.005; - } - } else if (mempool[txid].effectiveFeePerVsize <= rateThreshold) { // tolerance of 0.01 sat/vb + rounding - if (isCensored[txid]) { - delete isCensored[txid]; + const tx = mempool[txid]; + if (tx) { + if (overflowWeightRemaining > 0) { + if (isCensored[txid]) { + delete isCensored[txid]; + } + if (tx.effectiveFeePerVsize > maxOverflowRate) { + maxOverflowRate = tx.effectiveFeePerVsize; + rateThreshold = (Math.ceil(maxOverflowRate * 100) / 100) + 0.005; + } + } else if (tx.effectiveFeePerVsize <= rateThreshold) { // tolerance of 0.01 sat/vb + rounding + if (isCensored[txid]) { + delete isCensored[txid]; + } } + overflowWeightRemaining -= (mempool[txid]?.weight || 0); } - overflowWeightRemaining -= (mempool[txid]?.weight || 0); index--; }