def visitDoWhileStatement(self, ast: DoWhileStatement): if contains_private_expr(ast.condition): raise TypeException( 'Loop condition cannot contain private expressions', ast.condition) if contains_private_expr(ast.body): raise TypeException('Loop body cannot contain private expressions', ast.body) self.visitChildren(ast)
def visitForStatement(self, ast: ForStatement): if ast.init is not None: # Init is the only part of a for loop which may contain private expressions ast.init = self.visit(ast.init) ast.pre_statements += ast.init.pre_statements assert not contains_private_expr(ast.condition) assert not ast.update or not contains_private_expr(ast.update) assert not contains_private_expr(ast.body) # OR fixed size loop -> static analysis can prove that loop terminates in fixed # iterations return ast
def visitForStatement(self, ast: ForStatement): if contains_private_expr(ast.condition): raise TypeException( 'Loop condition cannot contain private expressions', ast.condition) if contains_private_expr(ast.body): raise TypeException('Loop body cannot contain private expressions', ast.body) if ast.update is not None and contains_private_expr(ast.update): raise TypeException( 'Loop update statement cannot contain private expressions', ast.update) self.visitChildren(ast)
def visitIfStatement(self, ast: IfStatement): """ Rule (6) + additional support for private conditions If the condition is public, guard conditions are introduced for both branches if any of the branches contains private expressions. If the condition is private, the whole if statement is inlined into the circuit. The only side-effects which are allowed inside the branch bodies are assignment statements with an lhs@me. (anything else would leak private information). The if statement will be replaced by an assignment statement where the lhs is a tuple of all locations which are written in either branch and rhs is a tuple of the corresponding circuit outputs. """ if ast.condition.annotated_type.is_public(): if contains_private_expr(ast.then_branch) or contains_private_expr(ast.else_branch): before_if_state = self.gen._remapper.get_state() guard_var = self.gen.add_to_circuit_inputs(ast.condition) ast.condition = guard_var.get_loc_expr(ast) with self.gen.guarded(guard_var, True): ast.then_branch = self.visit(ast.then_branch) self.gen._remapper.set_state(before_if_state) if ast.else_branch is not None: with self.gen.guarded(guard_var, False): ast.else_branch = self.visit(ast.else_branch) self.gen._remapper.set_state(before_if_state) # Invalidate values modified in either branch for val in ast.modified_values: if val.key is None: self.gen.invalidate_idf(val.target.idf) else: ast.condition = self.expr_trafo.visit(ast.condition) ast.then_branch = self.visit(ast.then_branch) if ast.else_branch is not None: ast.else_branch = self.visit(ast.else_branch) return ast else: return self.gen.evaluate_stmt_in_circuit(ast)
def visitDoWhileStatement(self, ast: DoWhileStatement): # Loops must always be purely public assert not contains_private_expr(ast.condition) assert not contains_private_expr(ast.body) return ast