Enforce Rust GBT instance lifecycle

This commit is contained in:
Mononaut 2023-06-25 20:37:42 -04:00
parent 8f675c7062
commit fc504012d5
No known key found for this signature in database
GPG Key ID: A3F058E41374C04E
4 changed files with 36 additions and 17 deletions

View File

@ -34,7 +34,7 @@ class Blocks {
private lastDifficultyAdjustmentTime = 0; private lastDifficultyAdjustmentTime = 0;
private previousDifficultyRetarget = 0; private previousDifficultyRetarget = 0;
private newBlockCallbacks: ((block: BlockExtended, txIds: string[], transactions: TransactionExtended[]) => void)[] = []; private newBlockCallbacks: ((block: BlockExtended, txIds: string[], transactions: TransactionExtended[]) => void)[] = [];
private newAsyncBlockCallbacks: ((block: BlockExtended, txIds: string[], transactions: TransactionExtended[]) => Promise<void>)[] = []; private newAsyncBlockCallbacks: ((block: BlockExtended, txIds: string[], transactions: MempoolTransactionExtended[]) => Promise<void>)[] = [];
private mainLoopTimeout: number = 120000; private mainLoopTimeout: number = 120000;
@ -60,7 +60,7 @@ class Blocks {
this.newBlockCallbacks.push(fn); this.newBlockCallbacks.push(fn);
} }
public setNewAsyncBlockCallback(fn: (block: BlockExtended, txIds: string[], transactions: TransactionExtended[]) => Promise<void>) { public setNewAsyncBlockCallback(fn: (block: BlockExtended, txIds: string[], transactions: MempoolTransactionExtended[]) => Promise<void>) {
this.newAsyncBlockCallbacks.push(fn); this.newAsyncBlockCallbacks.push(fn);
} }
@ -642,7 +642,7 @@ class Blocks {
const verboseBlock = await bitcoinClient.getBlock(blockHash, 2); const verboseBlock = await bitcoinClient.getBlock(blockHash, 2);
const block = BitcoinApi.convertBlock(verboseBlock); const block = BitcoinApi.convertBlock(verboseBlock);
const txIds: string[] = await bitcoinApi.$getTxIdsForBlock(blockHash); const txIds: string[] = await bitcoinApi.$getTxIdsForBlock(blockHash);
const transactions = await this.$getTransactionsExtended(blockHash, block.height, false, false, true); const transactions = await this.$getTransactionsExtended(blockHash, block.height, false, false, true) as MempoolTransactionExtended[];
if (config.MEMPOOL.BACKEND !== 'esplora') { if (config.MEMPOOL.BACKEND !== 'esplora') {
// fill in missing transaction fee data from verboseBlock // fill in missing transaction fee data from verboseBlock
for (let i = 0; i < transactions.length; i++) { for (let i = 0; i < transactions.length; i++) {

View File

@ -195,6 +195,7 @@ class DiskCache {
if (data.mempoolArray) { if (data.mempoolArray) {
for (const tx of data.mempoolArray) { for (const tx of data.mempoolArray) {
delete tx.uid;
data.mempool[tx.txid] = tx; data.mempool[tx.txid] = tx;
} }
} }
@ -207,6 +208,7 @@ class DiskCache {
const cacheData2 = JSON.parse(fs.readFileSync(fileName, 'utf8')); const cacheData2 = JSON.parse(fs.readFileSync(fileName, 'utf8'));
if (cacheData2.mempoolArray) { if (cacheData2.mempoolArray) {
for (const tx of cacheData2.mempoolArray) { for (const tx of cacheData2.mempoolArray) {
delete tx.uid;
data.mempool[tx.txid] = tx; data.mempool[tx.txid] = tx;
} }
} else { } else {

View File

@ -327,13 +327,21 @@ class MempoolBlocks {
} }
} }
public async $rustMakeBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, saveResults: boolean = false): Promise<MempoolBlockWithTransactions[]> { private resetRustGbt(): void {
this.rustInitialized = false;
this.rustGbtGenerator = new GbtGenerator();
}
private async $rustMakeBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, saveResults: boolean = false): Promise<MempoolBlockWithTransactions[]> {
const start = Date.now(); const start = Date.now();
// reset mempool short ids // reset mempool short ids
this.resetUids(); if (saveResults) {
this.resetUids();
}
// set missing short ids
for (const tx of Object.values(newMempool)) { for (const tx of Object.values(newMempool)) {
this.setUid(tx); this.setUid(tx, !saveResults);
} }
// serialize relevant mempool data into an ArrayBuffer // serialize relevant mempool data into an ArrayBuffer
@ -341,25 +349,34 @@ class MempoolBlocks {
const mempoolBuffer = this.mempoolToArrayBuffer(Object.values(newMempool), newMempool); const mempoolBuffer = this.mempoolToArrayBuffer(Object.values(newMempool), newMempool);
// run the block construction algorithm in a separate thread, and wait for a result // run the block construction algorithm in a separate thread, and wait for a result
const rustGbt = saveResults ? this.rustGbtGenerator : new GbtGenerator();
try { try {
const { blocks, rates, clusters } = this.convertNapiResultTxids( const { blocks, rates, clusters } = this.convertNapiResultTxids(
await this.rustGbtGenerator.make(new Uint8Array(mempoolBuffer)), await rustGbt.make(new Uint8Array(mempoolBuffer)),
); );
this.rustInitialized = true; if (saveResults) {
this.rustInitialized = true;
}
const processed = this.processBlockTemplates(newMempool, blocks, rates, clusters, saveResults); const processed = this.processBlockTemplates(newMempool, blocks, rates, clusters, saveResults);
logger.debug(`RUST makeBlockTemplates completed in ${(Date.now() - start)/1000} seconds`); logger.debug(`RUST makeBlockTemplates completed in ${(Date.now() - start)/1000} seconds`);
return processed; return processed;
} catch (e) { } catch (e) {
this.rustInitialized = false;
logger.err('RUST makeBlockTemplates failed. ' + (e instanceof Error ? e.message : e)); logger.err('RUST makeBlockTemplates failed. ' + (e instanceof Error ? e.message : e));
if (saveResults) {
this.resetRustGbt();
}
} }
return this.mempoolBlocks; return this.mempoolBlocks;
} }
public async $rustUpdateBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, added: MempoolTransactionExtended[], removed: MempoolTransactionExtended[], saveResults: boolean = false): Promise<void> { public async $oneOffRustBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }): Promise<MempoolBlockWithTransactions[]> {
return this.$rustMakeBlockTemplates(newMempool, false);
}
public async $rustUpdateBlockTemplates(newMempool: { [txid: string]: MempoolTransactionExtended }, added: MempoolTransactionExtended[], removed: MempoolTransactionExtended[]): Promise<void> {
if (!this.rustInitialized) { if (!this.rustInitialized) {
// need to reset the worker // need to reset the worker
await this.$rustMakeBlockTemplates(newMempool, saveResults); await this.$rustMakeBlockTemplates(newMempool, true);
return; return;
} }
@ -382,11 +399,11 @@ class MempoolBlocks {
new Uint8Array(removedBuffer), new Uint8Array(removedBuffer),
), ),
); );
this.processBlockTemplates(newMempool, blocks, rates, clusters, saveResults); this.processBlockTemplates(newMempool, blocks, rates, clusters, true);
logger.debug(`RUST updateBlockTemplates completed in ${(Date.now() - start)/1000} seconds`); logger.debug(`RUST updateBlockTemplates completed in ${(Date.now() - start)/1000} seconds`);
} catch (e) { } catch (e) {
this.rustInitialized = false;
logger.err('RUST updateBlockTemplates failed. ' + (e instanceof Error ? e.message : e)); logger.err('RUST updateBlockTemplates failed. ' + (e instanceof Error ? e.message : e));
this.resetRustGbt();
} }
} }

View File

@ -343,7 +343,7 @@ class WebsocketHandler {
if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) { if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) {
if (config.MEMPOOL.RUST_GBT) { if (config.MEMPOOL.RUST_GBT) {
await mempoolBlocks.$rustUpdateBlockTemplates(newMempool, newTransactions, deletedTransactions, true); await mempoolBlocks.$rustUpdateBlockTemplates(newMempool, newTransactions, deletedTransactions);
} else { } else {
await mempoolBlocks.$updateBlockTemplates(newMempool, newTransactions, deletedTransactions, true); await mempoolBlocks.$updateBlockTemplates(newMempool, newTransactions, deletedTransactions, true);
} }
@ -574,7 +574,7 @@ class WebsocketHandler {
}); });
} }
async handleNewBlock(block: BlockExtended, txIds: string[], transactions: TransactionExtended[]): Promise<void> { async handleNewBlock(block: BlockExtended, txIds: string[], transactions: MempoolTransactionExtended[]): Promise<void> {
if (!this.wss) { if (!this.wss) {
throw new Error('WebSocket.Server is not set'); throw new Error('WebSocket.Server is not set');
} }
@ -593,7 +593,7 @@ class WebsocketHandler {
auditMempool = deepClone(_memPool); auditMempool = deepClone(_memPool);
if (config.MEMPOOL.ADVANCED_GBT_AUDIT) { if (config.MEMPOOL.ADVANCED_GBT_AUDIT) {
if (config.MEMPOOL.RUST_GBT) { if (config.MEMPOOL.RUST_GBT) {
projectedBlocks = await mempoolBlocks.$rustMakeBlockTemplates(auditMempool, false); projectedBlocks = await mempoolBlocks.$oneOffRustBlockTemplates(auditMempool);
} else { } else {
projectedBlocks = await mempoolBlocks.$makeBlockTemplates(auditMempool, false); projectedBlocks = await mempoolBlocks.$makeBlockTemplates(auditMempool, false);
} }
@ -664,7 +664,7 @@ class WebsocketHandler {
if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) { if (config.MEMPOOL.ADVANCED_GBT_MEMPOOL) {
if (config.MEMPOOL.RUST_GBT) { if (config.MEMPOOL.RUST_GBT) {
await mempoolBlocks.$rustMakeBlockTemplates(_memPool, true); await mempoolBlocks.$rustUpdateBlockTemplates(_memPool, [], transactions);
} else { } else {
await mempoolBlocks.$makeBlockTemplates(_memPool, true); await mempoolBlocks.$makeBlockTemplates(_memPool, true);
} }