Merge pull request #2802 from mempool/nymkappa/bugfix/tx-fetcher-crash
Fix crash when channel short id is not valid
This commit is contained in:
		
						commit
						755090ce94
					
				@ -55,11 +55,12 @@ export async function convertAndmergeBidirectionalChannels(clChannels: any[]): P
 | 
			
		||||
      clChannelsDict[clChannel.short_channel_id] = clChannel;
 | 
			
		||||
      clChannelsDictCount[clChannel.short_channel_id] = 1;
 | 
			
		||||
    } else {
 | 
			
		||||
      consolidatedChannelList.push(
 | 
			
		||||
        await buildFullChannel(clChannel, clChannelsDict[clChannel.short_channel_id])
 | 
			
		||||
      );
 | 
			
		||||
      delete clChannelsDict[clChannel.short_channel_id];
 | 
			
		||||
      clChannelsDictCount[clChannel.short_channel_id]++;
 | 
			
		||||
      const fullChannel = await buildFullChannel(clChannel, clChannelsDict[clChannel.short_channel_id]);
 | 
			
		||||
      if (fullChannel !== null) {
 | 
			
		||||
        consolidatedChannelList.push(fullChannel);
 | 
			
		||||
        delete clChannelsDict[clChannel.short_channel_id];
 | 
			
		||||
        clChannelsDictCount[clChannel.short_channel_id]++;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const elapsedSeconds = Math.round((new Date().getTime() / 1000) - loggerTimer);
 | 
			
		||||
@ -74,7 +75,10 @@ export async function convertAndmergeBidirectionalChannels(clChannels: any[]): P
 | 
			
		||||
  channelProcessed = 0;
 | 
			
		||||
  const keys = Object.keys(clChannelsDict);
 | 
			
		||||
  for (const short_channel_id of keys) {
 | 
			
		||||
    consolidatedChannelList.push(await buildIncompleteChannel(clChannelsDict[short_channel_id]));
 | 
			
		||||
    const incompleteChannel = await buildIncompleteChannel(clChannelsDict[short_channel_id]);
 | 
			
		||||
    if (incompleteChannel !== null) {
 | 
			
		||||
      consolidatedChannelList.push(incompleteChannel);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const elapsedSeconds = Math.round((new Date().getTime() / 1000) - loggerTimer);
 | 
			
		||||
    if (elapsedSeconds > config.LIGHTNING.LOGGER_UPDATE_INTERVAL) {
 | 
			
		||||
@ -92,10 +96,13 @@ export async function convertAndmergeBidirectionalChannels(clChannels: any[]): P
 | 
			
		||||
 * Convert two clightning "getchannels" entries into a full a lnd "describegraph.edges" format
 | 
			
		||||
 * In this case, clightning knows the channel policy for both nodes
 | 
			
		||||
 */
 | 
			
		||||
async function buildFullChannel(clChannelA: any, clChannelB: any): Promise<ILightningApi.Channel> {
 | 
			
		||||
async function buildFullChannel(clChannelA: any, clChannelB: any): Promise<ILightningApi.Channel | null> {
 | 
			
		||||
  const lastUpdate = Math.max(clChannelA.last_update ?? 0, clChannelB.last_update ?? 0);
 | 
			
		||||
 | 
			
		||||
  const tx = await FundingTxFetcher.$fetchChannelOpenTx(clChannelA.short_channel_id);
 | 
			
		||||
  if (!tx) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
  const parts = clChannelA.short_channel_id.split('x');
 | 
			
		||||
  const outputIdx = parts[2];
 | 
			
		||||
 | 
			
		||||
@ -115,8 +122,11 @@ async function buildFullChannel(clChannelA: any, clChannelB: any): Promise<ILigh
 | 
			
		||||
 * Convert one clightning "getchannels" entry into a full a lnd "describegraph.edges" format
 | 
			
		||||
 * In this case, clightning knows the channel policy of only one node
 | 
			
		||||
 */
 | 
			
		||||
async function buildIncompleteChannel(clChannel: any): Promise<ILightningApi.Channel> {
 | 
			
		||||
async function buildIncompleteChannel(clChannel: any): Promise<ILightningApi.Channel | null> {
 | 
			
		||||
  const tx = await FundingTxFetcher.$fetchChannelOpenTx(clChannel.short_channel_id);
 | 
			
		||||
  if (!tx) {
 | 
			
		||||
    return null;
 | 
			
		||||
  }
 | 
			
		||||
  const parts = clChannel.short_channel_id.split('x');
 | 
			
		||||
  const outputIdx = parts[2];
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -210,6 +210,9 @@ class NetworkSyncService {
 | 
			
		||||
      const channels = await channelsApi.$getChannelsWithoutCreatedDate();
 | 
			
		||||
      for (const channel of channels) {
 | 
			
		||||
        const transaction = await fundingTxFetcher.$fetchChannelOpenTx(channel.short_id);
 | 
			
		||||
        if (!transaction) {
 | 
			
		||||
          continue;
 | 
			
		||||
        }
 | 
			
		||||
        await DB.query(`
 | 
			
		||||
          UPDATE channels SET created = FROM_UNIXTIME(?) WHERE channels.id = ?`,
 | 
			
		||||
          [transaction.timestamp, channel.id]
 | 
			
		||||
 | 
			
		||||
@ -71,7 +71,7 @@ class FundingTxFetcher {
 | 
			
		||||
    this.running = false;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  public async $fetchChannelOpenTx(channelId: string): Promise<{timestamp: number, txid: string, value: number}> {
 | 
			
		||||
  public async $fetchChannelOpenTx(channelId: string): Promise<{timestamp: number, txid: string, value: number} | null> {
 | 
			
		||||
    channelId = Common.channelIntegerIdToShortId(channelId);
 | 
			
		||||
 | 
			
		||||
    if (this.fundingTxCache[channelId]) {
 | 
			
		||||
@ -102,6 +102,11 @@ class FundingTxFetcher {
 | 
			
		||||
    const rawTx = await bitcoinClient.getRawTransaction(txid);
 | 
			
		||||
    const tx = await bitcoinClient.decodeRawTransaction(rawTx);
 | 
			
		||||
 | 
			
		||||
    if (!tx || !tx.vout || tx.vout.length < parseInt(outputIdx, 10) + 1 || tx.vout[outputIdx].value === undefined) {
 | 
			
		||||
      logger.err(`Cannot find blockchain funding tx for channel id ${channelId}. Possible reasons are: bitcoin backend timeout or the channel shortId is not valid`);
 | 
			
		||||
      return null;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    this.fundingTxCache[channelId] = {
 | 
			
		||||
      timestamp: block.time,
 | 
			
		||||
      txid: txid,
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user