Enforce block sigop limits in GBT algorithm

This commit is contained in:
Mononaut 2023-05-29 17:21:02 -04:00
parent ec63c822db
commit bf7df08305
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
3 changed files with 12 additions and 1 deletions

View File

@ -223,6 +223,7 @@ class MempoolBlocks {
uid: entry.uid, uid: entry.uid,
fee: entry.fee, fee: entry.fee,
weight: (entry.adjustedVsize * 4), weight: (entry.adjustedVsize * 4),
sigops: entry.sigops,
feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize, feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize,
effectiveFeePerVsize: entry.effectiveFeePerVsize || entry.adjustedFeePerVsize || entry.feePerVsize, effectiveFeePerVsize: entry.effectiveFeePerVsize || entry.adjustedFeePerVsize || entry.feePerVsize,
inputs: entry.vin.map(v => this.getUid(newMempool[v.txid])).filter(uid => uid != null) as number[], inputs: entry.vin.map(v => this.getUid(newMempool[v.txid])).filter(uid => uid != null) as number[],
@ -288,6 +289,7 @@ class MempoolBlocks {
uid: entry.uid || 0, uid: entry.uid || 0,
fee: entry.fee, fee: entry.fee,
weight: (entry.adjustedVsize * 4), weight: (entry.adjustedVsize * 4),
sigops: entry.sigops,
feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize, feePerVsize: entry.adjustedFeePerVsize || entry.feePerVsize,
effectiveFeePerVsize: entry.effectiveFeePerVsize || entry.adjustedFeePerVsize || entry.feePerVsize, effectiveFeePerVsize: entry.effectiveFeePerVsize || entry.adjustedFeePerVsize || entry.feePerVsize,
inputs: entry.vin.map(v => this.getUid(newMempool[v.txid])).filter(uid => uid != null) as number[], inputs: entry.vin.map(v => this.getUid(newMempool[v.txid])).filter(uid => uid != null) as number[],

View File

@ -48,12 +48,14 @@ function makeBlockTemplates(mempool: Map<number, CompactThreadTransaction>)
weight: tx.weight, weight: tx.weight,
feePerVsize: tx.feePerVsize, feePerVsize: tx.feePerVsize,
effectiveFeePerVsize: tx.feePerVsize, effectiveFeePerVsize: tx.feePerVsize,
sigops: tx.sigops,
inputs: tx.inputs || [], inputs: tx.inputs || [],
relativesSet: false, relativesSet: false,
ancestorMap: new Map<number, AuditTransaction>(), ancestorMap: new Map<number, AuditTransaction>(),
children: new Set<AuditTransaction>(), children: new Set<AuditTransaction>(),
ancestorFee: 0, ancestorFee: 0,
ancestorWeight: 0, ancestorWeight: 0,
ancestorSigops: 0,
score: 0, score: 0,
used: false, used: false,
modified: false, modified: false,
@ -83,6 +85,7 @@ function makeBlockTemplates(mempool: Map<number, CompactThreadTransaction>)
// (i.e. the package rooted in the transaction with the best ancestor score) // (i.e. the package rooted in the transaction with the best ancestor score)
const blocks: number[][] = []; const blocks: number[][] = [];
let blockWeight = 4000; let blockWeight = 4000;
let blockSigops = 0;
let transactions: AuditTransaction[] = []; let transactions: AuditTransaction[] = [];
const modified: PairingHeap<AuditTransaction> = new PairingHeap((a, b): boolean => { const modified: PairingHeap<AuditTransaction> = new PairingHeap((a, b): boolean => {
if (a.score === b.score) { if (a.score === b.score) {
@ -118,7 +121,7 @@ function makeBlockTemplates(mempool: Map<number, CompactThreadTransaction>)
if (nextTx && !nextTx?.used) { if (nextTx && !nextTx?.used) {
// Check if the package fits into this block // Check if the package fits into this block
if (blocks.length >= 7 || (blockWeight + nextTx.ancestorWeight < config.MEMPOOL.BLOCK_WEIGHT_UNITS)) { if (blocks.length >= 7 || ((blockWeight + nextTx.ancestorWeight < config.MEMPOOL.BLOCK_WEIGHT_UNITS) && (blockSigops + nextTx.ancestorSigops <= 80000))) {
const ancestors: AuditTransaction[] = Array.from(nextTx.ancestorMap.values()); const ancestors: AuditTransaction[] = Array.from(nextTx.ancestorMap.values());
// sort ancestors by dependency graph (equivalent to sorting by ascending ancestor count) // sort ancestors by dependency graph (equivalent to sorting by ascending ancestor count)
const sortedTxSet = [...ancestors.sort((a, b) => { return (a.ancestorMap.size || 0) - (b.ancestorMap.size || 0); }), nextTx]; const sortedTxSet = [...ancestors.sort((a, b) => { return (a.ancestorMap.size || 0) - (b.ancestorMap.size || 0); }), nextTx];
@ -237,9 +240,11 @@ function setRelatives(
}; };
tx.ancestorFee = tx.fee || 0; tx.ancestorFee = tx.fee || 0;
tx.ancestorWeight = tx.weight || 0; tx.ancestorWeight = tx.weight || 0;
tx.ancestorSigops = tx.sigops || 0;
tx.ancestorMap.forEach((ancestor) => { tx.ancestorMap.forEach((ancestor) => {
tx.ancestorFee += ancestor.fee; tx.ancestorFee += ancestor.fee;
tx.ancestorWeight += ancestor.weight; tx.ancestorWeight += ancestor.weight;
tx.ancestorSigops += ancestor.sigops;
}); });
tx.score = tx.ancestorFee / ((tx.ancestorWeight / 4) || 1); tx.score = tx.ancestorFee / ((tx.ancestorWeight / 4) || 1);
tx.relativesSet = true; tx.relativesSet = true;
@ -271,6 +276,7 @@ function updateDescendants(
descendantTx.ancestorMap.delete(rootTx.uid); descendantTx.ancestorMap.delete(rootTx.uid);
descendantTx.ancestorFee -= rootTx.fee; descendantTx.ancestorFee -= rootTx.fee;
descendantTx.ancestorWeight -= rootTx.weight; descendantTx.ancestorWeight -= rootTx.weight;
descendantTx.ancestorSigops -= rootTx.sigops;
tmpScore = descendantTx.score; tmpScore = descendantTx.score;
descendantTx.score = descendantTx.ancestorFee / (descendantTx.ancestorWeight / 4); descendantTx.score = descendantTx.ancestorFee / (descendantTx.ancestorWeight / 4);
descendantTx.dependencyRate = descendantTx.dependencyRate ? Math.min(descendantTx.dependencyRate, clusterRate) : clusterRate; descendantTx.dependencyRate = descendantTx.dependencyRate ? Math.min(descendantTx.dependencyRate, clusterRate) : clusterRate;

View File

@ -100,12 +100,14 @@ export interface AuditTransaction {
weight: number; weight: number;
feePerVsize: number; feePerVsize: number;
effectiveFeePerVsize: number; effectiveFeePerVsize: number;
sigops: number;
inputs: number[]; inputs: number[];
relativesSet: boolean; relativesSet: boolean;
ancestorMap: Map<number, AuditTransaction>; ancestorMap: Map<number, AuditTransaction>;
children: Set<AuditTransaction>; children: Set<AuditTransaction>;
ancestorFee: number; ancestorFee: number;
ancestorWeight: number; ancestorWeight: number;
ancestorSigops: number;
score: number; score: number;
used: boolean; used: boolean;
modified: boolean; modified: boolean;
@ -117,6 +119,7 @@ export interface CompactThreadTransaction {
uid: number; uid: number;
fee: number; fee: number;
weight: number; weight: number;
sigops: number;
feePerVsize: number; feePerVsize: number;
effectiveFeePerVsize?: number; effectiveFeePerVsize?: number;
inputs: number[]; inputs: number[];