示例#1
0
    def try_rehom(rhs: Expression, expected_type: AnnotatedTypeName):
        if rhs.annotated_type.is_public():
            raise ValueError(
                'Cannot change the homomorphism of a public value')

        if rhs.annotated_type.is_private_at_me(rhs.analysis):
            # The value is @me, so we can just insert a ReclassifyExpr to change
            # the homomorphism of this value, just like we do for public values.
            return TypeCheckVisitor.make_rehom(rhs, expected_type)

        if isinstance(rhs, ReclassifyExpr) and not isinstance(rhs, RehomExpr):
            # rhs is a valid ReclassifyExpr, i.e. the argument is public or @me-private
            # To create an expression with the correct homomorphism,
            # just change the ReclassifyExpr's output homomorphism
            rhs.homomorphism = expected_type.homomorphism
        elif isinstance(rhs, PrimitiveCastExpr):
            # Ignore primitive cast & recurse
            rhs.expr = TypeCheckVisitor.try_rehom(rhs.expr, expected_type)
        elif isinstance(rhs, FunctionCallExpr) and isinstance(rhs.func, BuiltinFunction) and rhs.func.is_ite() \
                and rhs.args[0].annotated_type.is_public():
            # Argument is public_cond ? true_val : false_val. Try to rehom both true_val and false_val
            rhs.args[1] = TypeCheckVisitor.try_rehom(rhs.args[1],
                                                     expected_type)
            rhs.args[2] = TypeCheckVisitor.try_rehom(rhs.args[2],
                                                     expected_type)
        else:
            raise TypeMismatchException(expected_type, rhs.annotated_type, rhs)

        # Rehom worked without throwing, change annotated_type and return
        rhs.annotated_type = rhs.annotated_type.with_homomorphism(
            expected_type.homomorphism)
        return rhs
示例#2
0
文件: deep_copy.py 项目: nibau/zkay
def replace_expr(old_expr: Expression,
                 new_expr: Expression,
                 copy_type: bool = False):
    """
        Copies over ast common ast attributes and reruns, parent setter, symbol table, side effect detector
    """
    _replace_ast(old_expr, new_expr)
    if copy_type:
        new_expr.annotated_type = old_expr.annotated_type
    return new_expr
示例#3
0
    def _get_circuit_output_for_private_expression(
            self, expr: Expression, new_privacy: PrivacyLabelExpr,
            homomorphism: Homomorphism) -> LocationExpr:
        """
        Add evaluation of expr to the circuit and return the output HybridArgumentIdf corresponding to the evaluation result.

        Note: has side effects on expr.statement (adds pre_statement)

        :param expr: [SIDE EFFECT] expression to evaluate
        :param new_privacy: result owner (determines encryption key)
        :return: HybridArgumentIdf which references the circuit output containing the result of expr
        """
        is_circ_val = isinstance(expr, IdentifierExpr) and isinstance(
            expr.idf, HybridArgumentIdf
        ) and expr.idf.arg_type != HybridArgType.PUB_CONTRACT_VAL
        is_hom_comp = isinstance(expr, FunctionCallExpr) and isinstance(
            expr.func, BuiltinFunction
        ) and expr.func.homomorphism != Homomorphism.NON_HOMOMORPHIC
        if is_hom_comp:
            # Treat a homomorphic operation as a privately evaluated operation on (public) ciphertexts
            expr.annotated_type = AnnotatedTypeName.cipher_type(
                expr.annotated_type, homomorphism)

        if is_circ_val or expr.annotated_type.is_private(
        ) or expr.evaluate_privately:
            priv_result_idf = self._evaluate_private_expression(expr)
        else:
            # For public expressions which should not be evaluated in private, only the result is moved into the circuit
            priv_result_idf = self.add_to_circuit_inputs(expr)
        private_expr = priv_result_idf.get_idf_expr()

        t_suffix = ''
        if isinstance(expr, IdentifierExpr) and not is_circ_val:
            t_suffix += f'_{expr.idf.name}'

        if isinstance(new_privacy,
                      AllExpr) or expr.annotated_type.type_name.is_cipher():
            # If the result is public, add an equality constraint to ensure that the user supplied public output
            # is equal to the circuit evaluation result
            tname = f'{self._out_name_factory.get_new_name(expr.annotated_type.type_name)}{t_suffix}'
            new_out_param = self._out_name_factory.add_idf(
                tname, expr.annotated_type.type_name, private_expr)
            self._phi.append(CircEqConstraint(priv_result_idf, new_out_param))
            out_var = new_out_param.get_loc_expr().explicitly_converted(
                expr.annotated_type.type_name)
        else:
            # If the result is encrypted, add an encryption constraint to ensure that the user supplied encrypted output
            # is equal to the correctly encrypted circuit evaluation result
            new_privacy = self._get_canonical_privacy_label(
                expr.analysis, new_privacy)
            privacy_label_expr = get_privacy_expr_from_label(new_privacy)
            cipher_t = TypeName.cipher_type(expr.annotated_type, homomorphism)
            tname = f'{self._out_name_factory.get_new_name(cipher_t)}{t_suffix}'
            enc_expr = EncryptionExpression(private_expr, privacy_label_expr,
                                            homomorphism)
            new_out_param = self._out_name_factory.add_idf(
                tname, cipher_t, enc_expr)
            crypto_params = cfg.get_crypto_params(homomorphism)
            self._ensure_encryption(expr.statement, priv_result_idf,
                                    new_privacy, crypto_params, new_out_param,
                                    False, False)
            out_var = new_out_param.get_loc_expr()

        # Add an invisible CircuitComputationStatement to the solidity code, which signals the offchain simulator,
        # that the value the contained out variable must be computed at this point by simulating expression evaluation
        expr.statement.pre_statements.append(
            CircuitComputationStatement(new_out_param))
        return out_var