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 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() ])