@node-dlc/messaging
Version:
DLC Messaging Protocol
162 lines (118 loc) • 4.14 kB
text/typescript
import { BufferReader, BufferWriter } from '@node-dlc/bufio';
import { crc32c } from '@node-dlc/checksum';
import { MessageType } from '../MessageType';
const MAX_DATA_LEN = 190;
export abstract class IrcMessage {
public static deserialize(buf: Buffer): IrcMessageV0 {
const reader = new BufferReader(buf);
const type = Number(reader.readUInt16BE());
switch (type) {
case MessageType.IrcMessageV0:
return IrcMessageV0.deserialize(buf);
default:
throw new Error(`Irc message type must be IrcMessageV0`);
}
}
public abstract type: number;
public abstract serialize(): Buffer;
}
/**
* IrcMessage contains information for Irc message packet.
*/
export class IrcMessageV0 extends IrcMessage {
public static type = MessageType.IrcMessageV0;
public static fromBuffer(buf: Buffer, pubkey: Buffer): IrcMessageV0[] {
const instances: IrcMessageV0[] = [];
const checksum = crc32c(buf);
const sequenceLength = Math.ceil(buf.length / MAX_DATA_LEN);
const reader = new BufferReader(buf);
const bufLen = buf.length;
const currentTime = Math.floor(new Date().getTime() / 1000);
for (let i = 0; i < sequenceLength; i++) {
const sequenceNumber = i;
const instance = new IrcMessageV0();
instance.sequenceLength = BigInt(sequenceLength);
instance.sequenceNumber = BigInt(sequenceNumber);
instance.checksum = checksum;
instance.pubkey = pubkey;
instance.timestamp = currentTime;
instance.data = reader.readBytes(
Math.min(MAX_DATA_LEN, bufLen - reader.position),
);
instances.push(instance);
}
return instances;
}
public static fromString(str: string, pubkey: Buffer): IrcMessageV0[] {
const buf = Buffer.from(str);
return IrcMessageV0.fromBuffer(buf, pubkey);
}
/**
* Deserializes an irc message
* @param buf
*/
public static deserialize(buf: Buffer): IrcMessageV0 {
const instance = new IrcMessageV0();
const reader = new BufferReader(buf);
reader.readBigSize(); // read type
instance.length = reader.readBigSize();
instance.sequenceLength = reader.readBigSize();
instance.sequenceNumber = reader.readBigSize();
instance.checksum = reader.readUInt32BE();
instance.signature = reader.readBytes(64);
instance.pubkey = reader.readBytes(33);
instance.timestamp = reader.readUInt32BE();
const dataLen = reader.readUInt16BE();
instance.data = reader.readBytes(dataLen);
return instance;
}
public type = IrcMessageV0.type;
public length: bigint;
public sequenceLength: bigint;
public sequenceNumber: bigint;
public checksum: number;
public signature: Buffer;
public pubkey: Buffer;
public timestamp: number;
public data: Buffer;
public serializeWithoutSig(): Buffer {
const writer = new BufferWriter();
writer.writeBigSize(this.sequenceLength);
writer.writeBigSize(this.sequenceNumber);
writer.writeUInt64BE(this.checksum);
writer.writeBytes(this.pubkey);
writer.writeUInt32BE(this.timestamp);
writer.writeUInt16BE(this.data.length);
writer.writeBytes(this.data);
return writer.toBuffer();
}
/**
* Serializes the irc_message_v0
*/
public serialize(): Buffer {
const writer = new BufferWriter();
writer.writeBigSize(this.type);
const dataWriter = new BufferWriter();
dataWriter.writeBigSize(this.sequenceLength);
dataWriter.writeBigSize(this.sequenceNumber);
dataWriter.writeUInt32BE(this.checksum);
dataWriter.writeBytes(this.signature);
dataWriter.writeBytes(this.pubkey);
dataWriter.writeUInt32BE(this.timestamp);
dataWriter.writeUInt16BE(this.data.length);
dataWriter.writeBytes(this.data);
writer.writeBigSize(dataWriter.size);
writer.writeBytes(dataWriter.toBuffer());
return writer.toBuffer();
}
}
export class IrcMessageWithoutSig {
constructor(
readonly sequenceLength: bigint,
readonly sequenceNumber: bigint,
readonly checksum: number,
readonly signature: Buffer,
readonly pubkey: Buffer,
readonly data: Buffer,
) {}
}