Example #1
0
def index(input_op_node: saldag.OpNode, output_name: str, idx_col_name: str = "index"):
    """
    Define Index relation.

    :param input_op_node: Parent node for the node returned by this method.
    :param output_name: Name of returned Index node.
    :param idx_col_name: Name of index column that gets appended to relation.
    :return: Index OpNode.
    """

    in_rel = input_op_node.out_rel

    # Copy over columns from existing relation
    out_rel_cols = copy.deepcopy(in_rel.columns)

    index_col = rel.Column(
        output_name, idx_col_name, len(in_rel.columns), "INTEGER", set())
    out_rel_cols = [index_col] + out_rel_cols

    # Create output relation
    out_rel = rel.Relation(output_name, out_rel_cols, copy.copy(in_rel.stored_with))
    out_rel.update_columns()

    op = saldag.Index(out_rel, input_op_node, idx_col_name)
    # Add it as a child to input node
    input_op_node.children.add(op)

    return op
Example #2
0
def _join_flags(left_input_node: cc_dag.OpNode,
                right_input_node: cc_dag.OpNode,
                output_name: str,
                left_col_names: list,
                right_col_names: list,
                out_col_name: str = "flags"):
    """
    Define JoinFlags operation.
    """

    join_op = join(left_input_node, right_input_node, output_name,
                   left_col_names, right_col_names)
    join_flags_op = cc_dag.JoinFlags.from_join(join_op)
    out_col = rel.Column(output_name, out_col_name, 0, "INTEGER",
                         join_flags_op.out_rel.columns[0].trust_set)
    out_rel = rel.Relation(output_name, [out_col],
                           join_flags_op.out_rel.stored_with)
    join_flags_op.out_rel = out_rel
    join_flags_op.is_mpc = True

    left_input_node.children.remove(join_op)
    right_input_node.children.remove(join_op)

    left_input_node.children.add(join_flags_op)
    right_input_node.children.add(join_flags_op)

    return join_flags_op
Example #3
0
    def _cols_from_rel(start_idx: int, relation: rel.Relation, key_col_idxs: list):

        result_cols = []
        for num, col in enumerate(relation.columns):
            # Exclude key columns and add num from enumerate to start index
            if col.idx not in set(key_col_idxs):
                new_col = rel.Column(
                    output_name, col.get_name(), num + start_idx - len(key_col_idxs), col.type_str, set())
                result_cols.append(new_col)

        return result_cols
Example #4
0
def multiply(input_op_node: saldag.OpNode, output_name: str, target_col_name: str, operands: list):
    """
    Define Multiply relation.

    :param input_op_node: Parent node for the node returned by this method.
    :param output_name: Name of returned Multiply node.
    :param target_col_name: Name of column that stores results of Multiply operation.
    If target_col_name refers to an already existing column in the relation, then that
    column should also be the first argument in the operands list. If target_col_name
    does not refer to an existing column, then the columns in the operands list will
    be multiplied together in order, and stored in a column named <target_col_name> and
    appended to the relation.
    :param operands: List of operand columns & scalars.
    :return: Multiply OpNode.
    """

    # Get input relation from input node
    in_rel = input_op_node.out_rel

    # Get relevant columns and create copies
    out_rel_cols = copy.deepcopy(in_rel.columns)

    # Replace all column names with corresponding columns.
    operands = [utils.find(in_rel.columns, op) if isinstance(
        op, str) else op for op in operands]
    for operand in operands:
        if hasattr(operand, "coll_sets"):
            operand.coll_sets = set()

    # if target_col already exists, it will be at the 0th index of operands
    if target_col_name == operands[0].name:
        target_column = utils.find(in_rel.columns, target_col_name)
        target_column.coll_sets = set()
    else:
        # TODO: figure out new column's coll_sets
        target_column = rel.Column(
            output_name, target_col_name, len(in_rel.columns), "INTEGER", set())
        out_rel_cols.append(target_column)

    # Create output relation
    out_rel = rel.Relation(output_name, out_rel_cols, copy.copy(in_rel.stored_with))
    out_rel.update_columns()

    # Create our operator node
    op = saldag.Multiply(out_rel, input_op_node, target_column, operands)

    # Add it as a child to input node
    input_op_node.children.add(op)

    return op
Example #5
0
def create(rel_name: str, columns: list, stored_with: set):
    """
    Define Create relation.

    :param rel_name: Name of returned Create node.
    :param columns: List of column objects.
    :param stored_with: Set of input party IDs that own this relation.
    :return: Create OpNode.
    """

    columns = [rel.Column(rel_name, col_name, idx, type_str, collusion_set)
               for idx, (col_name, type_str, collusion_set) in enumerate(columns)]
    out_rel = rel.Relation(rel_name, columns, stored_with)
    op = saldag.Create(out_rel)
    return op
Example #6
0
def num_rows(input_op_node: cc_dag.OpNode,
             output_name: str,
             col_name: str = "len"):
    # TODO docs
    in_rel = input_op_node.out_rel
    # Copy over columns from existing relation
    len_col = rel.Column(output_name, col_name, len(in_rel.columns), "INTEGER",
                         set())
    out_rel_cols = [len_col]

    # Create output relation
    out_rel = rel.Relation(output_name, out_rel_cols,
                           copy.copy(in_rel.stored_with))
    out_rel.update_columns()

    op = cc_dag.NumRows(out_rel, input_op_node, len_col)
    # Add it as a child to input node
    input_op_node.children.add(op)

    return op
Example #7
0
def join(left_input_node: saldag.OpNode, right_input_node: saldag.OpNode, output_name: str,
         left_col_names: list, right_col_names: list):
    """
    Define Join relation.

    :param left_input_node: Left parent node for the node returned by this method.
    :param right_input_node: Right parent node for the node returned by this method.
    :param output_name: Name of returned Join node.
    :param left_col_names: List of join columns in left parent relation.
    :param right_col_names: List of join columns in right parent relation.
    :return: Join OpNode.
    """

    # TODO: technically this should take in a start index as well
    # This helper method takes in a relation, the key column of the join
    # and its index.
    # It returns a list of new columns with correctly merged collusion sets
    # for the output relation (in the same order as they appear on the input
    # relation but excluding the key column)
    def _cols_from_rel(start_idx: int, relation: rel.Relation, key_col_idxs: list):

        result_cols = []
        for num, col in enumerate(relation.columns):
            # Exclude key columns and add num from enumerate to start index
            if col.idx not in set(key_col_idxs):
                new_col = rel.Column(
                    output_name, col.get_name(), num + start_idx - len(key_col_idxs), col.type_str, set())
                result_cols.append(new_col)

        return result_cols

    assert isinstance(left_col_names, list)
    assert isinstance(right_col_names, list)

    # Get input relation from input nodes
    left_in_rel = left_input_node.out_rel
    right_in_rel = right_input_node.out_rel

    # Get columns from both relations
    left_cols = left_in_rel.columns
    right_cols = right_in_rel.columns

    # Get columns we will join on
    left_join_cols = [utils.find(left_cols, left_col_name) for left_col_name in left_col_names]
    right_join_cols = [utils.find(right_cols, right_col_name) for right_col_name in right_col_names]

    # # Get the key columns' merged collusion set
    # keyCollusionSet = utils.mergeCollusionSets(
    #     left_join_col.collusionSet, right_join_col.collusionSet)

    # Create new key columns
    out_key_cols = []
    for i in range(len(left_join_cols)):
        out_key_cols.append(
            rel.Column(output_name, left_join_cols[i].get_name(), i, left_join_cols[i].type_str, set()))

    # Define output relation columns.
    # These will be the key columns followed
    # by all columns from left (other than join columns)
    # and right (again excluding join columns)

    start_idx = len(out_key_cols)
    # continue_idx will be (start_idx + len(left_in_rel.columns) - len(left_join_cols)),
    # which is just len(left_in_rel.columns)
    continue_idx = len(left_in_rel.columns)
    out_rel_cols = out_key_cols \
        + _cols_from_rel(
            start_idx, left_in_rel, [left_join_col.idx for left_join_col in left_join_cols]) \
        + _cols_from_rel(
            continue_idx, right_in_rel, [right_join_col.idx for right_join_col in right_join_cols])

    # The result of the join will be stored with the union
    # of the parties storing left and right
    out_stored_with = left_in_rel.stored_with.union(right_in_rel.stored_with)

    # Create output relation
    out_rel = rel.Relation(output_name, out_rel_cols, out_stored_with)
    out_rel.update_columns()

    # Create join operator
    op = saldag.Join(
        out_rel,
        left_input_node,
        right_input_node,
        left_join_cols,
        right_join_cols
    )

    # Add it as a child to both input nodes
    left_input_node.children.add(op)
    right_input_node.children.add(op)

    return op