Skip to main content

drive/verify/contract/
mod.rs

1use crate::error::Error;
2
3mod verify_contract;
4mod verify_contract_history;
5mod verify_contract_return_serialization;
6
7fn retry_contract_verification_with_history<R, RetryFn, HasPresentContractFn>(
8    result: Result<R, Error>,
9    contract_known_keeps_history: Option<bool>,
10    contract_id: [u8; 32],
11    in_multiple_contract_proof_form: bool,
12    retry: RetryFn,
13    has_present_contract: HasPresentContractFn,
14) -> Result<R, Error>
15where
16    RetryFn: FnOnce() -> Result<R, Error>,
17    HasPresentContractFn: Fn(&R) -> bool,
18{
19    if contract_known_keeps_history.is_some() {
20        return result;
21    }
22
23    match &result {
24        Ok(value) if has_present_contract(value) => result,
25        Ok(_) => {
26            tracing::debug!(
27                ?contract_id,
28                keeps_history = false,
29                retry_keeps_history = true,
30                in_multiple_contract_proof_form,
31                "retrying contract verification with history enabled after absence"
32            );
33
34            let retry_result = retry();
35            if matches!(retry_result.as_ref(), Ok(value) if has_present_contract(value)) {
36                retry_result
37            } else {
38                result
39            }
40        }
41        Err(error) => {
42            tracing::debug!(
43                ?contract_id,
44                keeps_history = false,
45                retry_keeps_history = true,
46                in_multiple_contract_proof_form,
47                error = ?error,
48                "retrying contract verification with history enabled after error"
49            );
50
51            let retry_result = retry();
52            if matches!(retry_result.as_ref(), Ok(value) if has_present_contract(value)) {
53                retry_result
54            } else {
55                result
56            }
57        }
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use super::retry_contract_verification_with_history;
64    use crate::error::proof::ProofError;
65    use crate::error::Error;
66
67    #[test]
68    fn should_preserve_original_error_when_retry_returns_absence() {
69        let result = retry_contract_verification_with_history(
70            Err(Error::Proof(ProofError::IncompleteProof("first error"))),
71            None,
72            [1; 32],
73            false,
74            || Ok(None::<u8>),
75            Option::is_some,
76        );
77
78        assert!(matches!(
79            result,
80            Err(Error::Proof(ProofError::IncompleteProof("first error")))
81        ));
82    }
83
84    #[test]
85    fn should_return_retry_result_when_retry_finds_contract_after_error() {
86        let result = retry_contract_verification_with_history(
87            Err(Error::Proof(ProofError::IncompleteProof("first error"))),
88            None,
89            [1; 32],
90            false,
91            || Ok(Some(7u8)),
92            Option::is_some,
93        );
94
95        assert!(matches!(result, Ok(Some(7))));
96    }
97}