def publish_template(self, metadata, operation, params, from_wallet): """ Publish the op template on chain. :param metadata: refers to the template metadata :param operation: refers to the code template :param params: refers to the code parameters :param from_wallet: the system account :return """ op = OpTemplate() op.add_metadata(metadata) op.add_template(operation, params) op.add_creator(from_wallet.address) op.assign_tid(DTHelper.generate_new_dt()) op.create_proof() ipfs_client = IPFSProvider(self.config) ipfs_path = ipfs_client.add(op.to_dict()) tid = DTHelper.dt_to_id(op.tid) name = metadata['main']['name'] checksum = op.proof['checksum'] if not self.verifier.check_op_exist(op.tid): self.op_template.publish_template(tid, name, checksum, ipfs_path, from_wallet) else: self.op_template.update_template(tid, name, checksum, ipfs_path, from_wallet) return op
def trace_dt_lifecycle(self, dt, prefix: list): """ Trace the whole lifecycle for a dt using dfs recursive search. Only when an algorithm cdt is submitted for solving tasks, the terminal state is reached. :param dt: data token identifier. :param prefix: fixed prefix path, then find its subsequent paths. :return all_paths: a list of found prefix + subsequent paths """ prefix = prefix.copy() if len(prefix): owner = self.get_dt_owner(dt) owner_info = self.get_enterprise(owner)[0] prefix.append({ "dt": DTHelper.id_bytes_to_dt(dt), "aggregator": owner_info, "aggrement": 0 }) else: prefix.append({"dt": dt}) dt = DTHelper.dt_to_id_bytes(dt) _, ddo = resolve_asset(dt, self.dt_factory) all_paths = [] if self.verifier.check_asset_type(ddo, self.TERMINAL): jobs = self.trace_cdt_jobs(dt) if len(jobs): for job in jobs: job_id, solver, task_id, demander, task_name, task_desc = job demander_info = self.get_enterprise(demander)[0] solver_info = self.get_enterprise(solver)[0] text = { "task_name": task_name, "task_desc": task_desc, "solver": solver_info, "demander": demander_info, "task_id": task_id, "job_id": job_id } new_path = prefix.copy() new_path.append(text) all_paths.append(new_path) return all_paths grantees = self.trace_dt_grantees(dt) for cdt in grantees: path_lists = self.trace_dt_lifecycle(cdt, prefix) all_paths.extend(path_lists) return all_paths
def activate_cdt(self, cdt, child_dts, aggregator_wallet): """ Activate cdt when all perms are ready. :param cdt: refers to cdt identifier :param child_dts: associated with child_dts identifier :param aggregator_wallet: aggregator account :return """ _cdt = DTHelper.dt_to_id(cdt) _child_dts = [DTHelper.dt_to_id(dt) for dt in child_dts] self.dt_factory.start_compose_dt(_cdt, _child_dts, aggregator_wallet) return
def grant_dt_perm(self, dt, grantee, owner_wallet): """ Grant one dt to other dt. :param dt: refers to data token identifier :param grantee: refers to granted dt identifier :param owner_wallet: owner account :return """ _dt = DTHelper.dt_to_id(dt) _grantee = DTHelper.dt_to_id(grantee) self.dt_factory.grant_dt(_dt, _grantee, owner_wallet) return
def generate_ddo(self, metadata, services, owner_address, child_dts=None, verify=True): """ Create an asset document and declare its services. :param metadata: refers to the asset metadata :param services: list of asset services :param owner_address: refers to the asset owner :param child_dts: list of child asset identifiers :param verify: check the correctness of asset services :return ddo: DDO instance """ ddo = DDO() ddo.add_metadata(metadata, child_dts) ddo.add_creator(owner_address) for service in services: ddo.add_service(service) ddo.assign_dt(DTHelper.generate_new_dt()) ddo.create_proof() # make sure the generated ddo is under system constraits if verify and not self.verifier.verify_services(ddo): raise AssertionError(f'Service agreements are not satisfied') return ddo
def resolve_op(tid, keeper_op_template): """ Resolve a tid to its corresponding OpTemplate. :param tid: the op tid to resolve, e.g., dt:ownership:<32 byte value> :param keeper_op_template: keeper instance of the op-template smart contract :return data: tid info on the chain :return op: OpTemplate of the resolved tid """ tid_bytes = DTHelper.dt_to_id_bytes(tid) data = keeper_op_template.get_template(tid_bytes) if not (data and data[3]): return None, None metadata_url = data[3] ipfs_client = IPFSProvider() op_json = ipfs_client.get(metadata_url) if not op_json: return data, None op = OpTemplate() op.from_dict(op_json) return data, op
def resolve_asset(dt, keeper_dt_factory): """ Resolve an asset dt to its corresponding DDO. :param dt: the asset dt to resolve, e.g., dt:ownership:<32 byte value> :param keeper_dt_factory: keeper instance of the dt-factory smart contract :return data: dt info on the chain :return ddo: DDO of the resolved asset dt """ dt_bytes = DTHelper.dt_to_id_bytes(dt) data = keeper_dt_factory.get_dt_register(dt_bytes) if not (data and data[4]): return None, None metadata_url = data[4] ipfs_client = IPFSProvider() ddo_json = ipfs_client.get(metadata_url) if not ddo_json: return data, None ddo = DDO() ddo.from_dict(ddo_json) return data, ddo
def verify_job_registered(self, job_id, cdt): """Ensure the cdt is submitted to the market with a given job id.""" job = self.task_market.get_job(job_id) if not (job and job[2]): return False return DTHelper.dt_to_id_bytes(cdt) == job[2]
def get_dt_marketplace(self): """ Get all available dts in the marketplace. :return: list """ dt_idx, _, issuers, checksums, _, ipfs_paths, _ = self.dt_factory.get_available_dts( ) issuer_names = self.asset_provider.get_issuer_names(issuers) marketplace_list = [] for dt, issuer_name, ipfs_path, checksum in zip( dt_idx, issuer_names, ipfs_paths, checksums): ddo = resolve_asset_by_url(ipfs_path) if ddo and ddo.metadata['main'].get('type') != "Algorithm": if self.verifier.verify_ddo_integrity(ddo, checksum): dt = DTHelper.id_bytes_to_dt(dt) asset_name = ddo.metadata["main"].get("name") asset_fig = ddo.metadata['main'].get('fig') union_or_not = ddo.is_cdt marketplace_list.append({ "dt": dt, "issuer": issuer_name, "name": asset_name, "fig": asset_fig, "union_or_not": union_or_not }) return marketplace_list
def add_job(self, task_id, cdt, solver_wallet): """ Create a new job on chain with the algorithm cdt. :param cdt: refers to the algorithm composable data token :param task_id: refers to the task id that be solved :param from_wallet: solver account :return: int job_id """ _id = DTHelper.dt_to_id(cdt) job_id = self.task_market.add_job(_id, task_id, solver_wallet) return job_id
def verify_perms_ready(self, cdt_ddo, required_dt=None): """ Ensure the given cdt has got all child permissions. :param cdt_ddo: DDO object for a cdt, previously activated on chain :param required_dt: dt identifier required to be the cdt child :return: bool """ child_dts = [] found = False for dt in cdt_ddo.child_dts: child_dts.append(DTHelper.dt_to_id(dt)) if dt == required_dt: found = True if required_dt and found == False: return False _cdt = DTHelper.dt_to_id(cdt_ddo.dt) return self.dt_factory.check_clinks(_cdt, child_dts)
def publish_dt(self, ddo, issuer_wallet): """ Publish a ddo to the decentralized storage network and register its data token on the smart-contract chain. :param ddo: refers to the asset DDO document :param issuer_wallet: issuer account, enterprize now :return """ ipfs_client = IPFSProvider(self.config) ipfs_path = ipfs_client.add(ddo.to_dict()) dt = DTHelper.dt_to_id(ddo.dt) owner = ddo.creator isLeaf = not bool(ddo.child_dts) checksum = ddo.proof['checksum'] self.dt_factory.mint_dt(dt, owner, isLeaf, checksum, ipfs_path, issuer_wallet) return
def trace_dt_grantees(self, dt): """Get the list of granteed father for a dt.""" _dt = DTHelper.dt_to_id_bytes(dt) return self.dt_factory.get_dt_grantees(_dt)
def get_dt_owner(self, dt): """Get the owner for a data token.""" _dt = DTHelper.dt_to_id_bytes(dt) return self.dt_factory.get_dt_owner(_dt)
def check_op_exist(self, tid): """Check template existence.""" _tid = DTHelper.dt_to_id(tid) return self.op_template.is_template_exist(_tid)
def check_dt_owner(self, dt, owner_address): """Check dt owner.""" _dt = DTHelper.dt_to_id(dt) return self.dt_factory.get_dt_owner(_dt) == owner_address
def check_dt_available(self, dt): """Check dt availability.""" _dt = DTHelper.dt_to_id(dt) return self.dt_factory.check_dt_available(_dt)
def check_dt_perm(self, dt, grantee): """Check granted permission.""" _dt = DTHelper.dt_to_id(dt) _grantee = DTHelper.dt_to_id(grantee) return self.dt_factory.check_dt_perm(_dt, _grantee)
def check_cdt_composed(self, cdt): """Check cdt composability.""" _cdt = DTHelper.dt_to_id(cdt) return self.dt_factory.check_cdt_available(_cdt)