diff --git a/src/signing/petition_types/mod.rs b/src/signing/petition_types/mod.rs index 176e0830..f71a3b89 100644 --- a/src/signing/petition_types/mod.rs +++ b/src/signing/petition_types/mod.rs @@ -1,11 +1,13 @@ mod factor_list_kind; -mod petition_factors_types; mod petition_for_entity; +mod petition_for_factors_types; mod petition_for_transaction; mod petitions; +mod petitions_status; pub use factor_list_kind::*; -pub use petition_factors_types::*; pub use petition_for_entity::*; +pub use petition_for_factors_types::*; pub(crate) use petition_for_transaction::*; pub(crate) use petitions::*; +pub(crate) use petitions_status::*; diff --git a/src/signing/petition_types/petition_factors_types/mod.rs b/src/signing/petition_types/petition_factors_types/mod.rs deleted file mode 100644 index c870bd1d..00000000 --- a/src/signing/petition_types/petition_factors_types/mod.rs +++ /dev/null @@ -1,18 +0,0 @@ -mod factor_source_referencing; -mod neglected_factor_instance; -mod petition_factors_input; -mod petition_factors_state; -mod petition_factors_state_snapshot; -mod petition_factors_status; -mod petition_factors_sub_state; -mod petition_for_factors; - -use petition_factors_input::*; -use petition_factors_state::*; -use petition_factors_state_snapshot::*; -use petition_factors_sub_state::*; - -pub(crate) use factor_source_referencing::*; -pub use neglected_factor_instance::*; -pub use petition_factors_status::*; -pub use petition_for_factors::*; diff --git a/src/signing/petition_types/petition_factors_types/petition_factors_status.rs b/src/signing/petition_types/petition_factors_types/petition_factors_status.rs deleted file mode 100644 index df496f6a..00000000 --- a/src/signing/petition_types/petition_factors_types/petition_factors_status.rs +++ /dev/null @@ -1,24 +0,0 @@ -/// The status of building using a certain list of factors, e.g. threshold or -/// override factors list. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum PetitionFactorsStatus { - /// In progress, still gathering output from factors (signatures or public keys). - InProgress, - - /// Finished building with factors, either successfully or failed. - Finished(PetitionFactorsStatusFinished), -} - -/// Finished building with factors, either successfully or failed. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum PetitionFactorsStatusFinished { - /// Successful completion of building with factors. - Success, - - /// Failure building with factors, either a simulated status, as in what - /// would happen if we skipped a factor source, or a real failure, as in, - /// the user explicitly chose to skip a factor source even though she was - /// advised it would result in some transaction failing. Or we failed to - /// use a required factor source for what some reason. - Fail, -} diff --git a/src/signing/petition_types/petition_for_entity.rs b/src/signing/petition_types/petition_for_entity.rs index a62c382f..d4666dd1 100644 --- a/src/signing/petition_types/petition_for_entity.rs +++ b/src/signing/petition_types/petition_for_entity.rs @@ -68,13 +68,13 @@ impl PetitionForEntity { /// Returns `true` if signatures requirement has been fulfilled, either by /// override factors or by threshold factors pub fn has_signatures_requirement_been_fulfilled(&self) -> bool { - self.status() == PetitionFactorsStatus::Finished(PetitionFactorsStatusFinished::Success) + self.status() == PetitionForFactorsStatus::Finished(PetitionFactorsStatusFinished::Success) } /// Returns `true` if the transaction of this petition already has failed due /// to too many factors neglected pub fn has_failed(&self) -> bool { - self.status() == PetitionFactorsStatus::Finished(PetitionFactorsStatusFinished::Fail) + self.status() == PetitionForFactorsStatus::Finished(PetitionFactorsStatusFinished::Fail) } fn map_list_then_form_union(&self, map: F) -> IndexSet @@ -172,9 +172,9 @@ impl PetitionForEntity { ) -> bool { assert!(self.references_any_factor_source(&factor_source_ids)); match self.status() { - PetitionFactorsStatus::Finished(PetitionFactorsStatusFinished::Fail) => true, - PetitionFactorsStatus::Finished(PetitionFactorsStatusFinished::Success) => false, - PetitionFactorsStatus::InProgress => false, + PetitionForFactorsStatus::Finished(PetitionFactorsStatusFinished::Fail) => true, + PetitionForFactorsStatus::Finished(PetitionFactorsStatusFinished::Success) => false, + PetitionForFactorsStatus::InProgress => false, } } @@ -184,7 +184,7 @@ impl PetitionForEntity { ) -> Option { let status_if_neglected = self.status_if_neglected_factors(factor_source_ids); match status_if_neglected { - PetitionFactorsStatus::Finished(finished_reason) => match finished_reason { + PetitionForFactorsStatus::Finished(finished_reason) => match finished_reason { PetitionFactorsStatusFinished::Fail => { let intent_hash = self.intent_hash.clone(); Some(InvalidTransactionIfNeglected::new( @@ -194,14 +194,14 @@ impl PetitionForEntity { } PetitionFactorsStatusFinished::Success => None, }, - PetitionFactorsStatus::InProgress => None, + PetitionForFactorsStatus::InProgress => None, } } pub fn status_if_neglected_factors( &self, factor_source_ids: IndexSet, - ) -> PetitionFactorsStatus { + ) -> PetitionForFactorsStatus { let simulation = self.clone(); for factor_source_id in factor_source_ids.iter() { simulation.neglect_if_referenced(NeglectedFactor::new( @@ -232,9 +232,9 @@ impl PetitionForEntity { self.both_void(|p| p.neglect_if_referenced(neglected.clone())); } - pub fn status(&self) -> PetitionFactorsStatus { - use PetitionFactorsStatus::*; + pub fn status(&self) -> PetitionForFactorsStatus { use PetitionFactorsStatusFinished::*; + use PetitionForFactorsStatus::*; self.both( |p| p.status(), @@ -252,12 +252,14 @@ impl PetitionForEntity { (Some(threshold), None) => threshold, (None, Some(r#override)) => r#override, (Some(threshold), Some(r#override)) => match (threshold, r#override) { - (InProgress, InProgress) => PetitionFactorsStatus::InProgress, - (Finished(Fail), InProgress) => PetitionFactorsStatus::InProgress, - (InProgress, Finished(Fail)) => PetitionFactorsStatus::InProgress, - (Finished(Fail), Finished(Fail)) => PetitionFactorsStatus::Finished(Fail), - (Finished(Success), _) => PetitionFactorsStatus::Finished(Success), - (_, Finished(Success)) => PetitionFactorsStatus::Finished(Success), + (InProgress, InProgress) => PetitionForFactorsStatus::InProgress, + (Finished(Fail), InProgress) => PetitionForFactorsStatus::InProgress, + (InProgress, Finished(Fail)) => PetitionForFactorsStatus::InProgress, + (Finished(Fail), Finished(Fail)) => { + PetitionForFactorsStatus::Finished(Fail) + } + (Finished(Success), _) => PetitionForFactorsStatus::Finished(Success), + (_, Finished(Success)) => PetitionForFactorsStatus::Finished(Success), }, } }, @@ -461,7 +463,7 @@ mod tests { #[test] fn debug() { - pretty_assertions::assert_eq!(format!("{:?}", Sut::sample()), "intent_hash: TXID(\"dedede\"), entity: acco_Grace, \"threshold_factors PetitionForFactors(input: PetitionFactorsInput(factors: {\\n factor_source_id: Device:00, derivation_path: 0/A/tx/6,\\n factor_source_id: Arculus:03, derivation_path: 0/A/tx/6,\\n factor_source_id: Yubikey:05, derivation_path: 0/A/tx/6,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\"\"override_factors PetitionForFactors(input: PetitionFactorsInput(factors: {\\n factor_source_id: Ledger:01, derivation_path: 0/A/tx/6,\\n factor_source_id: Arculus:04, derivation_path: 0/A/tx/6,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\""); + pretty_assertions::assert_eq!(format!("{:?}", Sut::sample()), "intent_hash: TXID(\"dedede\"), entity: acco_Grace, \"threshold_factors PetitionForFactors(input: PetitionForFactorsInput(factors: {\\n factor_source_id: Device:00, derivation_path: 0/A/tx/6,\\n factor_source_id: Arculus:03, derivation_path: 0/A/tx/6,\\n factor_source_id: Yubikey:05, derivation_path: 0/A/tx/6,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\"\"override_factors PetitionForFactors(input: PetitionForFactorsInput(factors: {\\n factor_source_id: Ledger:01, derivation_path: 0/A/tx/6,\\n factor_source_id: Arculus:04, derivation_path: 0/A/tx/6,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\""); } #[test] diff --git a/src/signing/petition_types/petition_factors_types/factor_source_referencing.rs b/src/signing/petition_types/petition_for_factors_types/factor_source_referencing.rs similarity index 90% rename from src/signing/petition_types/petition_factors_types/factor_source_referencing.rs rename to src/signing/petition_types/petition_for_factors_types/factor_source_referencing.rs index f4ab2087..e3c26f31 100644 --- a/src/signing/petition_types/petition_factors_types/factor_source_referencing.rs +++ b/src/signing/petition_types/petition_for_factors_types/factor_source_referencing.rs @@ -1,5 +1,6 @@ use crate::prelude::*; +/// A trait for types which reference a factor source. pub(crate) trait FactorSourceReferencing: std::hash::Hash + PartialEq + Eq + Clone { fn factor_source_id(&self) -> FactorSourceIDFromHash; } diff --git a/src/signing/petition_types/petition_for_factors_types/mod.rs b/src/signing/petition_types/petition_for_factors_types/mod.rs new file mode 100644 index 00000000..700c2697 --- /dev/null +++ b/src/signing/petition_types/petition_for_factors_types/mod.rs @@ -0,0 +1,7 @@ +mod factor_source_referencing; +mod neglected_factor_instance; +mod petition_for_factors; + +pub(crate) use factor_source_referencing::*; +pub use neglected_factor_instance::*; +pub(crate) use petition_for_factors::*; diff --git a/src/signing/petition_types/petition_factors_types/neglected_factor_instance.rs b/src/signing/petition_types/petition_for_factors_types/neglected_factor_instance.rs similarity index 100% rename from src/signing/petition_types/petition_factors_types/neglected_factor_instance.rs rename to src/signing/petition_types/petition_for_factors_types/neglected_factor_instance.rs diff --git a/src/signing/petition_types/petition_for_factors_types/petition_for_factors/mod.rs b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/mod.rs new file mode 100644 index 00000000..937d3359 --- /dev/null +++ b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/mod.rs @@ -0,0 +1,16 @@ +#[allow(clippy::module_inception)] +mod petition_for_factors; + +mod petition_for_factors_input; +mod petition_for_factors_state; +mod petition_for_factors_state_snapshot; +mod petition_for_factors_status; +mod petition_for_factors_sub_state; + +use petition_for_factors_input::*; +use petition_for_factors_state::*; +use petition_for_factors_state_snapshot::*; +use petition_for_factors_sub_state::*; + +pub(crate) use petition_for_factors::*; +pub(crate) use petition_for_factors_status::*; diff --git a/src/signing/petition_types/petition_factors_types/petition_for_factors.rs b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors.rs similarity index 84% rename from src/signing/petition_types/petition_factors_types/petition_for_factors.rs rename to src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors.rs index 15721757..3ceba42a 100644 --- a/src/signing/petition_types/petition_factors_types/petition_for_factors.rs +++ b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors.rs @@ -8,29 +8,29 @@ pub struct PetitionForFactors { pub factor_list_kind: FactorListKind, /// Factors to sign with and the required number of them. - pub(crate) input: PetitionFactorsInput, - state: RefCell, + pub(crate) input: PetitionForFactorsInput, + state: RefCell, } impl HasSampleValues for PetitionForFactors { fn sample() -> Self { - Self::new(FactorListKind::Threshold, PetitionFactorsInput::sample()) + Self::new(FactorListKind::Threshold, PetitionForFactorsInput::sample()) } fn sample_other() -> Self { Self::new( FactorListKind::Override, - PetitionFactorsInput::sample_other(), + PetitionForFactorsInput::sample_other(), ) } } impl PetitionForFactors { - pub fn new(factor_list_kind: FactorListKind, input: PetitionFactorsInput) -> Self { + pub fn new(factor_list_kind: FactorListKind, input: PetitionForFactorsInput) -> Self { Self { factor_list_kind, input, - state: RefCell::new(PetitionFactorsState::new()), + state: RefCell::new(PetitionForFactorsState::new()), } } @@ -55,12 +55,12 @@ impl PetitionForFactors { } Some(Self::new( FactorListKind::Threshold, - PetitionFactorsInput::new_threshold(IndexSet::from_iter(factors), threshold), + PetitionForFactorsInput::new_threshold(IndexSet::from_iter(factors), threshold), )) } pub fn new_unsecurified(factor: HierarchicalDeterministicFactorInstance) -> Self { - Self::new_threshold(vec![factor], 1).unwrap() // define as 1/1 threshold factor, which is a good definition. + Self::new_threshold(vec![factor], 1).expect("Factors is not empty") // define as 1/1 threshold factor, which is a good definition. } pub fn new_override(factors: Vec) -> Option { @@ -69,7 +69,7 @@ impl PetitionForFactors { } Some(Self::new( FactorListKind::Override, - PetitionFactorsInput::new_override(IndexSet::from_iter(factors)), + PetitionForFactorsInput::new_override(IndexSet::from_iter(factors)), )) } @@ -150,7 +150,7 @@ impl PetitionForFactors { self.input.reference_factor_source_with_id(factor_source_id) } - fn state_snapshot(&self) -> PetitionFactorsStateSnapshot { + fn state_snapshot(&self) -> PetitionForFactorsStateSnapshot { self.state.borrow().snapshot() } @@ -170,7 +170,7 @@ impl PetitionForFactors { is_finished_with_fail } - fn finished_with(&self) -> Option { + fn get_finished_with(&self) -> Option { if self.is_finished_successfully() { Some(PetitionFactorsStatusFinished::Success) } else if self.is_finished_with_fail() { @@ -180,11 +180,11 @@ impl PetitionForFactors { } } - pub fn status(&self) -> PetitionFactorsStatus { - if let Some(finished_state) = self.finished_with() { - return PetitionFactorsStatus::Finished(finished_state); + pub fn status(&self) -> PetitionForFactorsStatus { + if let Some(finished_state) = self.get_finished_with() { + return PetitionForFactorsStatus::Finished(finished_state); } - PetitionFactorsStatus::InProgress + PetitionForFactorsStatus::InProgress } pub fn debug_str(&self) -> String { diff --git a/src/signing/petition_types/petition_factors_types/petition_factors_input.rs b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_input.rs similarity index 80% rename from src/signing/petition_types/petition_factors_types/petition_factors_input.rs rename to src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_input.rs index 245d0967..ee8919a4 100644 --- a/src/signing/petition_types/petition_factors_types/petition_factors_input.rs +++ b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_input.rs @@ -1,9 +1,10 @@ use super::*; use crate::prelude::*; +/// The input passed to a PetitionsForFactors #[derive(Clone, PartialEq, Eq, derive_more::Debug)] -#[debug("PetitionFactorsInput(factors: {:#?})", self.factors)] -pub struct PetitionFactorsInput { +#[debug("PetitionForFactorsInput(factors: {:#?})", self.factors)] +pub struct PetitionForFactorsInput { /// Factors to sign with. pub(super) factors: IndexSet, @@ -11,7 +12,7 @@ pub struct PetitionFactorsInput { pub(super) required: i8, } -impl HasSampleValues for PetitionFactorsInput { +impl HasSampleValues for PetitionForFactorsInput { fn sample() -> Self { Self::new( IndexSet::from_iter([ @@ -30,7 +31,7 @@ impl HasSampleValues for PetitionFactorsInput { } } -impl PetitionFactorsInput { +impl PetitionForFactorsInput { pub(super) fn new( factors: IndexSet, required: i8, @@ -62,19 +63,19 @@ impl PetitionFactorsInput { self.factors.len() as i8 } - fn remaining_factors_until_success(&self, snapshot: PetitionFactorsStateSnapshot) -> i8 { + fn remaining_factors_until_success(&self, snapshot: PetitionForFactorsStateSnapshot) -> i8 { self.required - snapshot.signed_count() } - pub(super) fn is_fulfilled_by(&self, snapshot: PetitionFactorsStateSnapshot) -> bool { + pub(super) fn is_fulfilled_by(&self, snapshot: PetitionForFactorsStateSnapshot) -> bool { self.remaining_factors_until_success(snapshot) <= 0 } - fn factors_left_to_prompt(&self, snapshot: PetitionFactorsStateSnapshot) -> i8 { + fn factors_left_to_prompt(&self, snapshot: PetitionForFactorsStateSnapshot) -> i8 { self.factors_count() - snapshot.prompted_count() } - pub(super) fn is_failure_with(&self, snapshot: PetitionFactorsStateSnapshot) -> bool { + pub(super) fn is_failure_with(&self, snapshot: PetitionForFactorsStateSnapshot) -> bool { let signed_or_pending = self.factors_left_to_prompt(snapshot.clone()) + snapshot.signed_count(); let is_failure_with = signed_or_pending < self.required; diff --git a/src/signing/petition_types/petition_factors_types/petition_factors_state.rs b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_state.rs similarity index 83% rename from src/signing/petition_types/petition_factors_types/petition_factors_state.rs rename to src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_state.rs index f34d9e4d..8e98aa69 100644 --- a/src/signing/petition_types/petition_factors_types/petition_factors_state.rs +++ b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_state.rs @@ -6,32 +6,32 @@ use crate::prelude::*; /// Mutable state of `PetitionForFactors`, keeping track of which factors that /// have either signed or been neglected. #[derive(Clone, PartialEq, Eq, derive_more::Debug)] -#[debug("PetitionFactorsState(signed: {:?}, neglected: {:?})", signed.borrow().clone(), neglected.borrow().clone())] -pub struct PetitionFactorsState { +#[debug("PetitionForFactorsState(signed: {:?}, neglected: {:?})", signed.borrow().clone(), neglected.borrow().clone())] +pub struct PetitionForFactorsState { /// Factors that have signed. - signed: RefCell>, + signed: RefCell>, /// Neglected factors, either due to user explicitly skipping, or due /// implicitly neglected to failure. - neglected: RefCell>, + neglected: RefCell>, } -impl PetitionFactorsState { - /// Creates a new `PetitionFactorsState`. +impl PetitionForFactorsState { + /// Creates a new `PetitionForFactorsState`. pub(super) fn new() -> Self { Self { - signed: RefCell::new(PetitionFactorsSubState::<_>::new()), - neglected: RefCell::new(PetitionFactorsSubState::<_>::new()), + signed: RefCell::new(PetitionForFactorsSubState::<_>::new()), + neglected: RefCell::new(PetitionForFactorsSubState::<_>::new()), } } /// A reference to the neglected factors so far. - pub(super) fn neglected(&self) -> Ref> { + pub(super) fn neglected(&self) -> Ref> { self.neglected.borrow() } /// A reference to the factors which have been signed with so far. - pub(super) fn signed(&self) -> Ref> { + pub(super) fn signed(&self) -> Ref> { self.signed.borrow() } @@ -72,8 +72,8 @@ impl PetitionFactorsState { self.signed.borrow_mut().insert(signature) } - pub(super) fn snapshot(&self) -> PetitionFactorsStateSnapshot { - PetitionFactorsStateSnapshot::new(self.signed().snapshot(), self.neglected().snapshot()) + pub(super) fn snapshot(&self) -> PetitionForFactorsStateSnapshot { + PetitionForFactorsStateSnapshot::new(self.signed().snapshot(), self.neglected().snapshot()) } fn references_factor_source_by_id(&self, factor_source_id: FactorSourceIDFromHash) -> bool { @@ -90,9 +90,9 @@ mod tests { use super::*; - type Sut = PetitionFactorsState; + type Sut = PetitionForFactorsState; - impl PetitionFactorsState { + impl PetitionForFactorsState { fn test_neglect(&self, id: &HierarchicalDeterministicFactorInstance, simulated: bool) { self.neglect(&NeglectedFactorInstance::new( if simulated { diff --git a/src/signing/petition_types/petition_factors_types/petition_factors_state_snapshot.rs b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_state_snapshot.rs similarity index 90% rename from src/signing/petition_types/petition_factors_types/petition_factors_state_snapshot.rs rename to src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_state_snapshot.rs index 252ee17a..42ce36dc 100644 --- a/src/signing/petition_types/petition_factors_types/petition_factors_state_snapshot.rs +++ b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_state_snapshot.rs @@ -1,11 +1,9 @@ use crate::prelude::*; -use super::NeglectedFactorInstance; - -/// An immutable "snapshot" of `PetitionFactorsState` +/// An immutable "snapshot" of `PetitionForFactorsState` #[derive(Clone, PartialEq, Eq, derive_more::Debug)] #[debug("{}", self.debug_str())] -pub(super) struct PetitionFactorsStateSnapshot { +pub(super) struct PetitionForFactorsStateSnapshot { /// Factors that have signed. signed: IndexSet, @@ -13,7 +11,7 @@ pub(super) struct PetitionFactorsStateSnapshot { neglected: IndexSet, } -impl PetitionFactorsStateSnapshot { +impl PetitionForFactorsStateSnapshot { pub(super) fn new( signed: IndexSet, neglected: IndexSet, @@ -53,7 +51,7 @@ impl PetitionFactorsStateSnapshot { } } -impl HasSampleValues for PetitionFactorsStateSnapshot { +impl HasSampleValues for PetitionForFactorsStateSnapshot { fn sample() -> Self { Self::new( IndexSet::from_iter([HDSignature::sample(), HDSignature::sample_other()]), @@ -75,7 +73,7 @@ impl HasSampleValues for PetitionFactorsStateSnapshot { mod tests { use super::*; - type Sut = PetitionFactorsStateSnapshot; + type Sut = PetitionForFactorsStateSnapshot; #[test] fn equality() { diff --git a/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_status.rs b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_status.rs new file mode 100644 index 00000000..e5716aca --- /dev/null +++ b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_status.rs @@ -0,0 +1,61 @@ +/// The status of building using a certain list of factors, e.g. threshold or +/// override factors list. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PetitionForFactorsStatus { + /// In progress, still gathering output from factors (signatures or public keys). + InProgress, + + /// Finished building with factors, either successfully or failed. + Finished(PetitionFactorsStatusFinished), +} + +/// Finished building with factors, either successfully or failed. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum PetitionFactorsStatusFinished { + /// Successful completion of building with factors. + Success, + + /// Failure building with factors, either a simulated status, as in what + /// would happen if we skipped a factor source, or a real failure, as in, + /// the user explicitly chose to skip a factor source even though she was + /// advised it would result in some transaction failing. Or we failed to + /// use a required factor source for what some reason. + Fail, +} + +impl PetitionForFactorsStatus { + /// Reduces / aggergates a list of `PetitionForFactorsStatus` into some + /// other status, e.g. `PetitionsStatus`. + pub fn aggregate( + statuses: impl IntoIterator, + valid: T, + invalid: T, + pending: T, + ) -> T { + let statuses = statuses.into_iter().collect::>(); + + let are_all_valid = statuses.iter().all(|s| { + matches!( + s, + PetitionForFactorsStatus::Finished(PetitionFactorsStatusFinished::Success) + ) + }); + + if are_all_valid { + return valid; + } + + let is_some_invalid = statuses.iter().any(|s| { + matches!( + s, + PetitionForFactorsStatus::Finished(PetitionFactorsStatusFinished::Fail) + ) + }); + + if is_some_invalid { + return invalid; + } + + pending + } +} diff --git a/src/signing/petition_types/petition_factors_types/petition_factors_sub_state.rs b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_sub_state.rs similarity index 82% rename from src/signing/petition_types/petition_factors_types/petition_factors_sub_state.rs rename to src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_sub_state.rs index 51f38fd5..92ebf589 100644 --- a/src/signing/petition_types/petition_factors_types/petition_factors_sub_state.rs +++ b/src/signing/petition_types/petition_for_factors_types/petition_for_factors/petition_for_factors_sub_state.rs @@ -1,10 +1,10 @@ use crate::prelude::*; -/// A sub-state of `PetitionFactorsState` which can be used to track factors +/// A sub-state of `PetitionForFactorsState` which can be used to track factors /// that have signed or skipped. #[derive(Clone, PartialEq, Eq, derive_more::Debug)] #[debug("[{}]", factors.borrow().clone().into_iter().map(|f| format!("{:?}", f)).join(", "))] -pub struct PetitionFactorsSubState +pub struct PetitionForFactorsSubState where F: FactorSourceReferencing + std::fmt::Debug, { @@ -12,7 +12,7 @@ where factors: RefCell>, } -impl PetitionFactorsSubState { +impl PetitionForFactorsSubState { pub(super) fn new() -> Self { Self { factors: RefCell::new(IndexSet::new()), diff --git a/src/signing/petition_types/petition_for_transaction.rs b/src/signing/petition_types/petition_for_transaction.rs index 9761e2b5..c89f877d 100644 --- a/src/signing/petition_types/petition_for_transaction.rs +++ b/src/signing/petition_types/petition_for_transaction.rs @@ -127,6 +127,14 @@ impl PetitionForTransaction { ) } + pub fn status_of_each_petition_for_entity(&self) -> Vec { + self.for_entities + .borrow() + .values() + .map(|petition| petition.status()) + .collect() + } + pub fn invalid_transactions_if_neglected_factors( &self, factor_source_ids: IndexSet, @@ -227,6 +235,6 @@ mod tests { #[test] fn debug() { - assert_eq!(format!("{:?}", Sut::sample()), "PetitionForTransaction(for_entities: [PetitionForEntity(intent_hash: TXID(\"dedede\"), entity: acco_Grace, \"threshold_factors PetitionForFactors(input: PetitionFactorsInput(factors: {\\n factor_source_id: Device:de, derivation_path: 0/A/tx/0,\\n factor_source_id: Ledger:1e, derivation_path: 0/A/tx/1,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\"\"override_factors PetitionForFactors(input: PetitionFactorsInput(factors: {\\n factor_source_id: Ledger:1e, derivation_path: 0/A/tx/1,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\")])"); + assert_eq!(format!("{:?}", Sut::sample()), "PetitionForTransaction(for_entities: [PetitionForEntity(intent_hash: TXID(\"dedede\"), entity: acco_Grace, \"threshold_factors PetitionForFactors(input: PetitionForFactorsInput(factors: {\\n factor_source_id: Device:de, derivation_path: 0/A/tx/0,\\n factor_source_id: Ledger:1e, derivation_path: 0/A/tx/1,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\"\"override_factors PetitionForFactors(input: PetitionForFactorsInput(factors: {\\n factor_source_id: Ledger:1e, derivation_path: 0/A/tx/1,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\")])"); } } diff --git a/src/signing/petition_types/petitions.rs b/src/signing/petition_types/petitions.rs index 1feeb178..1ab7ab19 100644 --- a/src/signing/petition_types/petitions.rs +++ b/src/signing/petition_types/petitions.rs @@ -23,25 +23,6 @@ pub(crate) struct Petitions { pub txid_to_petition: RefCell>, } -#[derive(Clone, Copy, PartialEq, Eq, Debug)] -pub enum PetitionsStatus { - InProgressNoneInvalid, - AllAreValid, - SomeIsInvalid, -} -impl PetitionsStatus { - // pub fn are_all_done(&self) -> bool { - // matches!(self, Self::Done { .. }) - // } - pub fn are_all_valid(&self) -> bool { - matches!(self, Self::AllAreValid) - } - - pub fn is_some_invalid(&self) -> bool { - matches!(self, Self::SomeIsInvalid) - } -} - impl Petitions { pub(crate) fn new( factor_source_to_intent_hash: HashMap>, @@ -77,43 +58,6 @@ impl Petitions { ) } - pub fn status(&self) -> PetitionsStatus { - let statuses = self - .txid_to_petition - .borrow() - .iter() - .flat_map(|(_, petition)| { - petition - .for_entities - .borrow() - .iter() - .map(|(_, petition)| petition.status()) - .collect_vec() - }) - .collect::>(); - - let are_all_valid = statuses.iter().all(|s| { - matches!( - s, - PetitionFactorsStatus::Finished(PetitionFactorsStatusFinished::Success) - ) - }); - if are_all_valid { - return PetitionsStatus::AllAreValid; - } - - let is_some_invalid = statuses.iter().any(|s| { - matches!( - s, - PetitionFactorsStatus::Finished(PetitionFactorsStatusFinished::Fail) - ) - }); - if is_some_invalid { - return PetitionsStatus::SomeIsInvalid; - } - PetitionsStatus::InProgressNoneInvalid - } - pub fn each_petition( &self, factor_source_ids: IndexSet, @@ -178,7 +122,7 @@ impl Petitions { &self, factor_source_id: &FactorSourceIDFromHash, ) -> MonoFactorSignRequestInput { - let invalids = self.each_petition( + self.each_petition( IndexSet::from_iter([*factor_source_id]), |p| { if p.has_tx_failed() { @@ -187,28 +131,35 @@ impl Petitions { Some(p.input_for_interactor(factor_source_id)) } }, - |i| i.into_iter().flatten().collect::>(), - ); + |i| { + MonoFactorSignRequestInput::new( + *factor_source_id, + i.into_iter().flatten().collect::>(), + ) + }, + ) + } - MonoFactorSignRequestInput::new(*factor_source_id, invalids) + pub fn status(&self) -> PetitionsStatus { + self.each_petition( + self.factor_source_to_intent_hash.keys().cloned().collect(), + |p| p.status_of_each_petition_for_entity(), + |i| PetitionsStatus::reducing(i.into_iter().flatten()), + ) } fn add_signature(&self, signature: &HDSignature) { let binding = self.txid_to_petition.borrow(); - let petition = binding.get(signature.intent_hash()).unwrap(); + let petition = binding.get(signature.intent_hash()).expect("Should have a petition for each transaction, did you recently change the preprocessor logic of the SignaturesCollector, if you did you've missed adding an entry for `txid_to_petition`.map"); petition.add_signature(signature.clone()) } fn neglect_factor_source_with_id(&self, neglected: NeglectedFactor) { - let binding = self.txid_to_petition.borrow(); - let intent_hashes = self - .factor_source_to_intent_hash - .get(&neglected.factor_source_id()) - .unwrap(); - intent_hashes.into_iter().for_each(|intent_hash| { - let petition = binding.get(intent_hash).unwrap(); - petition.neglect_factor_source(neglected.clone()) - }); + self.each_petition( + IndexSet::from_iter([neglected.factor_source_id()]), + |p| p.neglect_factor_source(neglected.clone()), + |_| (), + ) } pub(crate) fn process_batch_response(&self, response: SignWithFactorsOutcome) { @@ -291,6 +242,6 @@ mod tests { #[test] fn debug() { - pretty_assertions::assert_eq!(format!("{:?}", Sut::sample()), "Petitions(TXID(\"dedede\"): PetitionForTransaction(for_entities: [PetitionForEntity(intent_hash: TXID(\"dedede\"), entity: acco_Grace, \"threshold_factors PetitionForFactors(input: PetitionFactorsInput(factors: {\\n factor_source_id: Device:de, derivation_path: 0/A/tx/0,\\n factor_source_id: Ledger:1e, derivation_path: 0/A/tx/1,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\"\"override_factors PetitionForFactors(input: PetitionFactorsInput(factors: {\\n factor_source_id: Ledger:1e, derivation_path: 0/A/tx/1,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\")]))"); + pretty_assertions::assert_eq!(format!("{:?}", Sut::sample()), "Petitions(TXID(\"dedede\"): PetitionForTransaction(for_entities: [PetitionForEntity(intent_hash: TXID(\"dedede\"), entity: acco_Grace, \"threshold_factors PetitionForFactors(input: PetitionForFactorsInput(factors: {\\n factor_source_id: Device:de, derivation_path: 0/A/tx/0,\\n factor_source_id: Ledger:1e, derivation_path: 0/A/tx/1,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\"\"override_factors PetitionForFactors(input: PetitionForFactorsInput(factors: {\\n factor_source_id: Ledger:1e, derivation_path: 0/A/tx/1,\\n}), state_snapshot: signatures: \\\"\\\", neglected: \\\"\\\")\")]))"); } } diff --git a/src/signing/petition_types/petitions_status.rs b/src/signing/petition_types/petitions_status.rs new file mode 100644 index 00000000..f9959882 --- /dev/null +++ b/src/signing/petition_types/petitions_status.rs @@ -0,0 +1,37 @@ +use crate::prelude::*; + +/// An aggregation of the status of all petitions for transaction, +/// if all transactions are valid, if some are invalid, if none are invalid +/// (but all are not yet valid). +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum PetitionsStatus { + /// All transactions are valid. + AllAreValid, + + /// Some transaction is invalid (one or more), and some might be valid. + SomeIsInvalid, + + /// Not all transactions are valid, but none are invalid. + InProgressNoneInvalid, +} + +impl PetitionsStatus { + /// returns true if all petitions are valid. + pub fn are_all_valid(&self) -> bool { + matches!(self, Self::AllAreValid) + } + + /// returns true if some petitions are invalid. + pub fn is_some_invalid(&self) -> bool { + matches!(self, Self::SomeIsInvalid) + } + + pub(crate) fn reducing(statuses: impl IntoIterator) -> Self { + PetitionForFactorsStatus::aggregate( + statuses.into_iter().collect_vec(), + Self::AllAreValid, + Self::SomeIsInvalid, + Self::InProgressNoneInvalid, + ) + } +}