diff options
| author | adelon <22380201+adelon@users.noreply.github.com> | 2026-08-01 02:38:51 +0200 |
|---|---|---|
| committer | adelon <22380201+adelon@users.noreply.github.com> | 2026-08-01 02:38:51 +0200 |
| commit | 183a82939f2e85eac6601f6ce8019fceef57cca0 (patch) | |
| tree | ac22044f1978c0d8ff9dc3bb5000ae0cb4308749 /source | |
| parent | 34ac40029e5fc6e3a0328de1b7f6bcbb5e624ac9 (diff) | |
Add warm proof validation lookup
Diffstat (limited to 'source')
| -rw-r--r-- | source/Checking/Declaration.hs | 115 | ||||
| -rw-r--r-- | source/Test/Unit/Declaration.hs | 71 |
2 files changed, 180 insertions, 6 deletions
diff --git a/source/Checking/Declaration.hs b/source/Checking/Declaration.hs index 8e31b8d..ee1b38d 100644 --- a/source/Checking/Declaration.hs +++ b/source/Checking/Declaration.hs @@ -10,6 +10,10 @@ module Checking.Declaration , DriverFailure(..) , DriverResult(..) , runModuleDriver + , ProofValidationLookup + , proofValidationLookup + , ProofValidationRunMode(..) + , runModuleDriverWithValidation , failModuleDriver , VampireResolver , vampireResolver @@ -34,6 +38,7 @@ module Checking.Declaration , authorizeKernelConstructionCandidate , acceptVampireObligation , acceptCachedVampireObligation + , lookupProofValidation , authorizeVampireCandidate , authorizeCachedVampireCandidate , authorizeSourceAxiomCandidate @@ -100,6 +105,24 @@ newtype DeclarationInvocation = DeclarationInvocation Natural newtype CandidateStage = CandidateStage Natural deriving stock (Show, Eq, Ord) +newtype ProofValidationLookup = ProofValidationLookup + { runProofValidationLookup + :: ProofValidationKey + -> IO (Either Text (Maybe ProofValidationRecord)) + } + +proofValidationLookup + :: (ProofValidationKey + -> IO (Either Text (Maybe ProofValidationRecord))) + -> ProofValidationLookup +proofValidationLookup = + ProofValidationLookup + +data ProofValidationRunMode + = FreshProofValidation + | WarmProofValidation + deriving stock (Show, Eq) + data BuilderFactAuthorization = BuilderFactAuthorization !BuilderIdentity @@ -321,6 +344,8 @@ data DriverState = DriverState !VampireResolver !LogicalBuilder !PendingModulePrefix + !(Maybe ProofValidationLookup) + !ProofValidationRunMode newtype ModuleDriver failure value = ModuleDriver { runDriverStep @@ -371,6 +396,29 @@ runModuleDriver DriverOpenError (DriverResult failure value)) runModuleDriver foundation owner direct resolver action = do + runModuleDriverWithValidation + foundation + owner + direct + resolver + Nothing + FreshProofValidation + action + +runModuleDriverWithValidation + :: CheckedFoundation + -> ModuleName + -> [SemanticInterfaceId] + -> VampireResolver + -> Maybe ProofValidationLookup + -> ProofValidationRunMode + -> ModuleDriver failure value + -> IO + (Either + DriverOpenError + (DriverResult failure value)) +runModuleDriverWithValidation + foundation owner direct resolver validationLookup validationMode action = do unique <- BuilderIdentity <$> newUnique let theory = theoryId foundation case (,) <$> @@ -402,7 +450,9 @@ runModuleDriver foundation owner direct resolver action = do resolver builder (PendingModulePrefix prefix []) - (result, DriverState _ finalBuilder finalPrefix) <- + validationLookup + validationMode + (result, DriverState _ finalBuilder finalPrefix _ _) <- State.runStateT (Except.runExceptT (runDriverStep action)) @@ -494,6 +544,8 @@ data PendingCandidate = PendingCandidate data DeclarationState = DeclarationState { declarationVampireResolver :: !VampireResolver + , declarationProofValidationLookup :: !(Maybe ProofValidationLookup) + , declarationProofValidationMode :: !ProofValidationRunMode , declarationBuilder :: !LogicalBuilder , declarationOwnSlot :: !DeclarationSlot , declarationInvocation :: !DeclarationInvocation @@ -598,7 +650,40 @@ reserveCandidateBatch specs = Declaration do (declarationNextFact state + offset))) spec - +lookupProofValidation + :: ProofSyntaxId + -> ReservedCandidate + -> Declaration (Maybe ProofValidationRecord) +lookupProofValidation syntax candidate = Declaration do + state <- State.get + case declarationProofValidationMode state of + FreshProofValidation -> + pure Nothing + WarmProofValidation -> + case declarationProofValidationLookup state of + Nothing -> + pure Nothing + Just (ProofValidationLookup lookupRecord) -> do + let builder = declarationBuilder state + reference = candidateTheoremReference builder candidate + key = + proofValidationKey + (theoremId + (factAuthorityTheorem + (factAuthority + reference + cleanAuthoritySafety))) + syntax + (logicalBuilderPrefix builder) + result <- State.lift + (liftIO (lookupRecord key)) + case result of + Left reason -> + State.lift + (Except.throwError + (ProofValidationLookupFailed reason)) + Right record -> + pure record data CandidatePremise = CandidatePremise !CheckedPropositionContent @@ -1500,9 +1585,15 @@ commitDeclaration -> ModuleDriver failure (value, CommittedDeclarationBatch) commitDeclaration mode action = ModuleDriver do - DriverState resolver builder pendingPrefix <- State.get + DriverState resolver builder pendingPrefix validationLookup validationMode <- + State.get let - declaration = initialDeclarationState resolver builder + declaration = + initialDeclarationState + resolver + validationLookup + validationMode + builder result <- liftIO (Except.runExceptT @@ -1520,16 +1611,25 @@ commitDeclaration mode action = ModuleDriver do let prefix' = appendPendingBatch batch pendingPrefix in do State.put - (DriverState resolver builder' prefix') + (DriverState + resolver + builder' + prefix' + validationLookup + validationMode) pure (value, batch) initialDeclarationState :: VampireResolver + -> Maybe ProofValidationLookup + -> ProofValidationRunMode -> LogicalBuilder -> DeclarationState -initialDeclarationState resolver builder = +initialDeclarationState resolver validationLookup validationMode builder = DeclarationState { declarationVampireResolver = resolver + , declarationProofValidationLookup = validationLookup + , declarationProofValidationMode = validationMode , declarationBuilder = builder , declarationOwnSlot = declarationSlot @@ -1901,6 +2001,7 @@ data DeclarationError | VampireFoundationMismatch !FoundationAxiomTag | CachedValidationMismatch !Materialization.MaterializationError + | ProofValidationLookupFailed !Text | DeclarationObjectAddedAfterAuthorization | DeclarationObjectValidationFailed !ObjectValidationError | DeclarationPropositionValidationFailed @@ -1972,6 +2073,8 @@ renderDeclarationError = \case "Vampire request has inconsistent foundation axiom " <> shown tag CachedValidationMismatch{} -> "cached validation does not match the current declaration" + ProofValidationLookupFailed reason -> + "could not load cached proof validation: " <> reason DeclarationObjectAddedAfterAuthorization -> "the declaration added an object after candidate authorization" DeclarationObjectValidationFailed{} -> diff --git a/source/Test/Unit/Declaration.hs b/source/Test/Unit/Declaration.hs index 28f277d..16f4461 100644 --- a/source/Test/Unit/Declaration.hs +++ b/source/Test/Unit/Declaration.hs @@ -373,6 +373,46 @@ aggregatesExactVampireObligations = ("unexpected cached validation records: " <> show (length records))) + warmCalls <- IORef.newIORef (0 :: Int) + warm <- runSuccessfulWithValidation fixture + (Declaration.proofValidationLookup \_ -> do + IORef.modifyIORef' warmCalls (+ 1) + pure (Right (Just cachedRecord))) + do + (_value, committed) <- Declaration.commitProofDeclaration + (Semantic.proofSyntaxId "two-vampire-obligations") do + candidate <- Declaration.reserveCandidate + (factSpec fixture "two-vampire-obligations") + cached <- Declaration.lookupProofValidation + (Semantic.proofSyntaxId "two-vampire-obligations") + candidate + case cached of + Just record -> + Declaration.authorizeCachedVampireCandidate + (Semantic.proofSyntaxId "two-vampire-obligations") + record + candidate do + Declaration.acceptCachedVampireObligation first + Declaration.acceptCachedVampireObligation second + Nothing -> + Declaration.failDeclaration + (Declaration.ProofValidationLookupFailed + "test cache miss") + pure committed + assertEqual "warm lookup executes once" + 1 + =<< IORef.readIORef warmCalls + assertEqual "warm path retains cached request IDs" + (Authority.CheckedSourceProof expectedRequests) + (case Declaration.committedBatchProofValidations warm of + [record] -> + Authority.validationDirectAuthorization + (Semantic.proofValidationRecordCertificate record) + records -> + error + ("unexpected warm validation records: " + <> show (length records))) + emptyProof <- runDriver fixture do Declaration.commitProofDeclaration (Semantic.proofSyntaxId "empty-vampire-proof") do @@ -776,6 +816,22 @@ runDriverWithResolver fixture resolver action = do action expectRight result +runDriverWithValidation + :: Fixture + -> Declaration.ProofValidationLookup + -> Declaration.ModuleDriver failure value + -> IO (Declaration.DriverResult failure value) +runDriverWithValidation fixture lookup action = do + result <- Declaration.runModuleDriverWithValidation + (fixtureFoundation fixture) + (fixtureOwner fixture) + [] + unavailableVampireResolver + (Just lookup) + Declaration.WarmProofValidation + action + expectRight result + unavailableVampireResolver :: Declaration.VampireResolver unavailableVampireResolver = Declaration.vampireResolver \_prepared -> @@ -807,6 +863,21 @@ runSuccessfulWithResolver fixture resolver action = do Declaration.DriverSealFailed failure _prefix -> assertFailure (show failure) >> fail "unreachable" +runSuccessfulWithValidation + :: Fixture + -> Declaration.ProofValidationLookup + -> Declaration.ModuleDriver failure value + -> IO value +runSuccessfulWithValidation fixture lookup action = do + outcome <- runDriverWithValidation fixture lookup action + case outcome of + Declaration.DriverSucceeded value _interface _prefix -> + pure value + Declaration.DriverFailed _failure _prefix -> + assertFailure "unexpected driver failure" >> fail "unreachable" + Declaration.DriverSealFailed failure _prefix -> + assertFailure (show failure) >> fail "unreachable" + requireSingleOccurrence :: Declaration.CommittedDeclarationBatch -> Declaration.ModuleDriver |
