diff options
Diffstat (limited to 'src/access')
| -rw-r--r-- | src/access/screen.rs | 32 |
1 files changed, 21 insertions, 11 deletions
diff --git a/src/access/screen.rs b/src/access/screen.rs index 010ef49..8fd2c61 100644 --- a/src/access/screen.rs +++ b/src/access/screen.rs @@ -716,24 +716,29 @@ pub(crate) fn apply_bytes( // A change of the actor this node writes as, and not one it made: another node writes // as it too (two started from one document file with `--keep-actor`, a copied data // directory). Each would make changes the other's peers refuse as forged; the node - // writes on as a fresh actor at once. The change is judged as any other. - let fresh_actor = changes + // writes on as a fresh actor once these are judged. They are judged as any other, + // under the actor still: one at a seq the node made a change at is forged + // (`Signatures::forks`). + let twin = changes .iter() .find(|change| { change.actor_id() == doc.get_actor() && !crate::document::changes::holds(&*doc, &change.hash()) }) - .map(|change| { + .map(Change::seq); + let switch = |doc: &mut Document| { + twin.map(|seq| { let actor = crate::document::ActorId::random(); tracing::warn!( actor = %doc.get_actor(), - seq = change.seq(), + seq, fresh = %actor, "A change of this node's actor that it didn't make: another node writes as it (its files copied?); writing as a fresh actor" ); doc.set_actor(actor.clone()); actor - }); + }) + }; let mut screening = screening.lock_or_recover(); let screening = screening.of(epoch_seq); // Into an empty document of the first epoch, a root only as pinned: one given or @@ -777,7 +782,7 @@ pub(crate) fn apply_bytes( screening.record(refused_roots); if changes.is_empty() && screening.waiting.len() == 0 { return Ok(Outcome { - fresh_actor, + fresh_actor: switch(doc), ..Outcome::default() }); } @@ -792,7 +797,9 @@ pub(crate) fn apply_bytes( &mut screening.refusals, signatures, log, - )?; + ); + let fresh_actor = switch(doc); + let screened = screened?; let outcome = Outcome { refused_again: received > 0 && screened.refused_again == received, roots: screened.roots.iter().copied().collect(), @@ -1128,14 +1135,16 @@ mod tests { assert!(building.refused[0].why.contains("builds on refused change")); } - /// A change of the node's own actor that it didn't make: it writes on as a fresh - /// actor. Its own changes coming back change nothing. + /// A change of the node's own actor that it didn't make: refused as forged where the + /// node made one at its seq, and it writes on as a fresh actor. Its own changes + /// coming back change nothing. #[test] fn another_writing_as_this_node() { let mut theirs = genesis(); let mut ours = theirs.fork().with_actor(theirs.get_actor().clone()); let screening = std::sync::Mutex::new(Screening::default()); - let take = |doc: &mut Document, from: &Document, since: &[ChangeHash]| { + let mut signatures = Signatures::default(); + let mut take = |doc: &mut Document, from: &Document, since: &[ChangeHash]| { let bytes: Vec<u8> = received(from, since) .iter() .flat_map(|change| change.raw_bytes().to_vec()) @@ -1146,7 +1155,7 @@ mod tests { 0, &bytes, &screening, - None, + Some(&mut signatures), &mut crate::document::PatchLog::inactive(), ) .unwrap() @@ -1166,6 +1175,7 @@ mod tests { json!(2), ); let outcome = take(&mut ours, &theirs, &before); + assert_eq!(outcome.forged, 1); assert_eq!(outcome.fresh_actor.as_ref(), Some(ours.get_actor())); assert_ne!(ours.get_actor(), &actor); } |
