@node-lightning/wire
Version:
Lightning Network Wire Protocol
130 lines (115 loc) • 5.38 kB
text/typescript
import { BufferReader, BufferWriter } from "@node-lightning/bufio";
import { BitField, HashByteOrder, HashValue } from "@node-lightning/core";
import { shortChannelIdFromBuffer } from "@node-lightning/core";
import { OutPoint } from "@node-lightning/core";
import { readTlvs } from "../serialize/readTlvs";
import { ChannelAnnouncementMessage } from "./ChannelAnnouncementMessage";
/**
* Decorator for the channel_announcement that includes the additional
* information provided by the on-chain validation. Specifically, the
* channel_announcement message only has a short_channel_id with block, tx num,
* and vout num. We need to obtain the txid as well as the outpoint value to
* determine the value of the channel.
*
* This information is stored in this decorator class which can be broadcast
* and used downstream by clients that need both sets of information. Additionally
* the use of this decorator allows us to store the on-chain data along side the
* channel_announcement data if so desired.
*/
export class ExtendedChannelAnnouncementMessage extends ChannelAnnouncementMessage {
/**
* Constructs a new ExtendedChannelAnnouncementMessage from the plain-jane
* ChannelAnnouncementMessage
*/
public static fromMessage(msg: ChannelAnnouncementMessage) {
const instance = new ExtendedChannelAnnouncementMessage();
instance.bitcoinKey1 = msg.bitcoinKey1;
instance.bitcoinKey2 = msg.bitcoinKey2;
instance.bitcoinSignature1 = msg.bitcoinSignature1;
instance.bitcoinSignature2 = msg.bitcoinSignature2;
instance.chainHash = msg.chainHash;
instance.features = msg.features;
instance.nodeId1 = msg.nodeId1;
instance.nodeId2 = msg.nodeId2;
instance.nodeSignature1 = msg.nodeSignature1;
instance.nodeSignature2 = msg.nodeSignature2;
instance.shortChannelId = msg.shortChannelId;
instance.type = msg.type;
return instance;
}
public static deserialize(payload: Buffer): ExtendedChannelAnnouncementMessage {
const instance = new ExtendedChannelAnnouncementMessage();
const reader = new BufferReader(payload);
reader.readUInt16BE(); // read off type
instance.nodeSignature1 = reader.readBytes(64);
instance.nodeSignature2 = reader.readBytes(64);
instance.bitcoinSignature1 = reader.readBytes(64);
instance.bitcoinSignature2 = reader.readBytes(64);
const len = reader.readUInt16BE();
instance.features = BitField.fromBuffer(reader.readBytes(len));
instance.chainHash = reader.readBytes(32);
instance.shortChannelId = shortChannelIdFromBuffer(reader.readBytes(8));
instance.nodeId1 = reader.readBytes(33);
instance.nodeId2 = reader.readBytes(33);
instance.bitcoinKey1 = reader.readBytes(33);
instance.bitcoinKey2 = reader.readBytes(33);
// read the TLVs for the extended data
readTlvs(reader, (type: bigint, valueReader: BufferReader) => {
switch (type) {
// process the outpoint which is obtained after looking onchain
// at the funding transaction. This is encoded as a 32-byte txid
// and a 2 byte uint output index
case BigInt(16777271): {
instance.outpoint = new OutPoint(
HashValue.fromRpc(valueReader.readBytes(32).toString("hex")),
valueReader.readTUInt16(),
);
return true;
}
// process the channel capacity which is obtained after looking
// onchain at the funding transaction outpoint. This is encoded
// as a single tuint64 value.
case BigInt(16777273): {
instance.capacity = valueReader.readTUInt64();
return true;
}
default:
return false;
}
});
return instance;
}
/**
* OutPoint for the channel that includes the transaction identifier as well
* as the vout index. This information is obtained by finding the transaction
* in a block based on the short_channel_id.
*/
public outpoint: OutPoint;
/**
* Capacity of the funding transaction. This information is obtained from on-chain
* validation of the transaction.
*/
public capacity: bigint;
public serialize() {
const chanAnnBuffer = super.serialize();
const writer = new BufferWriter();
// outpoint value
let valueWriter = new BufferWriter();
valueWriter.writeBytes(this.outpoint.txid.serialize(HashByteOrder.RPC));
valueWriter.writeTUInt16(this.outpoint.outputIndex);
let value = valueWriter.toBuffer();
// outpoint tlv
writer.writeBigSize(16777271);
writer.writeBigSize(value.length);
writer.writeBytes(value);
// capacity value
valueWriter = new BufferWriter();
valueWriter.writeTUInt64(this.capacity);
value = valueWriter.toBuffer();
// capacity tlv
writer.writeBigSize(16777273);
writer.writeBigSize(value.length);
writer.writeBytes(value);
return Buffer.concat([chanAnnBuffer, writer.toBuffer()]);
}
}