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