aboutsummaryrefslogtreecommitdiffstats
path: root/src/marmot.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/marmot.js')
-rw-r--r--src/marmot.js15
1 files changed, 11 insertions, 4 deletions
diff --git a/src/marmot.js b/src/marmot.js
index 7dd55d6..f6153a0 100644
--- a/src/marmot.js
+++ b/src/marmot.js
@@ -382,6 +382,7 @@ export function readKeyPackageEvent(ev, at = now()) {
return {
id: ev.id, pubkey: ev.pubkey, slot: d, ref: i, created_at: ev.created_at, lastResort,
keyPackage: kp.keyPackage,
+ sigKey: bytesToHex(kp.leaf.signatureKey), // which device: the leaf it would occupy
components: idList.dec(comp(kp.leaf.extensions, COMP.APP_COMPONENTS)),
extensions: caps.extensions, proposals: caps.proposals,
client: ev.tags.find((t) => t[0] === "client")?.[1] || "",
@@ -389,17 +390,23 @@ export function readKeyPackageEvent(ev, at = now()) {
} catch { return null; }
}
-// One candidate per (author, slot) — the newest, lower id on a tie — then
-// single-use packages before last-resort ones, fresher first, lower ref last.
-export function pickKeyPackage(candidates) {
+// One candidate per (author, slot) — the newest, lower id on a tie: a slot
+// is one installation, so this is one package per device. Ordered single-use
+// before last-resort, fresher first, lower ref last; at most `max` of them
+// (Marmot's multi-device direction caps an account at ten leaves).
+export const MAX_DEVICES = 10;
+export function pickKeyPackages(candidates, max = MAX_DEVICES) {
const slots = new Map();
for (const c of candidates) {
const k = c.pubkey + c.slot, cur = slots.get(k);
if (!cur || c.created_at > cur.created_at || (c.created_at === cur.created_at && c.id < cur.id)) slots.set(k, c);
}
return [...slots.values()].sort((a, b) =>
- (a.lastResort - b.lastResort) || (b.created_at - a.created_at) || (a.ref < b.ref ? -1 : 1))[0] || null;
+ (a.lastResort - b.lastResort) || (b.created_at - a.created_at) || (a.ref < b.ref ? -1 : 1)).slice(0, max);
}
+export const pickKeyPackage = (candidates) => pickKeyPackages(candidates, 1)[0] || null;
+// the signature keys of every leaf in a state: which devices are already in
+export const leafKeys = (state) => mls.members(state).map((m) => bytesToHex(m.signatureKey));
// Can this KeyPackage join a group in this state?
export function fits(state, cand) {