Merge pull request #3010 from mempool/mononaut/cpfp-error-handling
More robust error checking & handling in CPFP repositories
This commit is contained in:
		
						commit
						241850beca
					
				@ -111,7 +111,7 @@ class CpfpRepository {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public async $getCluster(clusterRoot: string): Promise<Cluster> {
 | 
					  public async $getCluster(clusterRoot: string): Promise<Cluster | void> {
 | 
				
			||||||
    const [clusterRows]: any = await DB.query(
 | 
					    const [clusterRows]: any = await DB.query(
 | 
				
			||||||
      `
 | 
					      `
 | 
				
			||||||
        SELECT *
 | 
					        SELECT *
 | 
				
			||||||
@ -121,9 +121,12 @@ class CpfpRepository {
 | 
				
			|||||||
      [clusterRoot]
 | 
					      [clusterRoot]
 | 
				
			||||||
    );
 | 
					    );
 | 
				
			||||||
    const cluster = clusterRows[0];
 | 
					    const cluster = clusterRows[0];
 | 
				
			||||||
 | 
					    if (cluster?.txs) {
 | 
				
			||||||
      cluster.txs = this.unpack(cluster.txs);
 | 
					      cluster.txs = this.unpack(cluster.txs);
 | 
				
			||||||
      return cluster;
 | 
					      return cluster;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					    return;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public async $deleteClustersFrom(height: number): Promise<void> {
 | 
					  public async $deleteClustersFrom(height: number): Promise<void> {
 | 
				
			||||||
    logger.info(`Delete newer cpfp clusters from height ${height} from the database`);
 | 
					    logger.info(`Delete newer cpfp clusters from height ${height} from the database`);
 | 
				
			||||||
@ -136,9 +139,9 @@ class CpfpRepository {
 | 
				
			|||||||
        [height]
 | 
					        [height]
 | 
				
			||||||
      ) as RowDataPacket[][];
 | 
					      ) as RowDataPacket[][];
 | 
				
			||||||
      if (rows?.length) {
 | 
					      if (rows?.length) {
 | 
				
			||||||
        for (let clusterToDelete of rows) {
 | 
					        for (const clusterToDelete of rows) {
 | 
				
			||||||
          const txs = this.unpack(clusterToDelete.txs);
 | 
					          const txs = this.unpack(clusterToDelete?.txs);
 | 
				
			||||||
          for (let tx of txs) {
 | 
					          for (const tx of txs) {
 | 
				
			||||||
            await transactionRepository.$removeTransaction(tx.txid);
 | 
					            await transactionRepository.$removeTransaction(tx.txid);
 | 
				
			||||||
          }
 | 
					          }
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -204,6 +207,7 @@ class CpfpRepository {
 | 
				
			|||||||
      return [];
 | 
					      return [];
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
      const arrayBuffer = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
 | 
					      const arrayBuffer = buf.buffer.slice(buf.byteOffset, buf.byteOffset + buf.byteLength);
 | 
				
			||||||
      const txs: Ancestor[] = [];
 | 
					      const txs: Ancestor[] = [];
 | 
				
			||||||
      const view = new DataView(arrayBuffer);
 | 
					      const view = new DataView(arrayBuffer);
 | 
				
			||||||
@ -218,6 +222,10 @@ class CpfpRepository {
 | 
				
			|||||||
        });
 | 
					        });
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      return txs;
 | 
					      return txs;
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      logger.warn(`Failed to unpack CPFP cluster. Reason: ` + (e instanceof Error ? e.message : e));
 | 
				
			||||||
 | 
					      return [];
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -3,15 +3,6 @@ import logger from '../logger';
 | 
				
			|||||||
import { Ancestor, CpfpInfo } from '../mempool.interfaces';
 | 
					import { Ancestor, CpfpInfo } from '../mempool.interfaces';
 | 
				
			||||||
import cpfpRepository from './CpfpRepository';
 | 
					import cpfpRepository from './CpfpRepository';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
interface CpfpSummary {
 | 
					 | 
				
			||||||
  txid: string;
 | 
					 | 
				
			||||||
  cluster: string;
 | 
					 | 
				
			||||||
  root: string;
 | 
					 | 
				
			||||||
  txs: Ancestor[];
 | 
					 | 
				
			||||||
  height: number;
 | 
					 | 
				
			||||||
  fee_rate: number;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class TransactionRepository {
 | 
					class TransactionRepository {
 | 
				
			||||||
  public async $setCluster(txid: string, clusterRoot: string): Promise<void> {
 | 
					  public async $setCluster(txid: string, clusterRoot: string): Promise<void> {
 | 
				
			||||||
    try {
 | 
					    try {
 | 
				
			||||||
@ -72,8 +63,10 @@ class TransactionRepository {
 | 
				
			|||||||
        const txid = txRows[0].id.toLowerCase();
 | 
					        const txid = txRows[0].id.toLowerCase();
 | 
				
			||||||
        const clusterId = txRows[0].root.toLowerCase();
 | 
					        const clusterId = txRows[0].root.toLowerCase();
 | 
				
			||||||
        const cluster = await cpfpRepository.$getCluster(clusterId);
 | 
					        const cluster = await cpfpRepository.$getCluster(clusterId);
 | 
				
			||||||
 | 
					        if (cluster) {
 | 
				
			||||||
          return this.convertCpfp(txid, cluster);
 | 
					          return this.convertCpfp(txid, cluster);
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    } catch (e) {
 | 
					    } catch (e) {
 | 
				
			||||||
      logger.err('Cannot get transaction cpfp info from db. Reason: ' + (e instanceof Error ? e.message : e));
 | 
					      logger.err('Cannot get transaction cpfp info from db. Reason: ' + (e instanceof Error ? e.message : e));
 | 
				
			||||||
      throw e;
 | 
					      throw e;
 | 
				
			||||||
@ -81,6 +74,7 @@ class TransactionRepository {
 | 
				
			|||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  public async $removeTransaction(txid: string): Promise<void> {
 | 
					  public async $removeTransaction(txid: string): Promise<void> {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
      await DB.query(
 | 
					      await DB.query(
 | 
				
			||||||
        `
 | 
					        `
 | 
				
			||||||
          DELETE FROM compact_transactions
 | 
					          DELETE FROM compact_transactions
 | 
				
			||||||
@ -88,6 +82,10 @@ class TransactionRepository {
 | 
				
			|||||||
        `,
 | 
					        `,
 | 
				
			||||||
        [txid]
 | 
					        [txid]
 | 
				
			||||||
      );
 | 
					      );
 | 
				
			||||||
 | 
					    } catch (e) {
 | 
				
			||||||
 | 
					      logger.warn('Cannot delete transaction cpfp info from db. Reason: ' + (e instanceof Error ? e.message : e));
 | 
				
			||||||
 | 
					      throw e;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private convertCpfp(txid, cluster): CpfpInfo {
 | 
					  private convertCpfp(txid, cluster): CpfpInfo {
 | 
				
			||||||
@ -95,7 +93,7 @@ class TransactionRepository {
 | 
				
			|||||||
    const ancestors: Ancestor[] = [];
 | 
					    const ancestors: Ancestor[] = [];
 | 
				
			||||||
    let matched = false;
 | 
					    let matched = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    for (const tx of cluster.txs) {
 | 
					    for (const tx of (cluster?.txs || [])) {
 | 
				
			||||||
      if (tx.txid === txid) {
 | 
					      if (tx.txid === txid) {
 | 
				
			||||||
        matched = true;
 | 
					        matched = true;
 | 
				
			||||||
      } else if (!matched) {
 | 
					      } else if (!matched) {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user