All files / lib/messages ReplyChannelRangeMessage.ts

98.53% Statements 67/68
70% Branches 7/10
100% Functions 5/5
98.53% Lines 67/68

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 1371x   1x   1x 1x 1x 1x     1x   6x 6x     6x   6x   6x 6x 6x     6x 6x 6x 6x 6x 126x 126x       6x 5x             4x 4x 4x 4x 84x         4x             1x 21x         1x                 6x     47x         47x 47x 47x       6x 88x   6x   6x 6x 6x 6x 6x 6x 6x 6x           6x 3x 3x 63x 63x   3x 3x 3x 3x           6x 1x 1x 2x 2x   1x 1x 1x 1x     6x      
import { BufferReader, BufferWriter } from '@node-dlc/bufio';
import { ShortChannelId } from '@node-dlc/common';
import { shortChannelIdFromBuffer } from '@node-dlc/common';
 
import { MessageType } from '../MessageType';
import { Encoder } from '../serialize/Encoder';
import { EncodingType } from '../serialize/EncodingType';
import { readTlvs } from '../serialize/readTlvs';
import { IWireMessage } from './IWireMessage';
 
export class ReplyChannelRangeMessage implements IWireMessage {
  public static deserialize(payload: Buffer): ReplyChannelRangeMessage {
    const instance = new ReplyChannelRangeMessage();
    const reader = new BufferReader(payload);
 
    // read type bytes
    reader.readUInt16BE();
 
    instance.chainHash = reader.readBytes(32);
 
    instance.firstBlocknum = reader.readUInt32BE();
    instance.numberOfBlocks = reader.readUInt32BE();
    instance.fullInformation = reader.readUInt8() === 1;
 
    // read encoded_short_ids
    const encodedLen = reader.readUInt16BE(); // encoded_short_channel_id bytes
    const encodedScidBytes = reader.readBytes(encodedLen);
    const scidsBytes = new Encoder().decode(encodedScidBytes);
    const scidsReader = new BufferReader(scidsBytes);
    while (!scidsReader.eof) {
      const scidBytes = scidsReader.readBytes(8);
      instance.shortChannelIds.push(shortChannelIdFromBuffer(scidBytes));
    }
 
    // read tlvs in the reply_channel_range realm
    readTlvs(reader, (type: bigint, valueReader: BufferReader) => {
      switch (type) {
        // timestamps TLVs include the timestamps for the node1/2
        // node_update messages. A tuple [number, number] will be
        // returned for each short_channel_id that is returned.
        // Timestamps are an encoded field where the first byte
        // indicates the encoding type (RAW or ZLIB DEFLATE).
        case BigInt(1): {
          const bytes = valueReader.readBytes();
          const decodedBytes = new Encoder().decode(bytes);
          const decodedReader = new BufferReader(decodedBytes);
          while (!decodedReader.eof) {
            instance.timestamps.push([
              decodedReader.readUInt32BE(),
              decodedReader.readUInt32BE(),
            ]);
          }
          return true;
        }
 
        // checksum TLVs include the checksums for the node1/2
        // node_update message. A tuple [number, number] will be
        // returned for each short_channel_id that is returned
        case BigInt(3): {
          while (!valueReader.eof) {
            instance.checksums.push([
              valueReader.readUInt32BE(),
              valueReader.readUInt32BE(),
            ]);
          }
          return true;
        }
 
        // return that the TLV type was not handled
        default:
          return false;
      }
    });
 
    return instance;
  }
 
  public type: MessageType = MessageType.ReplyChannelRange;
  public chainHash: Buffer;
  public firstBlocknum: number;
  public numberOfBlocks: number;
  public fullInformation: boolean;
  public shortChannelIds: ShortChannelId[] = [];
  public timestamps: Array<[number, number]> = [];
  public checksums: Array<[number, number]> = [];
 
  public serialize(encoding: EncodingType = EncodingType.ZlibDeflate): Buffer {
    // encode short channel ids
    const rawSids = Buffer.concat(
      this.shortChannelIds.map((p) => p.toBuffer()),
    );
    const esids = new Encoder().encode(encoding, rawSids);
 
    const writer = new BufferWriter();
    writer.writeUInt16BE(this.type);
    writer.writeBytes(this.chainHash);
    writer.writeUInt32BE(this.firstBlocknum);
    writer.writeUInt32BE(this.numberOfBlocks);
    writer.writeUInt8(this.fullInformation ? 1 : 0);
    writer.writeUInt16BE(esids.length);
    writer.writeBytes(esids);
 
    // write timestamp TLV if it is required. The timestaps are encoded as
    // uint32BE tuples corresponding to the timestamps for node1/2
    // channel_update messages. This buffer uses the encoding format
    // supplied and will be either RAW or ZLIB DEFLARE
    if (this.timestamps.length) {
      const valueWriter = new BufferWriter();
      for (const [v1, v2] of this.timestamps) {
        valueWriter.writeUInt32BE(v1);
        valueWriter.writeUInt32BE(v2);
      }
      const value = new Encoder().encode(encoding, valueWriter.toBuffer());
      writer.writeBigSize(1); // type
      writer.writeBigSize(value.length); // length
      writer.writeBytes(value); // value
    }
 
    // write checksums TLV if it is required. The checksums are encoded as
    // uint32BE tuples corresponding to the checksums for node1/2
    // channel_update messages
    if (this.checksums.length) {
      const valueWriter = new BufferWriter();
      for (const [v1, v2] of this.checksums) {
        valueWriter.writeUInt32BE(v1);
        valueWriter.writeUInt32BE(v2);
      }
      const value = valueWriter.toBuffer();
      writer.writeBigSize(3); // type
      writer.writeBigSize(value.length); // length
      writer.writeBytes(value); // value
    }
 
    return writer.toBuffer();
  }
}