All files / lib/messages ReplyChannelRangeMessage.ts

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

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 1341x   1x 1x 1x 1x 1x     1x   5x 5x     5x   5x   5x 5x 5x     5x 5x 5x 5x 5x 105x 105x       5x 4x             3x 3x 3x 3x 63x         3x             1x 21x         1x                 5x     45x         45x 45x 45x       67x 5x   5x 5x 5x 5x 5x 5x 5x 5x           5x 2x 2x 42x 42x   2x 2x 2x 2x           5x 1x 1x 2x 2x   1x 1x 1x 1x     5x      
import { BufferReader, BufferWriter } from "@node-lightning/bufio";
import { ShortChannelId } from "@node-lightning/core";
import { shortChannelIdFromBuffer } from "@node-lightning/core";
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();
    }
}