All files / lib/messages InitMessage.ts

100% Statements 36/36
100% Branches 3/3
100% Functions 4/4
100% Lines 36/36

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 1081x 1x   1x 1x                       1x               24x 24x     24x       24x 22x     22x 22x       22x     22x 6x         6x 8x 8x   6x         22x           34x         34x         34x             9x     9x     9x 9x     9x 9x 9x 9x     9x 7x 7x 7x     9x      
import { BufferReader, BufferWriter } from "@node-lightning/bufio";
import { BitField } from "@node-lightning/core";
import { InitFeatureFlags } from "../flags/InitFeatureFlags";
import { MessageType } from "../MessageType";
import { readTlvs } from "../serialize/readTlvs";
import { IWireMessage } from "./IWireMessage";
 
/**
 * InitMessage is defined in BOLT #1. Once authentication is complete, the first
 * message reveals the features supported or required by the node sending the
 * message. This message is sent even on a reconnection.
 *
 * This message contains two fields; global features and local features, that
 * are used to signal how the message should operate. The values of are defined
 * in the BOLT #9.
 */
export class InitMessage implements IWireMessage {
    /**
     * Processes a buffer containing the message information. This method
     * will capture the arbitrary length global and local
     * features into two internal properties of the newly constructed
     * init message object.
     */
    public static deserialize(buffer: Buffer): InitMessage {
        const instance = new InitMessage();
        const reader = new BufferReader(buffer);
 
        // read the type bytes
        reader.readUInt16BE();
 
        // read the global features and per the specification, the global
        // features should not exceed features greater than 13.
        const gflen = reader.readUInt16BE();
        const gf = BitField.fromBuffer(reader.readBytes(gflen));
 
        // Read the local length and parse into a BN value.
        const lflen = reader.readUInt16BE();
        const lf = BitField.fromBuffer(reader.readBytes(lflen));
 
        // construct a single features object by bitwise or of the global and
        // local features.
        instance.features = new BitField().or(gf).or(lf);
 
        // process TLVs
        readTlvs(reader, (type: bigint, valueReader: BufferReader) => {
            switch (type) {
                // Process networks TLVs which is a series of chain_hash 32
                // byte values. This method will simply read from the stream
                // until every thing has been read
                case BigInt(1): {
                    while (!valueReader.eof) {
                        const chainHash = valueReader.readBytes(32);
                        instance.chainHashes.push(chainHash);
                    }
                    return true;
                }
            }
        });
 
        return instance;
    }
 
    /**
     * Message type 16
     */
    public type: MessageType = MessageType.Init;
 
    /**
     * BitField containing the features provided in by the local or remote node
     */
    public features: BitField<InitFeatureFlags> = new BitField();
 
    /**
     * Supported chain_hashes for the remote peer
     */
    public chainHashes: Buffer[] = [];
 
    /**
     * Serialize will construct a properly formatted message based on the
     * properties of the configured message.
     */
    public serialize() {
        const writer = new BufferWriter();
 
        // write the type
        writer.writeUInt16BE(this.type);
 
        // write gflen
        const gflen = 0;
        writer.writeUInt16BE(gflen);
 
        // write features
        const features = this.features.toBuffer();
        const featuresLen = features.length;
        writer.writeUInt16BE(featuresLen);
        writer.writeBytes(features);
 
        // write chainhash tlv
        if (this.chainHashes.length) {
            writer.writeBigSize(1); // type
            writer.writeBigSize(this.chainHashes.length * 32); // length
            writer.writeBytes(Buffer.concat(this.chainHashes)); // value
        }
 
        return writer.toBuffer();
    }
}