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
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
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
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
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
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
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