module arch.node.engines.reads_for_behaviour; import prelude open; import Stdlib.Data.Set as Set; import arch.node.types.messages open; import arch.node.types.engine open; import arch.node.types.identities open; import arch.node.engines.reads_for_messages open; import arch.node.engines.reads_for_config open; import arch.node.engines.reads_for_environment open; import arch.node.types.anoma as Anoma open; type ReplyTo := mkReplyTo@{ whoAsked : Option EngineID; mailbox : Option MailboxID; }; type ReadsForActionArgument := | ReadsForActionArgumentReplyTo ReplyTo; ReadsForActionArguments : Type := List ReadsForActionArgument; ReadsForAction : Type := Action ReadsForCfg ReadsForLocalState ReadsForMailboxState ReadsForTimerHandle ReadsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; ReadsForActionInput : Type := ActionInput ReadsForCfg ReadsForLocalState ReadsForMailboxState ReadsForTimerHandle ReadsForActionArguments Anoma.Msg; ReadsForActionEffect : Type := ActionEffect ReadsForLocalState ReadsForMailboxState ReadsForTimerHandle Anoma.Msg Anoma.Cfg Anoma.Env; ReadsForActionExec : Type := ActionExec ReadsForCfg ReadsForLocalState ReadsForMailboxState ReadsForTimerHandle ReadsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; readsForQueryAction (input : ReadsForActionInput) : Option ReadsForActionEffect := let env := ActionInput.env input; tt := ActionInput.trigger input; cfg := ActionInput.cfg input; localState := EngineEnv.localState env; in case getEngineMsgFromTimestampedTrigger tt of | some emsg := case emsg of { | EngineMsg.mk@{ msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.Request (RequestReadsFor.mkRequestReadsFor identityA identityB)); } := let hasEvidence := isElement \{a b := a && b} true (map \{evidence := isEqual (Ord.compare (ReadsForEvidence.fromIdentity evidence) identityA) && isEqual (Ord.compare (ReadsForEvidence.toIdentity evidence) identityB)} (Set.toList (ReadsForLocalState.evidenceStore localState))); responseMsg := ReplyReadsFor.mkReplyReadsFor@{ readsFor := hasEvidence; err := none; }; in some ActionEffect.mk@{ env := env; msgs := [ EngineMsg.mk@{ sender := getEngineIDFromEngineCfg cfg; target := EngineMsg.sender emsg; mailbox := some 0; msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.Reply responseMsg); }; ]; timers := []; engines := []; } | _ := none } | _ := none; submitEvidenceAction (input : ReadsForActionInput) : Option ReadsForActionEffect := let env := ActionInput.env input; tt := ActionInput.trigger input; cfg := ActionInput.cfg input; localState := EngineEnv.localState env; in case getEngineMsgFromTimestampedTrigger tt of | some emsg := case emsg of { | EngineMsg.mk@{ msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.SubmitReadsForEvidenceRequest (RequestSubmitReadsForEvidence.mkRequestSubmitReadsForEvidence evidence)); } := case verifyEvidence evidence of { | true := case isElement \{a b := a && b} true (map \{e := isEqual (Ord.compare e evidence)} (Set.toList (ReadsForLocalState.evidenceStore localState))) of { | true := some ActionEffect.mk@{ env := env; msgs := [ EngineMsg.mk@{ sender := getEngineIDFromEngineCfg cfg; target := EngineMsg.sender emsg; mailbox := some 0; msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.SubmitReadsForEvidenceReply (ReplySubmitReadsForEvidence.mkReplySubmitReadsForEvidence (some "Evidence already exists."))); }; ]; timers := []; engines := []; } | false := let newEvidenceStore := Set.insert evidence (ReadsForLocalState.evidenceStore localState); updatedLocalState := localState@ReadsForLocalState{evidenceStore := newEvidenceStore}; newEnv := env@EngineEnv{localState := updatedLocalState}; in some ActionEffect.mk@{ env := newEnv; msgs := [ EngineMsg.mk@{ sender := getEngineIDFromEngineCfg cfg; target := EngineMsg.sender emsg; mailbox := some 0; msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.SubmitReadsForEvidenceReply (ReplySubmitReadsForEvidence.mkReplySubmitReadsForEvidence none)); }; ]; timers := []; engines := []; } } | false := some ActionEffect.mk@{ env := env; msgs := [ EngineMsg.mk@{ sender := getEngineIDFromEngineCfg cfg; target := EngineMsg.sender emsg; mailbox := some 0; msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.SubmitReadsForEvidenceReply (ReplySubmitReadsForEvidence.mkReplySubmitReadsForEvidence (some "Invalid evidence provided."))); }; ]; timers := []; engines := []; } } | _ := none } | _ := none; queryEvidenceAction (input : ReadsForActionInput) : Option ReadsForActionEffect := let env := ActionInput.env input; tt := ActionInput.trigger input; cfg := ActionInput.cfg input; localState := EngineEnv.localState env; in case getEngineMsgFromTimestampedTrigger tt of | some emsg := case emsg of { | EngineMsg.mk@{ msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.QueryReadsForEvidenceRequest (RequestQueryReadsForEvidence.mkRequestQueryReadsForEvidence identity)); } := let relevantEvidence := Set.filter \{evidence := isEqual (Ord.compare (ReadsForEvidence.fromIdentity evidence) identity) || isEqual (Ord.compare (ReadsForEvidence.toIdentity evidence) identity)} (ReadsForLocalState.evidenceStore localState); responseMsg := ReplyQueryReadsForEvidence.mkReplyQueryReadsForEvidence@{ externalIdentity := identity; evidence := relevantEvidence; err := none; }; in some ActionEffect.mk@{ env := env; msgs := [ EngineMsg.mk@{ sender := getEngineIDFromEngineCfg cfg; target := EngineMsg.sender emsg; mailbox := some 0; msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.QueryReadsForEvidenceReply responseMsg); }; ]; timers := []; engines := []; } | _ := none } | _ := none; readsForQueryActionLabel : ReadsForActionExec := ActionExec.Seq [readsForQueryAction]; submitEvidenceActionLabel : ReadsForActionExec := ActionExec.Seq [submitEvidenceAction]; queryEvidenceActionLabel : ReadsForActionExec := ActionExec.Seq [queryEvidenceAction]; ReadsForGuard : Type := Guard ReadsForCfg ReadsForLocalState ReadsForMailboxState ReadsForTimerHandle ReadsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; ReadsForGuardOutput : Type := GuardOutput ReadsForCfg ReadsForLocalState ReadsForMailboxState ReadsForTimerHandle ReadsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; ReadsForGuardEval : Type := GuardEval ReadsForCfg ReadsForLocalState ReadsForMailboxState ReadsForTimerHandle ReadsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; readsForQueryGuard (tt : TimestampedTrigger ReadsForTimerHandle Anoma.Msg) (cfg : EngineCfg ReadsForCfg) (env : ReadsForEnv) : Option ReadsForGuardOutput := case getEngineMsgFromTimestampedTrigger tt of | some EngineMsg.mk@{ msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.Request _); } := some GuardOutput.mk@{ action := readsForQueryActionLabel; args := []; } | _ := none; submitEvidenceGuard (tt : TimestampedTrigger ReadsForTimerHandle Anoma.Msg) (cfg : EngineCfg ReadsForCfg) (env : ReadsForEnv) : Option ReadsForGuardOutput := case getEngineMsgFromTimestampedTrigger tt of | some EngineMsg.mk@{ msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.SubmitReadsForEvidenceRequest _); } := some GuardOutput.mk@{ action := submitEvidenceActionLabel; args := []; } | _ := none; queryEvidenceGuard (tt : TimestampedTrigger ReadsForTimerHandle Anoma.Msg) (cfg : EngineCfg ReadsForCfg) (env : ReadsForEnv) : Option ReadsForGuardOutput := case getEngineMsgFromTimestampedTrigger tt of | some EngineMsg.mk@{ msg := Anoma.PreMsg.MsgReadsFor (ReadsForMsg.QueryReadsForEvidenceRequest _); } := some GuardOutput.mk@{ action := queryEvidenceActionLabel; args := []; } | _ := none; ReadsForBehaviour : Type := EngineBehaviour ReadsForCfg ReadsForLocalState ReadsForMailboxState ReadsForTimerHandle ReadsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; readsForBehaviour : ReadsForBehaviour := EngineBehaviour.mk@{ guards := GuardEval.First [readsForQueryGuard; submitEvidenceGuard; queryEvidenceGuard]; };