import b4a from 'b4a' import crypto from 'hypercore-crypto' export const PROTOCOL_NAME = 'bare-os-v1' export const TOPIC_STRING = 'bare-os-v1' /** Optional second Protomux channel for app-level RPC (paired when `BARE_OS_PROTOMUX_APP_CHANNEL` is set). */ export const PROTOCOL_APP_CHANNEL_NAME = 'bare-os-app-v1' /** Optional capability/datagram side channel (paired when `BARE_OS_PROTOMUX_CAP_CHANNEL` is set). */ export const PROTOCOL_CAP_CHANNEL_NAME = 'bare-os-cap-v1' /** Global swarm chat channel (paired by default; opt out with `BARE_OS_PROTOMUX_CHAT_CHANNEL=0`). */ export const PROTOCOL_CHAT_CHANNEL_NAME = 'bare-os-chat-v1' /** Meshdrop control/data channel (paired by default; opt out with `BARE_OS_PROTOMUX_MESHDROP_CHANNEL=0`). */ export const PROTOCOL_MESHDROP_CHANNEL_NAME = 'bare-os-meshdrop-v1' export const BLOCK_SIZE = 512 export const MBR_MAGIC = b4a.from('BIOS') export function topicKey(b4aMod = b4a) { return crypto.hash(b4aMod.from(TOPIC_STRING)) } export function buildMbr(primaryKey, failoverKeys = []) { if (primaryKey.byteLength !== 32) { throw new Error('primaryKey must be 32 bytes') } const mbr = b4a.alloc(BLOCK_SIZE) mbr.set(MBR_MAGIC) mbr.set(primaryKey, 8) const slots = [40, 72] for (let i = 0; i < slots.length; i++) { const k = failoverKeys[i] if (k) { if (k.byteLength !== 32) throw new Error('failover key must be 32 bytes') mbr.set(k, slots[i]) } } return mbr } export function parseMbr(mbr) { if (mbr.byteLength < 104) throw new Error('MBR too short') if (b4a.toString(mbr.slice(0, 4)) !== 'BIOS') { throw new Error('Invalid MBR magic') } const keys = [mbr.slice(8, 40), mbr.slice(40, 72), mbr.slice(72, 104)].filter( (k) => !b4a.equals(k, b4a.alloc(32)) ) return { keys } }