aboutsummaryrefslogtreecommitdiffstats
path: root/src/concord.js
diff options
context:
space:
mode:
Diffstat (limited to 'src/concord.js')
-rw-r--r--src/concord.js25
1 files changed, 25 insertions, 0 deletions
diff --git a/src/concord.js b/src/concord.js
index 63a83b9..521bfc8 100644
--- a/src/concord.js
+++ b/src/concord.js
@@ -187,6 +187,11 @@ export const foldControl = (entries, { ownerHex, cid }) => {
// entries: [{ rumor, author }] โ€” group by (vsk, eid), take highest intact version
let byEntity = new Map();
for (let e of entries) {
+ // Only the owner's editions are honored below, so only they compete for
+ // a head: anyone holding the control stream's key (every member of a
+ // public community) could otherwise sign a higher version and blank the
+ // owner's ban list, name or channels.
+ if (e.author !== ownerHex) continue;
let tag = (k) => e.rumor.tags?.find((t) => t[0] === k)?.[1];
let vsk = tag("vsk"), eid = tag("eid"), ev = +tag("ev");
if (vsk === undefined || !eid || !(ev >= 1)) continue;
@@ -225,6 +230,26 @@ export const foldControl = (entries, { ownerHex, cid }) => {
return state;
};
+// The owner's ban list as it stands: the head edition (its version, and the
+// hash a successor chains to) and the keys on it. Same winner as the fold.
+export const banlistHead = (entries, { ownerHex, cid }) => {
+ let eid = banlistEid(cid), cur = null;
+ for (let e of entries) {
+ if (e.author !== ownerHex || e.rumor.kind !== 3308) continue;
+ let tag = (k) => e.rumor.tags?.find((t) => t[0] === k)?.[1];
+ let ev = +tag("ev");
+ if (tag("vsk") !== "4" || tag("eid") !== eid || !(ev >= 1)) continue;
+ if (!cur || ev > cur.ev || (ev === cur.ev && e.rumor.id < cur.id)) cur = { ev, id: e.rumor.id, ep: tag("ep") || null, content: e.rumor.content };
+ }
+ let list = [];
+ try { let c = cur && JSON.parse(cur.content); if (Array.isArray(c)) list = c.filter((x) => /^[0-9a-f]{64}$/.test(x)); } catch {}
+ return { eid, version: cur ? cur.ev : 0, hash: cur ? editionHash(eid, cur.ev, cur.ep, cur.content) : null, list };
+};
+
+// The next ban-list edition: `list` replaces the one that stands.
+export const makeBanlist = (head, list, nowMs) =>
+ makeEdition({ vsk: 4, eid: head.eid, version: head.version + 1, prev: head.hash || undefined, content: JSON.stringify(list) }, nowMs);
+
// ---- CORD-02 ยง5 guestbook fold ----
// entries: [{ rumor, author }], returns Map(npub -> { state: 'join'|'leave'|'kick', t })
export const foldGuestbook = (entries, { nowMs, banned = new Set(), ownerHex } = {}) => {