module arch.node.engines.signs_for_behaviour; import prelude open; import arch.node.types.messages open; import arch.node.types.engine open; import arch.node.types.identities open; import arch.node.engines.signs_for_environment open; import arch.node.engines.signs_for_messages open; import arch.node.engines.signs_for_config open; import arch.node.types.anoma as Anoma open; type ReplyTo := mkReplyTo@{ whoAsked : Option EngineID; mailbox : Option MailboxID; }; type SignsForActionArgument := | SignsForActionArgumentReplyTo ReplyTo; SignsForActionArguments : Type := List SignsForActionArgument; SignsForAction : Type := Action SignsForCfg SignsForLocalState SignsForMailboxState SignsForTimerHandle SignsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; SignsForActionInput : Type := ActionInput SignsForCfg SignsForLocalState SignsForMailboxState SignsForTimerHandle SignsForActionArguments Anoma.Msg; SignsForActionEffect : Type := ActionEffect SignsForLocalState SignsForMailboxState SignsForTimerHandle Anoma.Msg Anoma.Cfg Anoma.Env; SignsForActionExec : Type := ActionExec SignsForCfg SignsForLocalState SignsForMailboxState SignsForTimerHandle SignsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; signsForQueryAction (input : SignsForActionInput) : Option SignsForActionEffect := let env := ActionInput.env input; cfg := ActionInput.cfg input; tt := ActionInput.trigger input; localState := EngineEnv.localState env; in case getEngineMsgFromTimestampedTrigger tt of | some mkEngineMsg@{ msg := Anoma.MsgSignsFor (MsgSignsForRequest (mkRequestSignsFor externalIdentityA externalIdentityB)); sender := msgSender; } := let hasEvidence := isElement \{a b := a && b} true (map \{evidence := isEqual (Ord.cmp (SignsForEvidence.fromIdentity evidence) externalIdentityA) && isEqual (Ord.cmp (SignsForEvidence.toIdentity evidence) externalIdentityB)} (Set.toList (SignsForLocalState.evidenceStore localState))); responseMsg := mkReplySignsFor@{ signsFor := hasEvidence; err := none; }; in some mkActionEffect@{ env := env; msgs := [ mkEngineMsg@{ sender := getEngineIDFromEngineCfg cfg; target := msgSender; mailbox := some 0; msg := Anoma.MsgSignsFor (MsgSignsForReply responseMsg); }; ]; timers := []; engines := []; } | _ := none; submitEvidenceAction (input : SignsForActionInput) : Option SignsForActionEffect := let env := ActionInput.env input; cfg := ActionInput.cfg input; tt := ActionInput.trigger input; localState := EngineEnv.localState env; in case getEngineMsgFromTimestampedTrigger tt of | some mkEngineMsg@{ msg := Anoma.MsgSignsFor (MsgSubmitSignsForEvidenceRequest (mkRequestSubmitSignsForEvidence evidence)); sender := msgSender; } := case verifyEvidence evidence of { | true := let alreadyExists := isElement \{a b := a && b} true (map \{e := isEqual (Ord.cmp e evidence)} (Set.toList (SignsForLocalState.evidenceStore localState))); in case alreadyExists of { | true := let responseMsg := mkReplySubmitSignsForEvidence@{ err := some "Evidence already exists."; }; in some mkActionEffect@{ env := env; msgs := [ mkEngineMsg@{ sender := getEngineIDFromEngineCfg cfg; target := msgSender; mailbox := some 0; msg := Anoma.MsgSignsFor (MsgSubmitSignsForEvidenceReply responseMsg); }; ]; timers := []; engines := []; } | false := let newEvidenceStore := Set.insert evidence (SignsForLocalState.evidenceStore localState); updatedLocalState := localState@SignsForLocalState{evidenceStore := newEvidenceStore}; newEnv := env@EngineEnv{localState := updatedLocalState}; responseMsg := mkReplySubmitSignsForEvidence@{ err := none; }; in some mkActionEffect@{ env := newEnv; msgs := [ mkEngineMsg@{ sender := getEngineIDFromEngineCfg cfg; target := msgSender; mailbox := some 0; msg := Anoma.MsgSignsFor (MsgSubmitSignsForEvidenceReply responseMsg); }; ]; timers := []; engines := []; } } | false := let responseMsg := mkReplySubmitSignsForEvidence@{ err := some "Invalid evidence provided."; }; in some mkActionEffect@{ env := env; msgs := [ mkEngineMsg@{ sender := getEngineIDFromEngineCfg cfg; target := msgSender; mailbox := some 0; msg := Anoma.MsgSignsFor (MsgSubmitSignsForEvidenceReply responseMsg); }; ]; timers := []; engines := []; } } | _ := none; queryEvidenceAction (input : SignsForActionInput) : Option SignsForActionEffect := let env := ActionInput.env input; cfg := ActionInput.cfg input; tt := ActionInput.trigger input; localState := EngineEnv.localState env; in case getEngineMsgFromTimestampedTrigger tt of | some mkEngineMsg@{ msg := Anoma.MsgSignsFor (MsgQuerySignsForEvidenceRequest (mkRequestQuerySignsForEvidence externalIdentity)); sender := msgSender; } := let relevantEvidence := AVLTree.filter \{evidence := isEqual (Ord.cmp (SignsForEvidence.fromIdentity evidence) externalIdentity) || isEqual (Ord.cmp (SignsForEvidence.toIdentity evidence) externalIdentity)} (SignsForLocalState.evidenceStore localState); responseMsg := mkReplyQuerySignsForEvidence@{ externalIdentity := externalIdentity; evidence := relevantEvidence; err := none; }; in some mkActionEffect@{ env := env; msgs := [ mkEngineMsg@{ sender := getEngineIDFromEngineCfg cfg; target := msgSender; mailbox := some 0; msg := Anoma.MsgSignsFor (MsgQuerySignsForEvidenceReply responseMsg); }; ]; timers := []; engines := []; } | _ := none; signsForQueryActionLabel : SignsForActionExec := Seq [signsForQueryAction]; submitEvidenceActionLabel : SignsForActionExec := Seq [submitEvidenceAction]; queryEvidenceActionLabel : SignsForActionExec := Seq [queryEvidenceAction]; SignsForGuard : Type := Guard SignsForCfg SignsForLocalState SignsForMailboxState SignsForTimerHandle SignsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; SignsForGuardOutput : Type := GuardOutput SignsForCfg SignsForLocalState SignsForMailboxState SignsForTimerHandle SignsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; SignsForGuardEval : Type := GuardEval SignsForCfg SignsForLocalState SignsForMailboxState SignsForTimerHandle SignsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; signsForQueryGuard (tt : TimestampedTrigger SignsForTimerHandle Anoma.Msg) (cfg : EngineCfg SignsForCfg) (env : SignsForEnv) : Option SignsForGuardOutput := case getEngineMsgFromTimestampedTrigger tt of | some mkEngineMsg@{msg := Anoma.MsgSignsFor (MsgSignsForRequest _)} := some mkGuardOutput@{ action := signsForQueryActionLabel; args := []; } | _ := none; submitEvidenceGuard (tt : TimestampedTrigger SignsForTimerHandle Anoma.Msg) (cfg : EngineCfg SignsForCfg) (env : SignsForEnv) : Option SignsForGuardOutput := case getEngineMsgFromTimestampedTrigger tt of | some mkEngineMsg@{ msg := Anoma.MsgSignsFor (MsgSubmitSignsForEvidenceRequest _); } := some mkGuardOutput@{ action := submitEvidenceActionLabel; args := []; } | _ := none; queryEvidenceGuard (tt : TimestampedTrigger SignsForTimerHandle Anoma.Msg) (cfg : EngineCfg SignsForCfg) (env : SignsForEnv) : Option SignsForGuardOutput := case getEngineMsgFromTimestampedTrigger tt of | some mkEngineMsg@{ msg := Anoma.MsgSignsFor (MsgQuerySignsForEvidenceRequest _); } := some mkGuardOutput@{ action := queryEvidenceActionLabel; args := []; } | _ := none; SignsForBehaviour : Type := EngineBehaviour SignsForCfg SignsForLocalState SignsForMailboxState SignsForTimerHandle SignsForActionArguments Anoma.Msg Anoma.Cfg Anoma.Env; signsForBehaviour : SignsForBehaviour := mkEngineBehaviour@{ guards := First [signsForQueryGuard; submitEvidenceGuard; queryEvidenceGuard]; };