def unsafe(self): clauses = [] for p in self.public_parameters: # only public out parameters can have safety conflicts sources = [ m for m in self.p_cover(p) if m.parameters[p].adornment == 'out' ] if len(sources) > 1: alts = [] for r in self.roles.values(): # assume an agent can choose between alternative messages msgs = [m.sent for m in sources if m.sender == r] if msgs: alts.append(or_(*msgs)) # at most one message producing this parameter can be sent more_than_one = or_(*pairwise(and_, alts)) # only consider cases where more than one at once is possible if more_than_one: clauses.append(logic.Name(more_than_one, p + "-unsafe")) if clauses: # at least one conflict return logic.And(self.correct, logic.Name(clauses, "unsafe")) else: # no conflicting pairs; automatically safe -> not unsafe return bx.ZERO
def minimality(self, protocol): """Every parameter observed by a role must have a corresponding message transmission or reception""" sources = {} def add(m, p): if p in sources: sources[p].append(m) else: sources[p] = [m] outgoing = set() for m in self.messages(protocol).values(): if m.recipient == self: for p in m.ins.union(m.outs): add(m, p) else: for p in m.outs: add(m, p) for p in m.ins: outgoing.add(p) # keep track of 'in' parameters being sent without sources # unsourced parameters cannot be observed unsourced = [logic.Name(~self.observe(p), p) for p in outgoing - set(sources.keys())] # sourced parameters must be received or sent to be observed sourced = [logic.Name(impl(self.observe(p), or_(*[simultaneous(self.observe(m), self.observe(p)) for m in sources[p]])), p) for p in sources] return logic.And(*(unsourced + sourced))
def reception(self): "Each message reception is accompanied by the observation of its parameters; either they are observed, or the message itself is not" clauses = [impl(self.received, or_(sequential(p, self.received), simultaneous(p, self.received))) for p in map(partial(observe, self.recipient), self.ins | self.outs)] return and_(*clauses)
def blocked(self): s = partial(observe, self.sender) ins = [~s(p) for p in self.ins] nils = [and_(s(p), ~(sequential(s(p), self.sent) | simultaneous(s(p), self.sent))) for p in self.nils] outs = [s(p) for p in self.outs] return or_(*(nils + outs + ins))
def _complete(self): "Each out parameter must be observed by at least one role" clauses = [] for p in self.outs: clauses.append(or_(*[m.received for m in self.p_cover(p) if m.parameters[p].adornment is 'out'])) return and_(*clauses)
def begin(self): return or_(*[m.sent for m in self.messages.values()])
def _enactable(self): "Some message must be received containing each parameter" clauses = [] for p in self.public_parameters: clauses.append(or_(*[m.received for m in self.p_cover(p)])) return and_(*clauses)
def cover(self): return logic.And(*[ logic.Name(or_(*[m.received for m in self.p_cover(p)]), p.name + "-cover") for p in self.public_parameters.values() ])