lotus-sdk
Version:
Central repository for several classes of tools for integrating with, and building for, the Lotusia ecosystem
101 lines (100 loc) • 3.19 kB
JavaScript
import { Hash } from '../bitcore/crypto/hash.js';
import { Random } from '../bitcore/crypto/random.js';
import { BaseMessageType } from './types.js';
export class P2PProtocol {
createMessage(type, payload, from, options) {
const messageId = this._generateMessageId();
return {
type,
from,
to: options?.to,
payload,
timestamp: Date.now(),
messageId,
signature: options?.signature,
protocol: options?.protocol,
};
}
serialize(message) {
try {
const json = JSON.stringify(message);
return Buffer.from(json, 'utf8');
}
catch (error) {
throw new Error(`Failed to serialize message: ${error}`);
}
}
deserialize(data) {
try {
const json = data.toString('utf8');
const message = JSON.parse(json);
return message;
}
catch (error) {
throw new Error(`Failed to deserialize message: ${error}`);
}
}
validateMessage(message) {
if (!message.type || typeof message.type !== 'string') {
return false;
}
if (!message.from || typeof message.from !== 'string') {
return false;
}
if (!message.timestamp || typeof message.timestamp !== 'number') {
return false;
}
if (!message.messageId || typeof message.messageId !== 'string') {
return false;
}
const now = Date.now();
const maxAge = 300000;
if (Math.abs(now - message.timestamp) > maxAge) {
return false;
}
return true;
}
validateMessageSize(message, maxSize = 1024 * 1024) {
const serialized = this.serialize(message);
return serialized.length <= maxSize;
}
computeMessageHash(message) {
const data = Buffer.concat([
Buffer.from(message.type),
Buffer.from(message.from),
Buffer.from(message.to || ''),
Buffer.from(message.messageId),
]);
return Hash.hmac(Hash.sha256, data, Buffer.from('lotus-lib-p2p-message-hash-key')).toString('hex');
}
createHandshake(peerId, metadata) {
return this.createMessage(BaseMessageType.PEER_HANDSHAKE, {
peerId,
timestamp: Date.now(),
metadata,
}, peerId);
}
createHeartbeat(peerId) {
return this.createMessage(BaseMessageType.PEER_HEARTBEAT, {
timestamp: Date.now(),
}, peerId);
}
createDisconnect(peerId, reason) {
return this.createMessage(BaseMessageType.PEER_DISCONNECT, {
reason,
timestamp: Date.now(),
}, peerId);
}
createError(peerId, error, context) {
return this.createMessage(BaseMessageType.ERROR, {
error,
context,
timestamp: Date.now(),
}, peerId);
}
_generateMessageId() {
const timestamp = Date.now().toString(36);
const random = Random.getRandomBuffer(8).toString('hex');
return `${timestamp}-${random}`;
}
}