aboutsummaryrefslogtreecommitdiffstats
path: root/src/access/screen.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/access/screen.rs')
-rw-r--r--src/access/screen.rs32
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);
}