update
This commit is contained in:
@@ -762,6 +762,17 @@ impl Community {
|
||||
let mut held = Vec::with_capacity(base.stepped.len() + self.state.held_roots.len());
|
||||
|
||||
for key in base.stepped {
|
||||
let known = self
|
||||
.state
|
||||
.held_roots
|
||||
.iter()
|
||||
.chain(held.iter())
|
||||
.any(|root| root.epoch == key.epoch && root.key == key.key);
|
||||
|
||||
if known {
|
||||
continue;
|
||||
}
|
||||
|
||||
held.push(HeldRoot {
|
||||
epoch: key.epoch,
|
||||
key: key.key,
|
||||
@@ -770,7 +781,17 @@ impl Community {
|
||||
});
|
||||
}
|
||||
|
||||
held.extend(self.state.held_roots.iter().copied());
|
||||
for root in &self.state.held_roots {
|
||||
if held
|
||||
.iter()
|
||||
.any(|kept| kept.epoch == root.epoch && kept.key == root.key)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
held.push(*root);
|
||||
}
|
||||
|
||||
self.state.held_roots = held;
|
||||
|
||||
if let Some(control_pk) = base.control_pk {
|
||||
|
||||
@@ -628,6 +628,11 @@ pub async fn fold(client: &Client, state: &CommunityState) -> Result<Option<Snap
|
||||
|
||||
if let Ok(edition) = cord02::open_edition(wrap, &plane.group, &plane.address, true)
|
||||
{
|
||||
observe(
|
||||
&mut observed,
|
||||
edition.author,
|
||||
wrap.created_at.as_secs().saturating_mul(1000),
|
||||
);
|
||||
editions.push(edition);
|
||||
}
|
||||
}
|
||||
@@ -1199,6 +1204,75 @@ mod tests {
|
||||
});
|
||||
}
|
||||
|
||||
/// The reference counts anyone seen publishing anywhere, and a control edit
|
||||
/// is the one publication that leaves no other trace: an npub that has
|
||||
/// never joined a channel and never touched the Guestbook exists in no
|
||||
/// other plane, so a fold that reads only those reads them as a stranger.
|
||||
#[test]
|
||||
fn a_control_editions_author_is_observed_as_a_member() {
|
||||
smol::block_on(async {
|
||||
let client = client();
|
||||
let keys = Keys::generate();
|
||||
let signer = UniversalSigner::new(keys.clone());
|
||||
let editor = Keys::generate();
|
||||
|
||||
let created = create(&client, &signer, &metadata("coop"))
|
||||
.await
|
||||
.expect("creates");
|
||||
|
||||
let community_head = created
|
||||
.heads
|
||||
.iter()
|
||||
.find(|head| head.entity == *created.id.as_bytes())
|
||||
.expect("a community head");
|
||||
let writer = cord02::ControlWriter {
|
||||
author: editor.public_key(),
|
||||
read: control_group_key(&created.community_root, &created.id, cord02::ROOT_EPOCH)
|
||||
.expect("a reading key"),
|
||||
signer: control_signer_group_key(
|
||||
&created.control_root.expect("a control root"),
|
||||
&created.id,
|
||||
cord02::ROOT_EPOCH,
|
||||
)
|
||||
.expect("a signing key"),
|
||||
};
|
||||
|
||||
// The editor holds no grant, so the edit is inert: it supersedes
|
||||
// nothing. It is still a publication by that npub.
|
||||
let (wrap, _) = writer
|
||||
.set_community_metadata(
|
||||
&editor,
|
||||
&created.id,
|
||||
&metadata("coop two"),
|
||||
Some(community_head),
|
||||
None,
|
||||
Timestamp::now().as_secs() + 1,
|
||||
)
|
||||
.await
|
||||
.expect("publishes");
|
||||
client.database().save_event(&wrap).await.expect("saves");
|
||||
|
||||
let snapshot = fold(&client, &created)
|
||||
.await
|
||||
.expect("folds")
|
||||
.expect("a control plane");
|
||||
|
||||
assert!(
|
||||
snapshot.members.contains(&editor.public_key()),
|
||||
"an edition's author is a member the fold has seen publishing"
|
||||
);
|
||||
assert_eq!(
|
||||
snapshot
|
||||
.control
|
||||
.community
|
||||
.as_ref()
|
||||
.map(|metadata| metadata.name.as_str()),
|
||||
Some("coop"),
|
||||
"an unauthorized edit still changes nothing"
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/// The other half of `create`: the membership must reach the account's
|
||||
/// Community List, and a later create must union into it rather than replace
|
||||
/// it (CORD-02 §8 read-modify-write).
|
||||
|
||||
Reference in New Issue
Block a user