@node-lightning/wire
Version:
Lightning Network Wire Protocol
215 lines • 8.46 kB
JavaScript
"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ChannelUpdateMessage = void 0;
const bufio_1 = require("@node-lightning/bufio");
const core_1 = require("@node-lightning/core");
const core_2 = require("@node-lightning/core");
const crypto = __importStar(require("@node-lightning/crypto"));
const Checksum_1 = require("../domain/Checksum");
const MessageType_1 = require("../MessageType");
/**
* After a channel has been announced, each side independently announces the fees
* and minimum expiry delta it requires to relay HTLCs through this channel. A
* node can broadcast this message multiple times in order to change fees.
*/
class ChannelUpdateMessage {
constructor() {
/**
* Message type is 258
*/
this.type = MessageType_1.MessageType.ChannelUpdate;
/**
* Indicate the presence of optional fields in the channel_update message.
* bit, field
* 0, htlc_maximum_msat
*/
this.messageFlags = new core_1.BitField();
/**
* Indicates the direction of the channel: it identifies the node that this
* update originated from and signals various options concerning the channel
* such as whether it is disabled.
* bit, name
* 0, direction
* 1, disabled
*/
this.channelFlags = new core_1.BitField();
}
/**
* Deserializes the message from a Buffer. The message
* is not validated in this function.
*/
static deserialize(payload) {
const instance = new ChannelUpdateMessage();
const reader = new bufio_1.BufferReader(payload);
reader.readUInt16BE(); // read off type
instance.signature = reader.readBytes(64);
instance.chainHash = reader.readBytes(32);
instance.shortChannelId = core_2.shortChannelIdFromBuffer(reader.readBytes(8));
instance.timestamp = reader.readUInt32BE();
instance.messageFlags = core_1.BitField.fromNumber(reader.readUInt8());
instance.channelFlags = core_1.BitField.fromNumber(reader.readUInt8());
instance.cltvExpiryDelta = reader.readUInt16BE();
instance.htlcMinimumMsat = core_1.Value.fromMilliSats(reader.readUInt64BE());
instance.feeBaseMsat = core_1.Value.fromMilliSats(reader.readUInt32BE());
instance.feeProportionalMillionths = core_1.Value.fromMicroSats(reader.readUInt32BE());
// has optional_channel_htlc_max
if (instance.hasHtlcMaximumMsatFlag) {
instance.htlcMaximumMsat = core_1.Value.fromMilliSats(reader.readUInt64BE());
}
return instance;
}
/**
* Performs a double SHA-256 hash of the message with all
* data excluding the signature data
*/
static hashForSignature(message) {
const raw = message.serialize().slice(66);
return crypto.hash256(raw);
}
/**
* Performs signature validation for the message by
* hashing the data post signature. A passing signature
* indicates that the message was submitted by the node
* that owns the channel. Becuase the nodeId is not included
* in the message, we need to obtain the nodeId by accessing
* the ChannelAnnouncementMessage and determining the public key
* @param message
* @param pubkey 33-byte ECDSA public key
*/
static validateSignature(message, pubkey) {
const sigmsg = ChannelUpdateMessage.hashForSignature(message);
return crypto.verifySig(sigmsg, message.signature, pubkey);
}
/**
* Returns true when message flags have the optional
* maximum HTLC msat value available
*/
get hasHtlcMaximumMsatFlag() {
return this.messageFlags.isSet(0);
}
/**
* Direction is determined by channel_flags bit 0.
* When set to 0, node_1 is the sender. When set to 1
* node_2 is the sender
*/
get direction() {
return this.channelFlags.isSet(0) ? 1 : 0;
}
set direction(val) {
if (val === 0) {
this.channelFlags.unset(0);
}
else if (val === 1) {
this.channelFlags.set(0);
}
else {
throw new Error("Invlid direction");
}
}
/**
* Disabled flag is determined by channel_flags bit 1.
* When set to 0, the channel is active. When set to 1
* the channel is disabled.
*/
get disabled() {
return this.channelFlags.isSet(1);
}
set disabled(val) {
if (val) {
this.channelFlags.set(1);
}
else {
this.channelFlags.unset(1);
}
}
/**
* Serializes the instance into a Buffer that can be
* transmitted over the wire
*/
serialize() {
const len = 2 + // type
64 + // signature
32 + // chain_hash
8 + // short_channel_id
4 + // timestamp
1 + // message_flags
1 + // channel_flags
2 + // cltv_expiry_delta
8 + // htlc_minimum_msat
4 + // fee_base_msat
4 + // fee_proportional_millionths
(this.hasHtlcMaximumMsatFlag ? 8 : 0);
const writer = new bufio_1.BufferWriter(Buffer.alloc(len));
writer.writeUInt16BE(this.type);
writer.writeBytes(this.signature);
writer.writeBytes(this.chainHash);
writer.writeBytes(this.shortChannelId.toBuffer());
writer.writeUInt32BE(this.timestamp);
writer.writeUInt8(this.messageFlags.toNumber());
writer.writeUInt8(this.channelFlags.toNumber());
writer.writeUInt16BE(this.cltvExpiryDelta);
writer.writeUInt64BE(this.htlcMinimumMsat.msats);
writer.writeUInt32BE(Number(this.feeBaseMsat.msats));
writer.writeUInt32BE(Number(this.feeProportionalMillionths.microsats));
if (this.hasHtlcMaximumMsatFlag) {
writer.writeUInt64BE(this.htlcMaximumMsat.msats);
}
return writer.toBuffer();
}
/**
* CRC32C checksum is calculated from the raw channel_update
* message and excludes the signature and timestamp.
*
* @remarks
* Defined in BOLT 07 gossip queries section:
* https://github.com/lightningnetwork/lightning-rfc/blob/master/07-routing-gossip.md#query-messages
*
*/
checksum() {
const len = 2 + // type
32 + // chain_hash
8 + // short_channel_id
1 + // message_flags
1 + // channel_flags
2 + // cltv_expiry_delta
8 + // htlc_minimum_msat
4 + // fee_base_msat
4 + // fee_proportional_millionths
(this.hasHtlcMaximumMsatFlag ? 8 : 0);
const writer = new bufio_1.BufferWriter(Buffer.alloc(len));
writer.writeUInt16BE(this.type);
writer.writeBytes(this.chainHash);
writer.writeBytes(this.shortChannelId.toBuffer());
writer.writeUInt8(Number(this.messageFlags));
writer.writeUInt8(Number(this.channelFlags));
writer.writeUInt16BE(this.cltvExpiryDelta);
writer.writeUInt64BE(this.htlcMinimumMsat.msats);
writer.writeUInt32BE(Number(this.feeBaseMsat.msats));
writer.writeUInt32BE(Number(this.feeProportionalMillionths.microsats));
if (this.hasHtlcMaximumMsatFlag) {
writer.writeUInt64BE(this.htlcMaximumMsat.msats);
}
return Checksum_1.Checksum.fromBuffer(writer.toBuffer());
}
}
exports.ChannelUpdateMessage = ChannelUpdateMessage;
//# sourceMappingURL=ChannelUpdateMessage.js.map