From 4d5837e09f7f69e4ed96831b3e624e5988d5d41f Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Mon, 30 Dec 2024 17:31:46 +0100 Subject: [PATCH 01/31] Add V8 query --- dkg/graph.py | 5 +- dkg/providers/node_http.py | 10 +- dkg/utils/node_request.py | 2 +- examples/demo.py | 220 ++++++++++++++++++++++--------------- 4 files changed, 146 insertions(+), 91 deletions(-) diff --git a/dkg/graph.py b/dkg/graph.py index 43cf234..025b0fb 100644 --- a/dkg/graph.py +++ b/dkg/graph.py @@ -37,12 +37,13 @@ def __init__(self, manager: DefaultRequestManager): def query( self, query: str, - repository: str, + repository: str | None = None, + paranet_ual: str | None = None, ) -> NQuads: parsed_query = parseQuery(query) query_type = parsed_query[1].name.replace("Query", "").upper() - operation_id: NodeResponseDict = self._query(query, query_type, repository)[ + operation_id: NodeResponseDict = self._query(query, query_type, repository, paranet_ual)[ "operationId" ] operation_result = self.get_operation_result(operation_id, "query") diff --git a/dkg/providers/node_http.py b/dkg/providers/node_http.py index 1286655..c096ca2 100644 --- a/dkg/providers/node_http.py +++ b/dkg/providers/node_http.py @@ -25,8 +25,14 @@ class NodeHTTPProvider: - def __init__(self, endpoint_uri: URI | str, auth_token: str | None = None): + def __init__( + self, + endpoint_uri: URI | str, + api_version: str = "v1", + auth_token: str | None = None, + ): self.endpoint_uri = URI(endpoint_uri) + self.api_version = api_version self.auth_token = auth_token def make_request( @@ -36,7 +42,7 @@ def make_request( params: dict[str, Any] = {}, data: dict[str, Any] = {}, ) -> NodeResponseDict: - url = f"{self.endpoint_uri}/{path}" + url = f"{self.endpoint_uri}/{self.api_version}/{path}" headers = ( {"Authorization": f"Bearer {self.auth_token}"} if self.auth_token else {} ) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 977dc8e..d7faac4 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -77,7 +77,7 @@ class NodeRequest: query = NodeCall( method=HTTPRequestMethod.POST, path="query", - data={"query": str, "type": str, "repository": str}, + data={"query": str, "type": str, "repository": str | None, "paranet_ual": str | None}, ) diff --git a/examples/demo.py b/examples/demo.py index 071b216..f77492b 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -20,7 +20,7 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider -node_provider = NodeHTTPProvider("http://localhost:8900") +node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") blockchain_provider = BlockchainProvider( "development", "hardhat2:31337", @@ -67,116 +67,164 @@ def print_json(json_dict: dict): divider() -formatted_assertions = dkg.assertion.format_graph(content) -print("======================== ASSET FORMATTED") -print_json(formatted_assertions) +# formatted_assertions = dkg.assertion.format_graph(content) +# print("======================== ASSET FORMATTED") +# print_json(formatted_assertions) -divider() +# divider() -public_assertion_id = dkg.assertion.get_public_assertion_id(content) -print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") -print(public_assertion_id) +# public_assertion_id = dkg.assertion.get_public_assertion_id(content) +# print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") +# print(public_assertion_id) -divider() +# divider() -public_assertion_size = dkg.assertion.get_size(content) -print("======================== PUBLIC ASSERTION SIZE CALCULATED") -print(public_assertion_size) +# public_assertion_size = dkg.assertion.get_size(content) +# print("======================== PUBLIC ASSERTION SIZE CALCULATED") +# print(public_assertion_size) -divider() +# divider() -public_assertion_triples_number = dkg.assertion.get_triples_number(content) -print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") -print(public_assertion_triples_number) +# public_assertion_triples_number = dkg.assertion.get_triples_number(content) +# print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") +# print(public_assertion_triples_number) -divider() +# divider() -public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) -print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") -print(public_assertion_chunks_number) +# public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) +# print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") +# print(public_assertion_chunks_number) -divider() +# divider() -bid_suggestion = dkg.network.get_bid_suggestion( - public_assertion_id, - public_assertion_size, - 2, -) -print("======================== BID SUGGESTION CALCULATED") -print(bid_suggestion) +# bid_suggestion = dkg.network.get_bid_suggestion( +# public_assertion_id, +# public_assertion_size, +# 2, +# ) +# print("======================== BID SUGGESTION CALCULATED") +# print(bid_suggestion) -divider() +# divider() -current_allowance = dkg.asset.get_current_allowance() -print("======================== GET CURRENT ALLOWANCE") -print(current_allowance) +# current_allowance = dkg.asset.get_current_allowance() +# print("======================== GET CURRENT ALLOWANCE") +# print(current_allowance) -divider() +# divider() -allowance_increase = dkg.asset.increase_allowance(bid_suggestion) -print("======================== INCREASE ALLOWANCE") -print(allowance_increase) +# allowance_increase = dkg.asset.increase_allowance(bid_suggestion) +# print("======================== INCREASE ALLOWANCE") +# print(allowance_increase) -divider() +# divider() -allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) -print("======================== DECREASE ALLOWANCE") -print(allowance_decrease) +# allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) +# print("======================== DECREASE ALLOWANCE") +# print(allowance_decrease) -divider() +# divider() -allowance_set = dkg.asset.set_allowance(bid_suggestion) -print("======================== SET ALLOWANCE") -print(allowance_set) +# allowance_set = dkg.asset.set_allowance(bid_suggestion) +# print("======================== SET ALLOWANCE") +# print(allowance_set) -divider() +# divider() -create_asset_result = dkg.asset.create(content, 2) -print("======================== ASSET CREATED") -print_json(create_asset_result) -divider() +# create_asset_result = dkg.asset.create(content, 2) +# print("======================== ASSET CREATED") +# print_json(create_asset_result) +# divider() -validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) -print("======================== VALIDATE UAL") -print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") -divider() +# validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) +# print("======================== VALIDATE UAL") +# print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") +# divider() -owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) -print("======================== GET ASSET OWNER") -print(owner_result) -divider() +# owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) +# print("======================== GET ASSET OWNER") +# print(owner_result) +# divider() -get_asset_result = dkg.asset.get(create_asset_result["UAL"]) -print("======================== ASSET RESOLVED") -print_json(get_asset_result) -divider() +# get_asset_result = dkg.asset.get(create_asset_result["UAL"]) +# print("======================== ASSET RESOLVED") +# print_json(get_asset_result) +# divider() -get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") -print("======================== ASSET LATEST RESOLVED") -print_json(get_latest_asset_result) -divider() +# get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") +# print("======================== ASSET LATEST RESOLVED") +# print_json(get_latest_asset_result) +# divider() -get_latest_finalized_asset_result = dkg.asset.get( - create_asset_result["UAL"], "latest_finalized", "all" -) -print("======================== ASSET LATEST FINALIZED RESOLVED") -print_json(get_latest_finalized_asset_result) -divider() +# get_latest_finalized_asset_result = dkg.asset.get( +# create_asset_result["UAL"], "latest_finalized", "all" +# ) +# print("======================== ASSET LATEST FINALIZED RESOLVED") +# print_json(get_latest_finalized_asset_result) +# divider() -get_first_state_by_index = dkg.asset.get(create_asset_result["UAL"], 0, "all") -print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") -print_json(get_first_state_by_index) -divider() - -get_first_state_by_hash = dkg.asset.get( - create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" +# get_first_state_by_index = dkg.asset.get(create_asset_result["UAL"], 0, "all") +# print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") +# print_json(get_first_state_by_index) +# divider() + +# get_first_state_by_hash = dkg.asset.get( +# create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" +# ) +# print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") +# print_json(get_first_state_by_hash) +# divider() + +query_operation_result = dkg.graph.query( + """ + PREFIX gs1: PREFIX schema: + + SELECT ?recipeNameRaw ?baseUal + WHERE { + ?recipe a schema:Recipe ; + GRAPH ?ual { + ?recipe schema:name ?recipeNameRaw ; + } + FILTER (STRSTARTS(STR(?ual), "did:dkg:base:84532/0x4e8ebfce9a0f4be374709f1ef2791e8ca6371ecb/")) + BIND (REPLACE(STR(?ual), "(did:dkg:base:[^/]+/[^/]+/[^/]+)(/.*)?", "$1") AS ?baseUal) + } + """ ) -print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") -print_json(get_first_state_by_hash) -divider() - -query_result = dkg.graph.query( - "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" +print("======================== ASSET QUERY") +print(query_operation_result) + +divider() + +query_operation_result = dkg.graph.query( + """ + CONSTRUCT { ?s ?p ?o .} + WHERE { + GRAPH ?g { ?s ?p ?o . } + VALUES ?g { + + + } + } + """ +) +print("======================== ASSET QUERY") +print(query_operation_result) + +divider() + +query_operation_result = dkg.graph.query( + """ + CONSTRUCT { ?s ?p ?o . } + WHERE { + { + GRAPH { ?s ?p ?o . } + } + UNION + { + GRAPH { ?s ?p ?o . } + } + } + """ ) -print("======================== QUERY LOCAL CURRENT RESULT") -print(query_result) +print("======================== ASSET QUERY") +print(query_operation_result) From dae8fd5e783d5c486b9a5db37489c09f9f20a7e4 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Tue, 31 Dec 2024 09:19:53 +0100 Subject: [PATCH 02/31] format query strings in demo --- examples/demo.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/demo.py b/examples/demo.py index f77492b..d3679e0 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -177,17 +177,17 @@ def print_json(json_dict: dict): query_operation_result = dkg.graph.query( """ - PREFIX gs1: PREFIX schema: - - SELECT ?recipeNameRaw ?baseUal - WHERE { - ?recipe a schema:Recipe ; - GRAPH ?ual { - ?recipe schema:name ?recipeNameRaw ; - } - FILTER (STRSTARTS(STR(?ual), "did:dkg:base:84532/0x4e8ebfce9a0f4be374709f1ef2791e8ca6371ecb/")) - BIND (REPLACE(STR(?ual), "(did:dkg:base:[^/]+/[^/]+/[^/]+)(/.*)?", "$1") AS ?baseUal) + PREFIX gs1: + PREFIX schema: + SELECT ?recipeNameRaw ?baseUal + WHERE { + ?recipe a schema:Recipe ; + GRAPH ?ual { + ?recipe schema:name ?recipeNameRaw ; } + FILTER (STRSTARTS(STR(?ual), "did:dkg:base:84532/0x4e8ebfce9a0f4be374709f1ef2791e8ca6371ecb/")) + BIND (REPLACE(STR(?ual), "(did:dkg:base:[^/]+/[^/]+/[^/]+)(/.*)?", "$1") AS ?baseUal) + } """ ) print("======================== ASSET QUERY") From 19a004284557ee93475fc6996184921fb0f139b0 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 3 Jan 2025 17:27:24 +0100 Subject: [PATCH 03/31] Initial v8 create --- dkg/asset.py | 387 +++-- dkg/constants.py | 31 +- dkg/data/interfaces/AssertionStorage.json | 229 --- dkg/data/interfaces/ContentAsset.json | 697 --------- dkg/data/interfaces/ContentAssetStorage.json | 706 --------- dkg/data/interfaces/Hub.json | 296 +++- dkg/data/interfaces/IdentityStorage.json | 58 + dkg/data/interfaces/Paranet.json | 244 +-- .../ParanetIncentivesPoolFactory.json | 20 +- .../ParanetKnowledgeMinersRegistry.json | 24 +- ...l.json => ParanetNeuroIncentivesPool.json} | 14 +- dkg/data/interfaces/ParanetsRegistry.json | 134 +- .../ServiceAgreementStorageProxy.json | 1314 ----------------- dkg/data/interfaces/Token.json | 163 +- dkg/providers/blockchain.py | 9 +- dkg/utils/blockchain_request.py | 6 + dkg/utils/node_request.py | 14 +- dkg/utils/rdf.py | 201 ++- examples/demo.py | 33 +- 19 files changed, 1192 insertions(+), 3388 deletions(-) delete mode 100644 dkg/data/interfaces/AssertionStorage.json delete mode 100644 dkg/data/interfaces/ContentAsset.json delete mode 100644 dkg/data/interfaces/ContentAssetStorage.json rename dkg/data/interfaces/{ParanetNeurowebIncentivesPool.json => ParanetNeuroIncentivesPool.json} (97%) delete mode 100644 dkg/data/interfaces/ServiceAgreementStorageProxy.json diff --git a/dkg/asset.py b/dkg/asset.py index cc56961..61cf419 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -18,13 +18,18 @@ import json import math import re +import hashlib from typing import Literal, Type from pyld import jsonld from web3 import Web3 -from web3.constants import ADDRESS_ZERO, HASH_ZERO +from web3.constants import ADDRESS_ZERO from web3.exceptions import ContractLogicError from web3.types import TxReceipt +from itertools import chain +from eth_abi.packed import encode_packed +from eth_account.messages import encode_defunct +from eth_account import Account from dkg.constants import ( DEFAULT_HASH_FUNCTION_ID, @@ -32,6 +37,12 @@ PRIVATE_ASSERTION_PREDICATE, PRIVATE_CURRENT_REPOSITORY, PRIVATE_HISTORICAL_REPOSITORY, + PRIVATE_RESOURCE_PREDICATE, + PRIVATE_HASH_SUBJECT_PREFIX, + CHUNK_BYTE_SIZE, + MAX_FILE_SIZE, + Operations, + DefaultParameters, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -65,7 +76,16 @@ StoreTypes, validate_operation_status, ) -from dkg.utils.rdf import format_content, normalize_dataset +from dkg.utils.rdf import ( + format_content, + normalize_dataset, + format_dataset, + generate_missing_ids_for_blank_nodes, + group_nquads_by_subject, + generate_named_node, + calculate_merkle_root, + calculate_number_of_chunks, +) from dkg.utils.ual import format_ual, parse_ual @@ -197,170 +217,260 @@ def decrease_allowance( _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) _create = Method(BlockchainRequest.create_asset) _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) _local_store = Method(NodeRequest.local_store) _publish = Method(NodeRequest.publish) + def process_content(self, content: str) -> list: + return [line.strip() for line in content.split("\n") if line.strip() != ""] + + def solidity_packed_sha256(self, types: list[str], values: list) -> str: + # Encode the values using eth_abi's encode_packed + packed_data = encode_packed(types, values) + + # Calculate SHA256 + sha256_hash = hashlib.sha256(packed_data).hexdigest() + + return f"0x{sha256_hash}" + + def insert_triple_sorted(self, triples_list: list, new_triple: str) -> int: + # Assuming triples_list is already sorted + left = 0 + right = len(triples_list) + + while left < right: + mid = (left + right) // 2 + if triples_list[mid] < new_triple: + left = mid + 1 + else: + right = mid + + # Insert the new triple at the correct position + triples_list.insert(left, new_triple) + return left + + def get_operation_status_dict(self, operation_result, operation_id): + # Check if data exists and has errorType + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data") + and operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} + + def get_message_signer_address(self, dataset_root: str, signature: dict): + message = encode_defunct(Web3.to_bytes(dataset_root)) + r, s, v = signature.get("r"), signature.get("s"), signature.get("v") + r = r[2:] if r.startswith("0x") else r + s = s[2:] if s.startswith("0x") else s + + sig = "0x" + r + s + hex(v)[2:].zfill(2) + + return Account.recover_message(message, signature=sig) + def create( self, content: dict[Literal["public", "private"], JSONLD], epochs_number: int, + minimum_number_of_finalization_confirmations: int, + minimum_number_of_node_replications: int, token_amount: Wei | None = None, - immutable: bool = False, - content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - paranet_ual: UAL | None = None, + # immutable: bool = False, + # content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + # paranet_ual: UAL | None = None, ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: blockchain_id = self.manager.blockchain_provider.blockchain_id - assertions = format_content(content, content_type) - public_assertion_id = MerkleTree( - hash_assertion_with_indexes(assertions["public"]), - sort_pairs=True, - ).root - public_assertion_metadata = generate_assertion_metadata(assertions["public"]) + dataset = {} + public_content = dataset.get("public") + private_content = dataset.get("private") + if isinstance(content, str): + dataset["public"] = self.process_content(content) + elif isinstance(public_content, str) or ( + not public_content and private_content and isinstance(private_content, str) + ): + if public_content: + dataset["public"] = self.process_content(public_content) + else: + dataset["public"] = [] - content_asset_storage_address = self._get_asset_storage_address( - "ContentAssetStorage" - ) + if private_content and isinstance(private_content, str): + dataset["private"] = self.process_content(private_content) + else: + dataset = format_dataset(content) - if token_amount is None: - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_number, - public_assertion_metadata["size"], - content_asset_storage_address, - public_assertion_id, - DEFAULT_HASH_FUNCTION_ID, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] + public_triples_grouped = [] + + # TODO: Uncomment and test this + # dataset["public"] = generate_missing_ids_for_blank_nodes(dataset.get("public")) + + if dataset.get("private") and len(dataset.get("private")): + # TODO: Uncomment and test this + # dataset["private"] = generate_missing_ids_for_blank_nodes( + # dataset.get("private") + # ) + + # Group private triples by subject and flatten + private_triples_grouped = group_nquads_by_subject( + dataset.get("private"), True ) - current_allowance = self.get_current_allowance() - if is_allowance_increased := current_allowance < token_amount: - self.increase_allowance(token_amount) + dataset["private"] = list(chain.from_iterable(private_triples_grouped)) - result = {"publicAssertionId": public_assertion_id, "operation": {}} + # Compute private root and add to public + private_root = calculate_merkle_root(dataset.get("private")) + dataset["public"].append( + f'<{generate_named_node()}> <${PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' + ) - try: - if paranet_ual is None: - receipt: TxReceipt = self._create( - { - "assertionId": Web3.to_bytes(hexstr=public_assertion_id), - "size": public_assertion_metadata["size"], - "triplesNumber": public_assertion_metadata["triples_number"], - "chunksNumber": public_assertion_metadata["chunks_number"], - "tokenAmount": token_amount, - "epochsNumber": epochs_number, - "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], - "immutable_": immutable, - } - ) - else: - parsed_paranet_ual = parse_ual(paranet_ual) - paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( - parsed_paranet_ual["contract_address"], - parsed_paranet_ual["token_id"], - ) + # Compute private root and add to public + public_triples_grouped = group_nquads_by_subject( + dataset.get("public"), True + ) + + # Create a dictionary for public subject -> index for quick lookup + public_subject_dict = {} + for i in range(len(public_triples_grouped)): + public_subject = public_triples_grouped[i][0].split(" ")[0] + public_subject_dict[public_subject] = i + + private_triple_subject_hashes_grouped_without_public_pair = [] + + # Integrate private subjects into public or store separately if no match to be appended later + for private_triples in private_triples_grouped: + private_subject = private_triples[0].split(" ")[ + 0 + ] # Extract the private subject - receipt: TxReceipt = self._mint_paranet_knowledge_asset( - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - { - "assertionId": Web3.to_bytes(hexstr=public_assertion_id), - "size": public_assertion_metadata["size"], - "triplesNumber": public_assertion_metadata["triples_number"], - "chunksNumber": public_assertion_metadata["chunks_number"], - "tokenAmount": token_amount, - "epochsNumber": epochs_number, - "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], - "immutable_": immutable, - }, + private_subject_hash = self.solidity_packed_sha256( + types=["string"], + values=[private_subject[1:-1]], ) - result["paranetId"] = Web3.to_hex( - Web3.solidity_keccak( - ["address", "uint256"], - [ - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - ], + if ( + private_subject in public_subject_dict + ): # Check if there's a public pair + # If there's a public pair, insert a representation in that group + # TODO: Test this + public_index = public_subject_dict.get(private_subject) + self.insert_triple_sorted( + public_triples_grouped.get(public_index), + f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{generate_named_node()}> .", + ) + else: + # If no public pair, maintain separate list, inserting sorted by hash + self.insert_triple_sorted( + private_triple_subject_hashes_grouped_without_public_pair, + f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{generate_named_node()}> .", ) - ) - except ContractLogicError as err: - if is_allowance_increased: - self.decrease_allowance(token_amount) - raise err - events = self.manager.blockchain_provider.decode_logs_event( - receipt, - "ContentAsset", - "AssetMinted", - ) - token_id = events[0].args["tokenId"] + for triple in private_triple_subject_hashes_grouped_without_public_pair: + public_triples_grouped.append([triple]) - result["UAL"] = format_ual( - blockchain_id, content_asset_storage_address, token_id + dataset["public"] = list(chain.from_iterable(public_triples_grouped)) + else: + # TODO: Test this + # No private triples, just group and flatten public + public_triples_grouped = group_nquads_by_subject( + dataset.get("public"), True + ) + dataset["public"] = list(chain.from_iterable(public_triples_grouped)) + + # Calculate the number of chunks + number_of_chunks = calculate_number_of_chunks( + dataset.get("public"), CHUNK_BYTE_SIZE ) - result["operation"]["mintKnowledgeAsset"] = json.loads(Web3.to_json(receipt)) + dataset_size = number_of_chunks * CHUNK_BYTE_SIZE - assertions_list = [ - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": public_assertion_id, - "assertion": assertions["public"], - "storeType": StoreTypes.TRIPLE, - } - ] + # Validate the assertion size in bytes + # TODO: Move into validation service once developed + if dataset_size > MAX_FILE_SIZE: + raise ValueError(f"File size limit is {MAX_FILE_SIZE / (1024 * 1024)}MB.") - if content.get("private", None): - assertions_list.append( - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": MerkleTree( - hash_assertion_with_indexes(assertions["private"]), - sort_pairs=True, - ).root, - "assertion": assertions["private"], - "storeType": StoreTypes.TRIPLE, - } - ) + # Calculate the Merkle root + dataset_root = calculate_merkle_root(dataset.get("public")) + + # Get the contract address for KnowledgeCollectionStorage + content_asset_storage_address = self._get_asset_storage_address( + "KnowledgeCollectionStorage" + ) - operation_id = self._publish( - public_assertion_id, - assertions["public"], + publish_operation_id = self._publish( + dataset_root, + dataset, blockchain_id, - content_asset_storage_address, - token_id, DEFAULT_HASH_FUNCTION_ID, + minimum_number_of_node_replications, )["operationId"] - operation_result = self.get_operation_result(operation_id, "publish") + publish_operation_result = self.get_operation_result( + Operations.PUBLISH.value, + publish_operation_id, + ) - result["operation"]["publish"] = { - "operationId": operation_id, - "status": operation_result["status"], - } + if publish_operation_result.get( + "status" + ) != OperationStatus.COMPLETED and not publish_operation_result.get( + "data", {} + ).get("minAcksReached"): + return { + "datasetRoot": dataset_root, + "operation": { + "publish": self.get_operation_status_dict( + publish_operation_result, publish_operation_id + ) + }, + } - if operation_result["status"] == OperationStatus.COMPLETED: - operation_id = self._local_store(assertions_list)["operationId"] - operation_result = self.get_operation_result(operation_id, "local-store") + data = publish_operation_result.get("data", {}) + signatures = data.get("signatures") - result["operation"]["localStore"] = { - "operationId": operation_id, - "status": operation_result["status"], - } + publisher_node_signature = data.get("publisherNodeSignature", {}) + publisher_node_identity_id = publisher_node_signature.get("identityId") + publisher_node_r = publisher_node_signature.get("r") + publisher_node_vs = publisher_node_signature.get("vs") - return result - + identity_ids, r, vs = [], [], [] + + for signature in signatures: + try: + signer_address = self.get_message_signer_address( + dataset_root, signature + ) + + key_is_operational_wallet = self._key_is_operational_wallet( + signature.get("identityId"), + Web3.solidity_keccak(["address"], [signer_address]), + 2, # IdentityLib.OPERATIONAL_KEY + ) + + # If valid, append the signature components + if key_is_operational_wallet: + identity_ids.append(signature.get("identityId")) + r.append(signature.get("r")) + vs.append(signature.get("vs")) + + except Exception: + continue + + # result["operation"]["publish"] = { + # "operationId": operation_id, + # "status": operation_result["status"], + # } + + # if operation_result["status"] == OperationStatus.COMPLETED: + # operation_id = self._local_store(assertions_list)["operationId"] + # operation_result = self.get_operation_result(operation_id, "local-store") + + # result["operation"]["localStore"] = { + # "operationId": operation_id, + # "status": operation_result["status"], + # } + + # return result def local_store( self, @@ -489,7 +599,6 @@ def local_store( return result - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) def submit_to_paranet( @@ -587,7 +696,10 @@ def handle_latest_finalized_state(token_id: int) -> tuple[HexStr, bool]: is_state_finalized = False match state: - case KnowledgeAssetEnumStates.LATEST | KnowledgeAssetEnumStates.LATEST_FINALIZED: + case ( + KnowledgeAssetEnumStates.LATEST + | KnowledgeAssetEnumStates.LATEST_FINALIZED + ): public_assertion_id, is_state_finalized = handle_latest_finalized_state( token_id ) @@ -898,13 +1010,18 @@ def get_agreement_id(self, contract_address: Address, token_id: int) -> HexStr: _get_operation_result = Method(NodeRequest.get_operation_result) - @retry(catch=OperationNotFinished, max_retries=5, base_delay=1, backoff=2) + @retry( + catch=OperationNotFinished, + max_retries=DefaultParameters.MAX_NUMBER_OF_RETRIES.value, + base_delay=DefaultParameters.FREQUENCY.value, + backoff=2, + ) def get_operation_result( - self, operation_id: str, operation: str + self, operation: str, operation_id: str ) -> NodeResponseDict: operation_result = self._get_operation_result( - operation_id=operation_id, operation=operation, + operation_id=operation_id, ) validate_operation_status(operation_result) diff --git a/dkg/constants.py b/dkg/constants.py index cf50cea..679a135 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -1,3 +1,4 @@ +from enum import Enum # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -15,10 +16,29 @@ # specific language governing permissions and limitations # under the License. +DEFAULT_CANON_ALGORITHM = "URDNA2015" +DEFAULT_RDF_FORMAT = "application/n-quads" + PRIVATE_ASSERTION_PREDICATE = ( - "https://ontology.origintrail.io/dkg/1.0#privateAssertionID" + "https://ontology.origintrail.io/dkg/1.0#privateMerkleRoot" +) + +PRIVATE_HASH_SUBJECT_PREFIX = "https://ontology.origintrail.io/dkg/1.0#metadata-hash:" + +PRIVATE_RESOURCE_PREDICATE = ( + "https://ontology.origintrail.io/dkg/1.0#representsPrivateResource" ) +CHUNK_BYTE_SIZE = 32 + +MAX_FILE_SIZE = 10000000 + + +class DefaultParameters(Enum): + MAX_NUMBER_OF_RETRIES: int = 5 + FREQUENCY: int = 5 + + BLOCKCHAINS = { "development": { "hardhat1:31337": { @@ -67,3 +87,12 @@ PRIVATE_HISTORICAL_REPOSITORY = "privateHistory" PRIVATE_CURRENT_REPOSITORY = "privateCurrent" + + +class Operations(Enum): + PUBLISH = "publish" + GET = "get" + LOCAL_STORE = "local-store" + QUERY = "query" + PUBLISH_PARANET = "publishParanet" + FINALITY = "finality" diff --git a/dkg/data/interfaces/AssertionStorage.json b/dkg/data/interfaces/AssertionStorage.json deleted file mode 100644 index 749ce61..0000000 --- a/dkg/data/interfaces/AssertionStorage.json +++ /dev/null @@ -1,229 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "assertionExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - } - ], - "name": "createAssertion", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "deleteAssertion", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertion", - "outputs": [ - { - "components": [ - { - "internalType": "uint256", - "name": "timestamp", - "type": "uint256" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - } - ], - "internalType": "struct AssertionStructs.Assertion", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertionChunksNumber", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertionSize", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertionTimestamp", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "getAssertionTriplesNumber", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/data/interfaces/ContentAsset.json b/dkg/data/interfaces/ContentAsset.json deleted file mode 100644 index df9ed74..0000000 --- a/dkg/data/interfaces/ContentAsset.json +++ /dev/null @@ -1,697 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "AssetExpired", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "CommitPhaseOngoing", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "CommitPhaseSucceeded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "FirstEpochHasAlreadyEnded", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetStorage", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "NoPendingUpdate", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetStorage", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "latestStateIndex", - "type": "uint256" - } - ], - "name": "PendingUpdateFinalization", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "assetStorage", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "latestState", - "type": "bytes32" - } - ], - "name": "UpdateIsNotFinalized", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "returnedTokenAmount", - "type": "uint96" - } - ], - "name": "AssetBurnt", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "state", - "type": "bytes32" - } - ], - "name": "AssetMinted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "AssetPaymentIncreased", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "stateIndex", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "returnedTokenAmount", - "type": "uint96" - } - ], - "name": "AssetStateUpdateCanceled", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "stateIndex", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "updateTokenAmount", - "type": "uint96" - } - ], - "name": "AssetStateUpdated", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "AssetStoringPeriodExtended", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "assetContract", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "AssetUpdatePaymentIncreased", - "type": "event" - }, - { - "inputs": [], - "name": "assertionContract", - "outputs": [ - { - "internalType": "contract Assertion", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "burnAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "cancelAssetStateUpdate", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "clearOldCommitsMetadata", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "contentAssetStorage", - "outputs": [ - { - "internalType": "contract ContentAssetStorage", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "components": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "internalType": "struct ContentAssetStructs.AssetInputArgs", - "name": "args", - "type": "tuple" - } - ], - "name": "createAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "name": "createAssetWithVariables", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "extendAssetStoringPeriod", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "hashingProxy", - "outputs": [ - { - "internalType": "contract HashingProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "increaseAssetTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "increaseAssetUpdateTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [], - "name": "parametersStorage", - "outputs": [ - { - "internalType": "contract ParametersStorage", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "serviceAgreementStorageProxy", - "outputs": [ - { - "internalType": "contract ServiceAgreementStorageProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "serviceAgreementV1", - "outputs": [ - { - "internalType": "contract ServiceAgreementV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "_flag", - "type": "bool" - } - ], - "name": "setOldMetadataClearingFlag", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "unfinalizedStateStorage", - "outputs": [ - { - "internalType": "contract UnfinalizedStateStorage", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint96", - "name": "updateTokenAmount", - "type": "uint96" - } - ], - "name": "updateAssetState", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/data/interfaces/ContentAssetStorage.json b/dkg/data/interfaces/ContentAssetStorage.json deleted file mode 100644 index b931831..0000000 --- a/dkg/data/interfaces/ContentAssetStorage.json +++ /dev/null @@ -1,706 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "approved", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Approval", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "indexed": false, - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "ApprovalForAll", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "indexed": true, - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "Transfer", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "approve", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "assetAssertionId", - "type": "bytes32" - } - ], - "name": "assertionExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "balanceOf", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "burn", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "deleteAssertionIssuer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "deleteAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "generateTokenId", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getApproved", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "getAssertionIdByIndex", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getAssertionIds", - "outputs": [ - { - "internalType": "bytes32[]", - "name": "", - "type": "bytes32[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getAssertionIdsLength", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "assertionIndex", - "type": "uint256" - } - ], - "name": "getAssertionIssuer", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getAsset", - "outputs": [ - { - "components": [ - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - }, - { - "internalType": "bytes32[]", - "name": "assertionIds", - "type": "bytes32[]" - } - ], - "internalType": "struct ContentAssetStructs.Asset", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "getLatestAssertionId", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - }, - { - "internalType": "address", - "name": "operator", - "type": "address" - } - ], - "name": "isApprovedForAll", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "isMutable", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "name": "issuers", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "mint", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "ownerOf", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - } - ], - "name": "pushAssertionId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes", - "name": "data", - "type": "bytes" - } - ], - "name": "safeTransferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "operator", - "type": "address" - }, - { - "internalType": "bool", - "name": "approved", - "type": "bool" - } - ], - "name": "setApprovalForAll", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "issuer", - "type": "address" - } - ], - "name": "setAssertionIssuer", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "name": "setMutability", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "symbol", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "tokenURI", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "tokenId", - "type": "uint256" - } - ], - "name": "transferFrom", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/data/interfaces/Hub.json b/dkg/data/interfaces/Hub.json index 1c53f39..92906e6 100644 --- a/dkg/data/interfaces/Hub.json +++ b/dkg/data/interfaces/Hub.json @@ -1,4 +1,118 @@ [ + { + "inputs": [], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AddressAlreadyInSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AddressDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ContractAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ContractDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "contractName", + "type": "string" + } + ], + "name": "ContractNotRegistered", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyName", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "InvalidTargetContract", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -18,6 +132,25 @@ "name": "AssetStorageChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "contractName", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "AssetStorageRemoved", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -37,6 +170,25 @@ "name": "ContractChanged", "type": "event" }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "contractName", + "type": "string" + }, + { + "indexed": false, + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "ContractRemoved", + "type": "event" + }, { "anonymous": false, "inputs": [ @@ -94,6 +246,30 @@ "name": "OwnershipTransferred", "type": "event" }, + { + "inputs": [ + { + "internalType": "address", + "name": "target", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "forwardCall", + "outputs": [ + { + "internalType": "bytes", + "name": "", + "type": "bytes" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "getAllAssetStorages", @@ -111,7 +287,7 @@ "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSetLib.Contract[]", + "internalType": "struct UnorderedNamedContractDynamicSet.Contract[]", "name": "", "type": "tuple[]" } @@ -136,7 +312,7 @@ "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSetLib.Contract[]", + "internalType": "struct UnorderedNamedContractDynamicSet.Contract[]", "name": "", "type": "tuple[]" } @@ -284,6 +460,58 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "assetStorageAddress", + "type": "address" + } + ], + "name": "removeAssetStorageByAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "assetStorageName", + "type": "string" + } + ], + "name": "removeAssetStorageByName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "contractAddress", + "type": "address" + } + ], + "name": "removeContractByAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "contractName", + "type": "string" + } + ], + "name": "removeContractByName", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [], "name": "renounceOwnership", @@ -291,6 +519,70 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "internalType": "struct HubLib.Contract[]", + "name": "newContracts", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "internalType": "struct HubLib.Contract[]", + "name": "newAssetStorageContracts", + "type": "tuple[]" + }, + { + "internalType": "address[]", + "name": "contractsToReinitialize", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "string", + "name": "contractName", + "type": "string" + }, + { + "internalType": "bytes[]", + "name": "encodedData", + "type": "bytes[]" + } + ], + "internalType": "struct HubLib.ForwardCallInputArgs[]", + "name": "forwardCallsData", + "type": "tuple[]" + } + ], + "name": "setAndReinitializeContracts", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/dkg/data/interfaces/IdentityStorage.json b/dkg/data/interfaces/IdentityStorage.json index 568fde9..e7d99f4 100644 --- a/dkg/data/interfaces/IdentityStorage.json +++ b/dkg/data/interfaces/IdentityStorage.json @@ -10,6 +10,38 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "length", + "type": "uint256" + } + ], + "name": "IndexOutOfBounds", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -264,6 +296,19 @@ "stateMutability": "view", "type": "function" }, + { + "inputs": [], + "name": "lastIdentityId", + "outputs": [ + { + "internalType": "uint72", + "name": "", + "type": "uint72" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [], "name": "name", @@ -308,6 +353,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + } + ], + "name": "setLastIdentityId", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { diff --git a/dkg/data/interfaces/Paranet.json b/dkg/data/interfaces/Paranet.json index ba21816..04ce899 100644 --- a/dkg/data/interfaces/Paranet.json +++ b/dkg/data/interfaces/Paranet.json @@ -13,12 +13,12 @@ { "inputs": [ { - "internalType": "enum ParanetStructs.MinersAccessPolicy[]", + "internalType": "enum ParanetLib.MinersAccessPolicy[]", "name": "expectedAccessPolicies", "type": "uint8[]" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "actualAccessPolicy", "type": "uint8" } @@ -29,12 +29,12 @@ { "inputs": [ { - "internalType": "enum ParanetStructs.NodesAccessPolicy[]", + "internalType": "enum ParanetLib.NodesAccessPolicy[]", "name": "expectedAccessPolicies", "type": "uint8[]" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "actualAccessPolicy", "type": "uint8" } @@ -42,27 +42,6 @@ "name": "InvalidParanetNodesAccessPolicy", "type": "error" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKnowledgeAssetStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetTokenId", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "paranetId", - "type": "bytes32" - } - ], - "name": "KnowledgeAssetIsAPartOfOtherParanet", - "type": "error" - }, { "inputs": [ { @@ -92,7 +71,7 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -193,7 +172,7 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -292,6 +271,22 @@ "name": "ProfileDoesntExist", "type": "error" }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -602,7 +597,7 @@ } ], "indexed": false, - "internalType": "struct ParanetStructs.IncentivesPool", + "internalType": "struct ParanetLib.IncentivesPool", "name": "incentivesPool", "type": "tuple" } @@ -670,19 +665,19 @@ }, { "indexed": false, - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { "indexed": false, - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" }, { "indexed": false, - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "knowledgeAssetsAccessPolicy", "type": "uint8" } @@ -866,7 +861,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.UniversalAssetLocator[]", + "internalType": "struct ParanetLib.UniversalAssetLocator[]", "name": "services", "type": "tuple[]" } @@ -922,51 +917,12 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "contentAsset", - "outputs": [ - { - "internalType": "contract ContentAssetV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "contentAssetStorage", - "outputs": [ - { - "internalType": "contract ContentAssetStorageV2", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hashingProxy", - "outputs": [ - { - "internalType": "contract HashingProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [], "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } @@ -994,77 +950,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKAStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "components": [ - { - "internalType": "bytes32", - "name": "assertionId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "size", - "type": "uint128" - }, - { - "internalType": "uint32", - "name": "triplesNumber", - "type": "uint32" - }, - { - "internalType": "uint96", - "name": "chunksNumber", - "type": "uint96" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "bool", - "name": "immutable_", - "type": "bool" - } - ], - "internalType": "struct ContentAssetStructs.AssetInputArgs", - "name": "knowledgeAssetArgs", - "type": "tuple" - } - ], - "name": "mintKnowledgeAsset", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "name", @@ -1130,34 +1015,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKAStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "start", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "end", - "type": "uint256" - } - ], - "name": "processUpdatedKnowledgeAssetStatesMetadata", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [], "name": "profileStorage", @@ -1194,12 +1051,12 @@ "type": "string" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" } @@ -1382,19 +1239,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [], - "name": "serviceAgreementStorageProxy", - "outputs": [ - { - "internalType": "contract ServiceAgreementStorageProxy", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { @@ -1421,34 +1265,6 @@ "stateMutability": "view", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "paranetKAStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "paranetKATokenId", - "type": "uint256" - }, - { - "internalType": "address", - "name": "knowledgeAssetStorageContract", - "type": "address" - }, - { - "internalType": "uint256", - "name": "knowledgeAssetTokenId", - "type": "uint256" - } - ], - "name": "submitKnowledgeAsset", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { diff --git a/dkg/data/interfaces/ParanetIncentivesPoolFactory.json b/dkg/data/interfaces/ParanetIncentivesPoolFactory.json index c276757..774b229 100644 --- a/dkg/data/interfaces/ParanetIncentivesPoolFactory.json +++ b/dkg/data/interfaces/ParanetIncentivesPoolFactory.json @@ -36,6 +36,22 @@ "name": "ParanetIncentivesPoolAlreadyExists", "type": "error" }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -65,7 +81,7 @@ } ], "indexed": false, - "internalType": "struct ParanetStructs.IncentivesPool", + "internalType": "struct ParanetLib.IncentivesPool", "name": "incentivesPool", "type": "tuple" } @@ -117,7 +133,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } diff --git a/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json b/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json index e725892..f78c7e5 100644 --- a/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json +++ b/dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json @@ -10,6 +10,22 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "inputs": [ { @@ -288,7 +304,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.KnowledgeMinerMetadata", + "internalType": "struct ParanetLib.KnowledgeMinerMetadata", "name": "", "type": "tuple" } @@ -464,7 +480,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetStructs.UpdatingKnowledgeAssetState[]", + "internalType": "struct ParanetLib.UpdatingKnowledgeAssetState[]", "name": "", "type": "tuple[]" } @@ -510,7 +526,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetStructs.UpdatingKnowledgeAssetState[]", + "internalType": "struct ParanetLib.UpdatingKnowledgeAssetState[]", "name": "", "type": "tuple[]" } @@ -523,7 +539,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } diff --git a/dkg/data/interfaces/ParanetNeurowebIncentivesPool.json b/dkg/data/interfaces/ParanetNeuroIncentivesPool.json similarity index 97% rename from dkg/data/interfaces/ParanetNeurowebIncentivesPool.json rename to dkg/data/interfaces/ParanetNeuroIncentivesPool.json index 288bf3e..1677d83 100644 --- a/dkg/data/interfaces/ParanetNeurowebIncentivesPool.json +++ b/dkg/data/interfaces/ParanetNeuroIncentivesPool.json @@ -212,7 +212,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetStructs.ParanetIncentivizationProposalVoterInput[]", + "internalType": "struct ParanetLib.ParanetIncentivizationProposalVoterInput[]", "name": "voters_", "type": "tuple[]" } @@ -366,7 +366,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.ParanetIncentivesPoolClaimedRewardsProfile[]", + "internalType": "struct ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[]", "name": "", "type": "tuple[]" } @@ -391,7 +391,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.ParanetIncentivesPoolClaimedRewardsProfile[]", + "internalType": "struct ParanetLib.ParanetIncentivesPoolClaimedRewardsProfile[]", "name": "", "type": "tuple[]" } @@ -518,7 +518,7 @@ "type": "bool" } ], - "internalType": "struct ParanetStructs.NeuroEmissionMultiplier[]", + "internalType": "struct ParanetLib.NeuroEmissionMultiplier[]", "name": "", "type": "tuple[]" } @@ -619,7 +619,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.ParanetIncentivizationProposalVoter", + "internalType": "struct ParanetLib.ParanetIncentivizationProposalVoter", "name": "", "type": "tuple" } @@ -649,7 +649,7 @@ "type": "uint256" } ], - "internalType": "struct ParanetStructs.ParanetIncentivizationProposalVoter[]", + "internalType": "struct ParanetLib.ParanetIncentivizationProposalVoter[]", "name": "", "type": "tuple[]" } @@ -675,7 +675,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } diff --git a/dkg/data/interfaces/ParanetsRegistry.json b/dkg/data/interfaces/ParanetsRegistry.json index 4810d44..438a9fb 100644 --- a/dkg/data/interfaces/ParanetsRegistry.json +++ b/dkg/data/interfaces/ParanetsRegistry.json @@ -10,6 +10,76 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AddressAlreadyInSet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + } + ], + "name": "AddressDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ContractAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "name", + "type": "string" + } + ], + "name": "ContractDoesNotExist", + "type": "error" + }, + { + "inputs": [], + "name": "EmptyName", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, { "inputs": [ { @@ -100,7 +170,7 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -123,7 +193,7 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -187,7 +257,7 @@ "type": "address" } ], - "internalType": "struct UnorderedNamedContractDynamicSetStructs.Contract[]", + "internalType": "struct UnorderedNamedContractDynamicSet.Contract[]", "name": "", "type": "tuple[]" } @@ -237,7 +307,7 @@ "type": "bytes" } ], - "internalType": "struct ParanetStructs.Node[]", + "internalType": "struct ParanetLib.Node[]", "name": "", "type": "tuple[]" } @@ -337,7 +407,7 @@ "name": "getKnowledgeAssetsAccessPolicy", "outputs": [ { - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "", "type": "uint8" } @@ -460,12 +530,12 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest", + "internalType": "struct ParanetLib.ParanetKnowledgeMinerAccessRequest", "name": "", "type": "tuple" } @@ -506,12 +576,12 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest[]", + "internalType": "struct ParanetLib.ParanetKnowledgeMinerAccessRequest[]", "name": "", "type": "tuple[]" } @@ -614,12 +684,12 @@ "type": "address" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetKnowledgeMinerAccessRequest", + "internalType": "struct ParanetLib.ParanetKnowledgeMinerAccessRequest", "name": "", "type": "tuple" } @@ -660,12 +730,12 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetNodeJoinRequest", + "internalType": "struct ParanetLib.ParanetNodeJoinRequest", "name": "", "type": "tuple" } @@ -684,7 +754,7 @@ "name": "getMinersAccessPolicy", "outputs": [ { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "", "type": "uint8" } @@ -749,12 +819,12 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetNodeJoinRequest", + "internalType": "struct ParanetLib.ParanetNodeJoinRequest", "name": "", "type": "tuple" } @@ -795,12 +865,12 @@ "type": "uint72" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } ], - "internalType": "struct ParanetStructs.ParanetNodeJoinRequest[]", + "internalType": "struct ParanetLib.ParanetNodeJoinRequest[]", "name": "", "type": "tuple[]" } @@ -843,7 +913,7 @@ "name": "getNodesAccessPolicy", "outputs": [ { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "", "type": "uint8" } @@ -908,17 +978,17 @@ "type": "string" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "knowledgeAssetsAccessPolicy", "type": "uint8" }, @@ -928,7 +998,7 @@ "type": "uint96" } ], - "internalType": "struct ParanetStructs.ParanetMetadata", + "internalType": "struct ParanetLib.ParanetMetadata", "name": "", "type": "tuple" } @@ -1027,7 +1097,7 @@ "name": "hub", "outputs": [ { - "internalType": "contract HubV2", + "internalType": "contract Hub", "name": "", "type": "address" } @@ -1186,17 +1256,17 @@ "type": "string" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" }, { - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "knowledgeAssetsAccessPolicy", "type": "uint8" } @@ -1433,7 +1503,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetStructs.KnowledgeAssetsAccessPolicy", + "internalType": "enum ParanetLib.KnowledgeAssetsAccessPolicy", "name": "knowledgeAssetsAccessPolicy", "type": "uint8" } @@ -1451,7 +1521,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetStructs.MinersAccessPolicy", + "internalType": "enum ParanetLib.MinersAccessPolicy", "name": "minersAccessPolicy", "type": "uint8" } @@ -1487,7 +1557,7 @@ "type": "bytes32" }, { - "internalType": "enum ParanetStructs.NodesAccessPolicy", + "internalType": "enum ParanetLib.NodesAccessPolicy", "name": "nodesAccessPolicy", "type": "uint8" } @@ -1556,7 +1626,7 @@ "type": "uint256" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } @@ -1584,7 +1654,7 @@ "type": "uint256" }, { - "internalType": "enum ParanetStructs.RequestStatus", + "internalType": "enum ParanetLib.RequestStatus", "name": "status", "type": "uint8" } diff --git a/dkg/data/interfaces/ServiceAgreementStorageProxy.json b/dkg/data/interfaces/ServiceAgreementStorageProxy.json deleted file mode 100644 index 342afe4..0000000 --- a/dkg/data/interfaces/ServiceAgreementStorageProxy.json +++ /dev/null @@ -1,1314 +0,0 @@ -[ - { - "inputs": [ - { - "internalType": "address", - "name": "hubAddress", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "agreementV1Exists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "agreementV1StorageAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "agreementV1U1Exists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "agreementV1U1StorageAddress", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "commitSubmissionExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "commitV1Exists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "commitV1U1Exists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "prevIdentityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "nextIdentityId", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "score", - "type": "uint40" - } - ], - "name": "createV1CommitSubmissionObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint128", - "name": "epochLength", - "type": "uint128" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "proofWindowOffsetPerc", - "type": "uint8" - } - ], - "name": "createV1ServiceAgreementObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "prevIdentityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "nextIdentityId", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "score", - "type": "uint40" - } - ], - "name": "createV1U1CommitSubmissionObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint128", - "name": "epochLength", - "type": "uint128" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - }, - { - "internalType": "uint8", - "name": "scoreFunctionId", - "type": "uint8" - }, - { - "internalType": "uint8", - "name": "proofWindowOffsetPerc", - "type": "uint8" - } - ], - "name": "createV1U1ServiceAgreementObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "decrementAgreementRewardedNodesNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - } - ], - "name": "decrementCommitsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "deleteAgreementRewardedNodesNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "deleteCommitSubmissionsObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - } - ], - "name": "deleteCommitsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "deleteServiceAgreementObject", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "deleteServiceAgreementV1Object", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "deleteServiceAgreementV1U1Object", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "stateId", - "type": "bytes32" - } - ], - "name": "deleteUpdateCommitsDeadline", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementData", - "outputs": [ - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - }, - { - "internalType": "uint128", - "name": "epochLength", - "type": "uint128" - }, - { - "internalType": "uint96[2]", - "name": "tokens", - "type": "uint96[2]" - }, - { - "internalType": "uint8[2]", - "name": "scoreFunctionIdAndProofWindowOffsetPerc", - "type": "uint8[2]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementEpochLength", - "outputs": [ - { - "internalType": "uint128", - "name": "", - "type": "uint128" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementEpochsNumber", - "outputs": [ - { - "internalType": "uint16", - "name": "", - "type": "uint16" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementProofWindowOffsetPerc", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "getAgreementRewardedNodesNumber", - "outputs": [ - { - "internalType": "uint32", - "name": "", - "type": "uint32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementScoreFunctionId", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementStartTime", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementTokenAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "getAgreementUpdateTokenAmount", - "outputs": [ - { - "internalType": "uint96", - "name": "", - "type": "uint96" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmission", - "outputs": [ - { - "components": [ - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "prevIdentityId", - "type": "uint72" - }, - { - "internalType": "uint72", - "name": "nextIdentityId", - "type": "uint72" - }, - { - "internalType": "uint40", - "name": "score", - "type": "uint40" - } - ], - "internalType": "struct ServiceAgreementStructsV1.CommitSubmission", - "name": "", - "type": "tuple" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmissionIdentityId", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmissionNextIdentityId", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmissionPrevIdentityId", - "outputs": [ - { - "internalType": "uint72", - "name": "", - "type": "uint72" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - } - ], - "name": "getCommitSubmissionScore", - "outputs": [ - { - "internalType": "uint40", - "name": "", - "type": "uint40" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - } - ], - "name": "getCommitsCount", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "stateId", - "type": "bytes32" - } - ], - "name": "getUpdateCommitsDeadline", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "getV1AgreementEpochSubmissionHead", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "stateIndex", - "type": "uint256" - } - ], - "name": "getV1U1AgreementEpochSubmissionHead", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "hub", - "outputs": [ - { - "internalType": "contract Hub", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - } - ], - "name": "incrementAgreementRewardedNodesNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - } - ], - "name": "incrementCommitsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "initialize", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "migrateV1ServiceAgreement", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "name", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - } - ], - "name": "serviceAgreementExists", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint128", - "name": "epochLength", - "type": "uint128" - } - ], - "name": "setAgreementEpochLength", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epochsNumber", - "type": "uint16" - } - ], - "name": "setAgreementEpochsNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "proofWindowOffsetPerc", - "type": "uint8" - } - ], - "name": "setAgreementProofWindowOffsetPerc", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - }, - { - "internalType": "uint32", - "name": "rewardedNodesNumber", - "type": "uint32" - } - ], - "name": "setAgreementRewardedNodesNumber", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "newScoreFunctionId", - "type": "uint8" - } - ], - "name": "setAgreementScoreFunctionId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "startTime", - "type": "uint256" - } - ], - "name": "setAgreementStartTime", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "setAgreementTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint96", - "name": "updateTokenAmount", - "type": "uint96" - } - ], - "name": "setAgreementUpdateTokenAmount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "identityId", - "type": "uint72" - } - ], - "name": "setCommitSubmissionIdentityId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "nextIdentityId", - "type": "uint72" - } - ], - "name": "setCommitSubmissionNextIdentityId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint72", - "name": "prevIdentityId", - "type": "uint72" - } - ], - "name": "setCommitSubmissionPrevIdentityId", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "commitId", - "type": "bytes32" - }, - { - "internalType": "uint40", - "name": "score", - "type": "uint40" - } - ], - "name": "setCommitSubmissionScore", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "epochStateId", - "type": "bytes32" - }, - { - "internalType": "uint8", - "name": "epochStateCommitsCount", - "type": "uint8" - } - ], - "name": "setCommitsCount", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "stateId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "deadline", - "type": "uint256" - } - ], - "name": "setUpdateCommitsDeadline", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - }, - { - "internalType": "bytes32", - "name": "headCommitId", - "type": "bytes32" - } - ], - "name": "setV1AgreementEpochSubmissionHead", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "uint16", - "name": "epoch", - "type": "uint16" - }, - { - "internalType": "uint256", - "name": "stateIndex", - "type": "uint256" - }, - { - "internalType": "bytes32", - "name": "headCommitId", - "type": "bytes32" - } - ], - "name": "setV1U1AgreementEpochSubmissionHead", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "storageV1", - "outputs": [ - { - "internalType": "contract ServiceAgreementStorageV1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "storageV1U1", - "outputs": [ - { - "internalType": "contract ServiceAgreementStorageV1U1", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "agreementId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "transferAgreementTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "transferV1AgreementTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "receiver", - "type": "address" - }, - { - "internalType": "uint96", - "name": "tokenAmount", - "type": "uint96" - } - ], - "name": "transferV1U1AgreementTokens", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "pure", - "type": "function" - } -] diff --git a/dkg/data/interfaces/Token.json b/dkg/data/interfaces/Token.json index 8a5ce2b..c722726 100644 --- a/dkg/data/interfaces/Token.json +++ b/dkg/data/interfaces/Token.json @@ -15,6 +15,135 @@ "stateMutability": "nonpayable", "type": "constructor" }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "needed", + "type": "uint256" + } + ], + "name": "ERC20InsufficientBalance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "approver", + "type": "address" + } + ], + "name": "ERC20InvalidApprover", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "receiver", + "type": "address" + } + ], + "name": "ERC20InvalidReceiver", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "ERC20InvalidSender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "ERC20InvalidSpender", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, { "anonymous": false, "inputs": [ @@ -218,7 +347,7 @@ }, { "internalType": "uint256", - "name": "amount", + "name": "value", "type": "uint256" } ], @@ -326,6 +455,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -434,7 +576,7 @@ }, { "internalType": "address", - "name": "account", + "name": "callerConfirmation", "type": "address" } ], @@ -461,19 +603,6 @@ "stateMutability": "nonpayable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "minter", - "type": "address" - } - ], - "name": "setupRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, { "inputs": [ { @@ -528,7 +657,7 @@ }, { "internalType": "uint256", - "name": "amount", + "name": "value", "type": "uint256" } ], @@ -557,7 +686,7 @@ }, { "internalType": "uint256", - "name": "amount", + "name": "value", "type": "uint256" } ], diff --git a/dkg/providers/blockchain.py b/dkg/providers/blockchain.py index 96b2603..321b5f1 100644 --- a/dkg/providers/blockchain.py +++ b/dkg/providers/blockchain.py @@ -260,11 +260,14 @@ def _update_contract_instance(self, contract: str) -> bool: ): self.contracts[contract] = self.w3.eth.contract( address=( - self.contracts["Hub"].functions.getContractAddress(contract).call() - if not contract.endswith("AssetStorage") - else self.contracts["Hub"] + self.contracts["Hub"] .functions.getAssetStorageAddress(contract) .call() + if contract.endswith("AssetStorage") + or contract.endswith("CollectionStorage") + else self.contracts["Hub"] + .functions.getContractAddress(contract) + .call() ), abi=self.abi[contract], decode_tuples=True, diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index 9ec37a0..fc5b379 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -67,6 +67,12 @@ class BlockchainRequest: args={"assetStorageName": str}, ) + key_is_operational_wallet = ContractCall( + contract="IdentityStorage", + function="keyHasPurpose", + args={"identityId": int, "_key": Address, "_purpose": int}, + ) + allowance = ContractCall( contract="Token", function="allowance", diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index d7faac4..340c650 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -61,12 +61,11 @@ class NodeRequest: method=HTTPRequestMethod.POST, path="publish", data={ - "assertionId": str, - "assertion": NQuads, + "datasetRoot": str, + "dataset": dict[str, list[str]], "blockchain": str, - "contract": Address, - "tokenId": int, "hashFunctionId": int, + "minimumNumberOfNodeReplications": int, }, ) get = NodeCall( @@ -77,7 +76,12 @@ class NodeRequest: query = NodeCall( method=HTTPRequestMethod.POST, path="query", - data={"query": str, "type": str, "repository": str | None, "paranet_ual": str | None}, + data={ + "query": str, + "type": str, + "repository": str | None, + "paranet_ual": str | None, + }, ) diff --git a/dkg/utils/rdf.py b/dkg/utils/rdf.py index 409a61d..06eced2 100644 --- a/dkg/utils/rdf.py +++ b/dkg/utils/rdf.py @@ -17,20 +17,30 @@ from typing import Literal -from dkg.constants import PRIVATE_ASSERTION_PREDICATE +from rdflib.plugins.parsers.nquads import NQuadsParser +from io import StringIO + +from dkg.constants import CHUNK_BYTE_SIZE, PRIVATE_ASSERTION_PREDICATE from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset from dkg.types import JSONLD, HexStr, NQuads from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes from pyld import jsonld +from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM +from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral +from uuid import uuid4 +from web3 import Web3 +import math def normalize_dataset( dataset: JSONLD | NQuads, input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + output_format=DEFAULT_RDF_FORMAT, + algorithm=DEFAULT_CANON_ALGORITHM, ) -> NQuads: normalization_options = { - "algorithm": "URDNA2015", - "format": "application/n-quads", + "algorithm": algorithm, + "format": output_format, } match input_format.lower(): @@ -79,3 +89,188 @@ def format_content( "public": public_assertion, "private": private_assertion if content.get("private", None) else {}, } + + +def is_empty_dict(dictionary: dict): + return len(dictionary.keys()) == 0 and isinstance(dictionary, dict) + + +def format_dataset( + content: dict, + input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + output_format=DEFAULT_RDF_FORMAT, + algorithm=DEFAULT_CANON_ALGORITHM, +): + private_assertion = None + if content.get("private") and not is_empty_dict(content.get("private")): + private_assertion = normalize_dataset( + content.get("private"), input_format, output_format, algorithm + ) + elif not content.get("public"): + content = {"public": content} + + public_assertion = [] + if content.get("public"): + public_assertion = normalize_dataset( + content.get("public"), input_format, output_format, algorithm + ) + + if ( + public_assertion + and len(public_assertion) == 0 + and private_assertion + and len(private_assertion) == 0 + ): + raise ValueError("File format is corrupted, no n-quads are extracted.") + + dataset = {"public": public_assertion} + if private_assertion: + dataset["private"] = private_assertion + + return dataset + + +def generate_missing_ids_for_blank_nodes(nquads_list: list[str]) -> list[str]: + generated_ids = {} + + def replace_blank_node(term): + # Handle blank nodes + if isinstance(term, BNode): + if str(term) not in generated_ids: + generated_ids[str(term)] = URIRef(f"uuid:{str(uuid4())}") + return generated_ids[str(term)] + + # Handle nested quads (RDF-star) + if hasattr(term, "subject"): # Check if term is a quad + return Graph().quad( + replace_blank_node(term.subject), + replace_blank_node(term.predicate), + replace_blank_node(term.object), + ) + + return term # Return IRIs or Literals unchanged + + # Create a graph and parse the N-Quads + g = Graph() + g.parse(data="".join(nquads_list)) + + # Create new graph for updated quads + updated_graph = Graph() + + # Process each quad and replace blank nodes + for quad in g: + updated_quad = ( + replace_blank_node(quad[0]), # subject + replace_blank_node(quad[1]), # predicate + replace_blank_node(quad[2]), # object + ) + updated_graph.add(updated_quad) + + # Serialize back to N-Quads format and split into lines + result = updated_graph.serialize(format="nquads").strip().split("\n") + return [line for line in result if line] # Remove empty + + +def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): + grouped = {} + + # Process each quad in original order + for nquad in nquads_list: + if not nquad.strip(): # Skip empty lines + continue + + # Parse single quad + g = Graph() + g.parse(data=nquad, format="nquads") + quad = next(iter(g)) + subject, predicate, obj = quad + + # Get subject key + subject_key = ( + f"<<<{subject.subject}> <{subject.predicate}> <{subject.object}>>" + if hasattr(subject, "subject") + else f"<{subject}>" + ) + + # Initialize group if needed + if subject_key not in grouped: + grouped[subject_key] = [] + + # Format object + object_value = f'"{obj}"' if isinstance(obj, RDFLiteral) else f"<{obj}>" + + # Add quad to group + quad_string = f"{subject_key} <{predicate}> {object_value} ." + grouped[subject_key].append(quad_string) + + # Return grouped quads (sorted if requested) + grouped_items = sorted(grouped.items()) if sort else grouped.items() + return [quads for _, quads in grouped_items] + + +def split_into_chunks(quads, chunk_size_bytes=32): + # Concatenate the quads with newline characters + concatenated_quads = "\n".join(quads) + + # Encode the concatenated string to bytes + encoded_bytes = concatenated_quads.encode("utf-8") + + # Split the encoded bytes into chunks + chunks = [] + start = 0 + + while start < len(encoded_bytes): + end = min(start + chunk_size_bytes, len(encoded_bytes)) + chunk = encoded_bytes[start:end] + chunks.append(chunk.decode("utf-8")) # Decode bytes back to string + start = end + + return chunks + + +def calculate_merkle_root(quads: list[str], chunk_size_bytes: int = CHUNK_BYTE_SIZE): + chunks = split_into_chunks(quads, chunk_size_bytes) + + # Create leaves using solidityKeccak256 equivalent + leaves = [ + bytes.fromhex(Web3.solidity_keccak(["string", "uint256"], [chunk, index]).hex()) + for index, chunk in enumerate(chunks) + ] + + while len(leaves) > 1: + next_level = [] + + for i in range(0, len(leaves), 2): + left = leaves[i] + + if i + 1 >= len(leaves): + next_level.append(left) + break + + right = leaves[i + 1] + + # Combine and sort the leaves + combined = [left, right] + combined.sort() + + # Calculate the hash of the combined leaves + hash_value = Web3.keccak(b"".join(combined)) + next_level.append(hash_value) + + leaves = next_level + + return f"0x{leaves[0].hex()}" + + +def generate_named_node(): + return f"uuid:{uuid4()}" + + +def calculate_number_of_chunks(quads, chunk_size_bytes=CHUNK_BYTE_SIZE): + # Concatenate the quads with newline characters + concatenated_quads = "\n".join(quads) + + total_size_bytes = len(concatenated_quads.encode("utf-8")) + + # Calculate and return the number of chunks + return math.ceil(total_size_bytes / chunk_size_bytes) diff --git a/examples/demo.py b/examples/demo.py index d3679e0..9bddbf9 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -23,7 +23,7 @@ node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") blockchain_provider = BlockchainProvider( "development", - "hardhat2:31337", + "hardhat1:31337", private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ) @@ -41,18 +41,17 @@ def print_json(json_dict: dict): content = { - "public": { - "@context": ["http://schema.org"], - "@id": "uuid:1", - "company": "OT", - "user": {"@id": "uuid:user:1"}, - "city": {"@id": "uuid:belgrade"}, - }, "private": { - "@context": ["http://schema.org"], - "@graph": [ - {"@id": "uuid:user:1", "name": "Adam", "lastname": "Smith"}, - {"@id": "uuid:belgrade", "title": "Belgrade", "postCode": "11000"}, + "@context": "https://www.schema.org", + "@id": "urn:eu-pp:safety-test:3oRIwPtUOJapwNSAGZTzCOWR9bEo", + "@type": "ProductSafetyTest", + "testType": "Functional Safety Test", + "testResults": "Fail", + "relatedProduct": [ + { + "@id": "urn:epc:id:sgtin:59G1yu8uivSRKLLu", + "name": "59G1yu8uivSRKLLu", + }, ], }, } @@ -129,12 +128,12 @@ def print_json(json_dict: dict): # print("======================== SET ALLOWANCE") # print(allowance_set) -# divider() +divider() -# create_asset_result = dkg.asset.create(content, 2) -# print("======================== ASSET CREATED") -# print_json(create_asset_result) -# divider() +create_asset_result = dkg.asset.create(content, 2, 3, 1, "100") +print("======================== ASSET CREATED") +print_json(create_asset_result) +divider() # validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) # print("======================== VALIDATE UAL") From 7ddcc6c47bf1116a42cfe9bf5042ca239023934c Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Mon, 6 Jan 2025 14:34:40 +0100 Subject: [PATCH 04/31] implemented v8 get --- dkg/asset.py | 195 +++++++++++++++++++++++++++++++++++--- dkg/constants.py | 22 +++++ dkg/utils/node_request.py | 9 +- examples/demo.py | 191 +++++++++++++++++++------------------ 4 files changed, 308 insertions(+), 109 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index cc56961..35791a4 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -32,6 +32,7 @@ PRIVATE_ASSERTION_PREDICATE, PRIVATE_CURRENT_REPOSITORY, PRIVATE_HISTORICAL_REPOSITORY, + DEFAULT_PARAMETERS, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -360,7 +361,6 @@ def create( } return result - def local_store( self, @@ -489,7 +489,6 @@ def local_store( return result - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) def submit_to_paranet( @@ -563,6 +562,122 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: _get = Method(NodeRequest.get) _query = Method(NodeRequest.query) + def get_v8(self, ual: UAL) -> dict: + get_public_operation_id: NodeResponseDict = self._get( + ual, + DEFAULT_PARAMETERS["CONTENT_TYPE"], + DEFAULT_PARAMETERS["INCLUDE_METADATA"], + DEFAULT_PARAMETERS["HASH_FUNCTION_ID"], + DEFAULT_PARAMETERS["PARANET_UAL"], + DEFAULT_PARAMETERS["GET_SUBJECT_UAL"], + )["operationId"] + + get_public_operation_result = self.get_operation_result( + get_public_operation_id, + "get", + DEFAULT_PARAMETERS["MAX_NUMBER_OF_RETRIES"], + ) + + def get_operation_status_object(self, operation_result, operation_id): + + if "errorType" in operation_result.get("data", {}): + + operation_data = { + "status": operation_result["status"], + **operation_result["data"], + } + else: + + operation_data = {"status": operation_result["status"]} + + return {"operationId": operation_id, **operation_data} + + if DEFAULT_PARAMETERS["GET_SUBJECT_UAL"]: + if get_public_operation_result["data"]: + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + "subjectUALPairs": get_public_operation_result["data"], + } + if get_public_operation_result["status"] != "FAILED": + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to find assertion on the network!", + } + get_public_operation_result["status"] = "FAILED" + + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + metadata = get_public_operation_result["data"] + assertion = get_public_operation_result["data"].get("assertion", None) + + if not assertion: + if get_public_operation_result["status"] != "FAILED": + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Unable to find assertion on the network!", + } + get_public_operation_result["status"] = "FAILED" + + return { + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + + if DEFAULT_PARAMETERS["GET_SUBJECT_UAL"]: + is_valid = True # #TODO: Implement assertion validation logic + if not is_valid: + get_public_operation_result["data"] = { + "errorType": "DKG_CLIENT_ERROR", + "errorMessage": "Calculated root hashes don't match!", + } + + formatted_assertion = "\n".join( + assertion.get("public", []) + assertion.get("private", []) + ) + + formatted_metadata = None + if DEFAULT_PARAMETERS["OUTPUT_FORMAT"] == "JSON-LD": + formatted_assertion = self.to_jsonld(formatted_assertion) + + if DEFAULT_PARAMETERS["INCLUDE_METADATA"]: + print("USAO") + formatted_metadata = self.to_jsonld("\n".join(metadata)) + + if DEFAULT_PARAMETERS["OUTPUT_FORMAT"] == "N-QUADS": + formatted_assertion = self.to_nquads( + formatted_assertion, "application/n-quads" + ) + if DEFAULT_PARAMETERS["INCLUDE_METADATA"]: + formatted_metadata = self.to_nquads( + "\n".join(metadata), "application/n-quads" + ) + + result = { + "assertion": formatted_assertion, + "operation": { + "get": self.get_operation_status_object( + get_public_operation_result, get_public_operation_id + ), + }, + } + + if DEFAULT_PARAMETERS["INCLUDE_METADATA"] and metadata: + result["metadata"] = formatted_metadata + + return result + def get( self, ual: UAL, @@ -587,7 +702,10 @@ def handle_latest_finalized_state(token_id: int) -> tuple[HexStr, bool]: is_state_finalized = False match state: - case KnowledgeAssetEnumStates.LATEST | KnowledgeAssetEnumStates.LATEST_FINALIZED: + case ( + KnowledgeAssetEnumStates.LATEST + | KnowledgeAssetEnumStates.LATEST_FINALIZED + ): public_assertion_id, is_state_finalized = handle_latest_finalized_state( token_id ) @@ -716,9 +834,11 @@ def handle_latest_finalized_state(token_id: int) -> tuple[HexStr, bool]: query_private_operation_id = self._query( query, "CONSTRUCT", - PRIVATE_CURRENT_REPOSITORY - if is_state_finalized - else PRIVATE_HISTORICAL_REPOSITORY, + ( + PRIVATE_CURRENT_REPOSITORY + if is_state_finalized + else PRIVATE_HISTORICAL_REPOSITORY + ), )["operationId"] query_private_operation_result = self.get_operation_result( @@ -898,15 +1018,62 @@ def get_agreement_id(self, contract_address: Address, token_id: int) -> HexStr: _get_operation_result = Method(NodeRequest.get_operation_result) - @retry(catch=OperationNotFinished, max_retries=5, base_delay=1, backoff=2) def get_operation_result( - self, operation_id: str, operation: str - ) -> NodeResponseDict: - operation_result = self._get_operation_result( - operation_id=operation_id, - operation=operation, + self, operation_id: str, operation: str, max_retries: int = 5 + ): + @retry( + catch=OperationNotFinished, max_retries=max_retries, base_delay=1, backoff=2 ) + def _get_opeation_results_(): + operation_result = self._get_operation_result( + operation_id=operation_id, + operation=operation, + ) + print(operation_result) + validate_operation_status(operation_result) - validate_operation_status(operation_result) + return operation_result - return operation_result + return _get_opeation_results_() + + def to_jsonld(self, nquads: str): + options = { + "algorithm": "URDNA2015", + "format": "application/n-quads", + } + + return jsonld.from_rdf(nquads, options) + + def to_nquads(self, content, input_format): + options = { + "algorithm": "URDNA2015", + "format": "application/n-quads", + } + + if input_format: + options["inputFormat"] = input_format + try: + + jsonld_data = jsonld.from_rdf(content, options) + canonized = jsonld.to_rdf(jsonld_data, options) + + if isinstance(canonized, str): + return [line for line in canonized.split("\n") if line.strip()] + + except Exception as e: + raise ValueError(f"Error processing content: {e}") + + def get_operation_status_object(self, operation_result, operation_id): + + if operation_result.get("data", {}).get("errorType"): + operation_data = { + "status": operation_result["status"], + **operation_result["data"], + } + else: + operation_data = {"status": operation_result["status"]} + + return { + "operationId": operation_id, + **operation_data, + } diff --git a/dkg/constants.py b/dkg/constants.py index cf50cea..b5b47bd 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -67,3 +67,25 @@ PRIVATE_HISTORICAL_REPOSITORY = "privateHistory" PRIVATE_CURRENT_REPOSITORY = "privateCurrent" + +DEFAULT_PARAMETERS = { + "ENVIRONMENT": "mainnet", + "PORT": 8900, + "FREQUENCY": 5, + "MAX_NUMBER_OF_RETRIES": 5, + "HASH_FUNCTION_ID": 1, + "IMMUTABLE": False, + "VALIDATE": True, + "OUTPUT_FORMAT": "JSON-LD", + "STATE": None, + "INCLUDE_METADATA": False, + "CONTENT_TYPE": "all", + "GRAPH_LOCATION": "LOCAL_KG", + "GRAPH_STATE": "CURRENT", + "HANDLE_NOT_MINED_ERROR": False, + "SIMULATE_TXS": False, + "FORCE_REPLACE_TXS": False, + "GAS_LIMIT_MULTIPLIER": 1, + "PARANET_UAL": None, + "GET_SUBJECT_UAL": False, +} diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 977dc8e..84c6a9a 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -72,7 +72,14 @@ class NodeRequest: get = NodeCall( method=HTTPRequestMethod.POST, path="get", - data={"id": UAL, "state": str, "hashFunctionId": int}, + data={ + "id": UAL, + "contentType": str, + "includeMetadata": bool, + "hashFunctionId": int, + "paranetUAL": UAL, + "subjectUAL": UAL, + }, ) query = NodeCall( method=HTTPRequestMethod.POST, diff --git a/examples/demo.py b/examples/demo.py index 071b216..2d521fd 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -20,11 +20,11 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider -node_provider = NodeHTTPProvider("http://localhost:8900") +node_provider = NodeHTTPProvider("https://v6-pegasus-node-04.origin-trail.network:8900") blockchain_provider = BlockchainProvider( - "development", - "hardhat2:31337", - private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", + "testnet", + "base:84532", + private_key="db20be6415f83a8a9f0c129bf20ab99ba15bfb90ac5e34f1848f59c20ea9c068", ) dkg = DKG(node_provider, blockchain_provider) @@ -58,125 +58,128 @@ def print_json(json_dict: dict): } -divider() +# divider() -info_result = dkg.node.info +# info_result = dkg.node.info -print("======================== NODE INFO RECEIVED") -print_json(info_result) +# print("======================== NODE INFO RECEIVED") +# print_json(info_result) divider() -formatted_assertions = dkg.assertion.format_graph(content) -print("======================== ASSET FORMATTED") -print_json(formatted_assertions) +# formatted_assertions = dkg.assertion.format_graph(content) +# print("======================== ASSET FORMATTED") +# print_json(formatted_assertions) -divider() +# divider() -public_assertion_id = dkg.assertion.get_public_assertion_id(content) -print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") -print(public_assertion_id) +# public_assertion_id = dkg.assertion.get_public_assertion_id(content) +# print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") +# print(public_assertion_id) -divider() +# divider() -public_assertion_size = dkg.assertion.get_size(content) -print("======================== PUBLIC ASSERTION SIZE CALCULATED") -print(public_assertion_size) +# public_assertion_size = dkg.assertion.get_size(content) +# print("======================== PUBLIC ASSERTION SIZE CALCULATED") +# print(public_assertion_size) -divider() +# divider() -public_assertion_triples_number = dkg.assertion.get_triples_number(content) -print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") -print(public_assertion_triples_number) +# public_assertion_triples_number = dkg.assertion.get_triples_number(content) +# print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") +# print(public_assertion_triples_number) -divider() +# divider() -public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) -print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") -print(public_assertion_chunks_number) +# public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) +# print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") +# print(public_assertion_chunks_number) -divider() +# divider() -bid_suggestion = dkg.network.get_bid_suggestion( - public_assertion_id, - public_assertion_size, - 2, -) -print("======================== BID SUGGESTION CALCULATED") -print(bid_suggestion) +# bid_suggestion = dkg.network.get_bid_suggestion( +# public_assertion_id, +# public_assertion_size, +# 2, +# ) +# print("======================== BID SUGGESTION CALCULATED") +# print(bid_suggestion) -divider() - -current_allowance = dkg.asset.get_current_allowance() -print("======================== GET CURRENT ALLOWANCE") -print(current_allowance) - -divider() +# divider() -allowance_increase = dkg.asset.increase_allowance(bid_suggestion) -print("======================== INCREASE ALLOWANCE") -print(allowance_increase) +# current_allowance = dkg.asset.get_current_allowance() +# print("======================== GET CURRENT ALLOWANCE") +# print(current_allowance) -divider() +# divider() -allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) -print("======================== DECREASE ALLOWANCE") -print(allowance_decrease) +# allowance_increase = dkg.asset.increase_allowance(bid_suggestion) +# print("======================== INCREASE ALLOWANCE") +# print(allowance_increase) -divider() +# divider() -allowance_set = dkg.asset.set_allowance(bid_suggestion) -print("======================== SET ALLOWANCE") -print(allowance_set) +# allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) +# print("======================== DECREASE ALLOWANCE") +# print(allowance_decrease) -divider() +# divider() -create_asset_result = dkg.asset.create(content, 2) -print("======================== ASSET CREATED") -print_json(create_asset_result) -divider() +# allowance_set = dkg.asset.set_allowance(bid_suggestion) +# print("======================== SET ALLOWANCE") +# print(allowance_set) -validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) -print("======================== VALIDATE UAL") -print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") -divider() +# divider() -owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) -print("======================== GET ASSET OWNER") -print(owner_result) -divider() +# create_asset_result = dkg.asset.create(content, 2) +# print("======================== ASSET CREATED") +# print_json(create_asset_result) +# divider() -get_asset_result = dkg.asset.get(create_asset_result["UAL"]) -print("======================== ASSET RESOLVED") -print_json(get_asset_result) -divider() +# validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) +# print("======================== VALIDATE UAL") +# print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") +# divider() -get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") -print("======================== ASSET LATEST RESOLVED") -print_json(get_latest_asset_result) -divider() +# owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) +# print("======================== GET ASSET OWNER") +# print(owner_result) +# divider() -get_latest_finalized_asset_result = dkg.asset.get( - create_asset_result["UAL"], "latest_finalized", "all" -) -print("======================== ASSET LATEST FINALIZED RESOLVED") -print_json(get_latest_finalized_asset_result) -divider() +# get_asset_result = dkg.asset.get(create_asset_result["UAL"]) +# print("======================== ASSET RESOLVED") +# print_json(get_asset_result) +# divider() -get_first_state_by_index = dkg.asset.get(create_asset_result["UAL"], 0, "all") -print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") -print_json(get_first_state_by_index) -divider() +# get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") +# print("======================== ASSET LATEST RESOLVED") +# print_json(get_latest_asset_result) +# divider() -get_first_state_by_hash = dkg.asset.get( - create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" -) -print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") -print_json(get_first_state_by_hash) -divider() +# get_latest_finalized_asset_result = dkg.asset.get( +# create_asset_result["UAL"], "latest_finalized", "all" +# ) +# print("======================== ASSET LATEST FINALIZED RESOLVED") +# print_json(get_latest_finalized_asset_result) +# divider() -query_result = dkg.graph.query( - "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" +get_v8_test = dkg.asset.get_v8( + "did:dkg:base:84532/0xd5550173b0f7b8766ab2770e4ba86caf714a5af5/10176" ) -print("======================== QUERY LOCAL CURRENT RESULT") -print(query_result) +print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") +print(get_v8_test) +# print_json(get_v8_test) +divider() + +# get_first_state_by_hash = dkg.asset.get( +# create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" +# ) +# print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") +# print_json(get_first_state_by_hash) +# divider() + +# query_result = dkg.graph.query( +# "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" +# ) +# print("======================== QUERY LOCAL CURRENT RESULT") +# print(query_result) From 87657df982d2f3dc8defa27dbf9f1119f5abbd86 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:48:37 +0100 Subject: [PATCH 05/31] Update abi --- dkg/data/interfaces/KnowledgeCollection.json | 610 +++++ .../KnowledgeCollectionStorage.json | 2312 +++++++++++++++++ 2 files changed, 2922 insertions(+) create mode 100644 dkg/data/interfaces/KnowledgeCollection.json create mode 100644 dkg/data/interfaces/KnowledgeCollectionStorage.json diff --git a/dkg/data/interfaces/KnowledgeCollection.json b/dkg/data/interfaces/KnowledgeCollection.json new file mode 100644 index 0000000..3eaeebf --- /dev/null +++ b/dkg/data/interfaces/KnowledgeCollection.json @@ -0,0 +1,610 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "CannotUpdateImmutableKnowledgeCollection", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "messageHash", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "vs", + "type": "bytes32" + } + ], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "expectedTokenAMount", + "type": "uint96" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + } + ], + "name": "InvalidTokenAmount", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "currentEpoch", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "endEpoch", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "requiredSignatures", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "receivedSignatures", + "type": "uint256" + } + ], + "name": "MinSignaturesRequirementNotMet", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "rAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "vsAmount", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "identityIdsAmount", + "type": "uint256" + } + ], + "name": "SignaturesSignersMismatch", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint72", + "name": "identityId", + "type": "uint72" + }, + { + "internalType": "address", + "name": "signer", + "type": "address" + } + ], + "name": "SignerIsNotNodeOperator", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "allowance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "TooLowAllowance", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "balance", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "expected", + "type": "uint256" + } + ], + "name": "TooLowBalance", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroTokenAmount", + "type": "error" + }, + { + "inputs": [], + "name": "askStorage", + "outputs": [ + { + "internalType": "contract AskStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "chronos", + "outputs": [ + { + "internalType": "contract Chronos", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "publishOperationId", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetsAmount", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "epochs", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "internalType": "uint72", + "name": "publisherNodeIdentityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "publisherNodeR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "publisherNodeVS", + "type": "bytes32" + }, + { + "internalType": "uint72[]", + "name": "identityIds", + "type": "uint72[]" + }, + { + "internalType": "bytes32[]", + "name": "r", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "vs", + "type": "bytes32[]" + } + ], + "name": "createKnowledgeCollection", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "epochStorage", + "outputs": [ + { + "internalType": "contract EpochStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint40", + "name": "epochs", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + } + ], + "name": "extendKnowledgeCollectionLifetime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "identityStorage", + "outputs": [ + { + "internalType": "contract IdentityStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + } + ], + "name": "increaseKnowledgeCollectionTokenAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "knowledgeCollectionStorage", + "outputs": [ + { + "internalType": "contract KnowledgeCollectionStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "parametersStorage", + "outputs": [ + { + "internalType": "contract ParametersStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "paymasterManager", + "outputs": [ + { + "internalType": "contract PaymasterManager", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "shardingTableStorage", + "outputs": [ + { + "internalType": "contract ShardingTableStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenContract", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "string", + "name": "updateOperationId", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "mintKnowledgeAssetsAmount", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "knowledgeAssetsToBurn", + "type": "uint256[]" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "address", + "name": "paymaster", + "type": "address" + }, + { + "internalType": "uint72", + "name": "publisherNodeIdentityId", + "type": "uint72" + }, + { + "internalType": "bytes32", + "name": "publisherNodeR", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "publisherNodeVS", + "type": "bytes32" + }, + { + "internalType": "uint72[]", + "name": "identityIds", + "type": "uint72[]" + }, + { + "internalType": "bytes32[]", + "name": "r", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "vs", + "type": "bytes32[]" + } + ], + "name": "updateKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + } +] diff --git a/dkg/data/interfaces/KnowledgeCollectionStorage.json b/dkg/data/interfaces/KnowledgeCollectionStorage.json new file mode 100644 index 0000000..7940b0f --- /dev/null +++ b/dkg/data/interfaces/KnowledgeCollectionStorage.json @@ -0,0 +1,2312 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_knowledgeCollectionMaxSize", + "type": "uint256" + }, + { + "internalType": "string", + "name": "uri", + "type": "string" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "ApprovalCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "BalanceQueryForZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "BurnFromNonOnwerAddress", + "type": "error" + }, + { + "inputs": [], + "name": "BurnFromZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "custodian", + "type": "address" + } + ], + "name": "CustodianHasNoOwners", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "custodian", + "type": "address" + } + ], + "name": "CustodianNotAContract", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "custodian", + "type": "address" + } + ], + "name": "CustodianWithoutOwnersFunction", + "type": "error" + }, + { + "inputs": [], + "name": "EtherTransferFailed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "minted", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "requested", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxSize", + "type": "uint256" + } + ], + "name": "ExceededKnowledgeCollectionMaxSize", + "type": "error" + }, + { + "inputs": [], + "name": "InputLengthMistmatch", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidQueryRange", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenContractAddress", + "type": "address" + } + ], + "name": "InvalidTokenContract", + "type": "error" + }, + { + "inputs": [], + "name": "MintToZeroAddress", + "type": "error" + }, + { + "inputs": [], + "name": "MintZeroQuantity", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "NotPartOfKnowledgeCollection", + "type": "error" + }, + { + "inputs": [], + "name": "TokenTransferFailed", + "type": "error" + }, + { + "inputs": [], + "name": "TransferCallerNotOwnerNorApproved", + "type": "error" + }, + { + "inputs": [], + "name": "TransferFromIncorrectOwnerOrInvalidAmount", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToNonERC1155ReceiverImplementer", + "type": "error" + }, + { + "inputs": [], + "name": "TransferToZeroAddress", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressCustodian", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "ApprovalForAll", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "KnowledgeAssetsBurned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endId", + "type": "uint256" + } + ], + "name": "KnowledgeAssetsMinted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "burned", + "type": "uint256[]" + } + ], + "name": "KnowledgeCollectionBurnedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "byteSize", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionByteSizeUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "chunksAmount", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionChunksAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "publishOperationId", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "indexed": false, + "internalType": "uint40", + "name": "startEpoch", + "type": "uint40" + }, + { + "indexed": false, + "internalType": "uint40", + "name": "endEpoch", + "type": "uint40" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "indexed": false, + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + } + ], + "name": "KnowledgeCollectionCreated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "endEpoch", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionEndEpochUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + } + ], + "name": "KnowledgeCollectionMerkleRootAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + } + ], + "name": "KnowledgeCollectionMerkleRootRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "indexed": false, + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "merkleRoots", + "type": "tuple[]" + } + ], + "name": "KnowledgeCollectionMerkleRootsUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minted", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionMintedUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "publisher", + "type": "address" + } + ], + "name": "KnowledgeCollectionPublisherUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "startEpoch", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionStartEpochUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmount", + "type": "uint256" + } + ], + "name": "KnowledgeCollectionTokenAmountUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "updateOperationId", + "type": "string" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "byteSize", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + } + ], + "name": "KnowledgeCollectionUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "custodian", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "tokenContract", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MisplacedERC20Withdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "custodian", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "MisplacedEtherWithdrawn", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "custodian", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "TokenTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "indexed": false, + "internalType": "uint256[]", + "name": "values", + "type": "uint256[]" + } + ], + "name": "TransferBatch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "TransferSingle", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "value", + "type": "string" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "URI", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "string", + "name": "newURI", + "type": "string" + } + ], + "name": "URIUpdate", + "type": "event" + }, + { + "inputs": [], + "name": "KNOWLEDGE_COLLECTION_MAX_SIZE", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stop", + "type": "uint256" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + } + ], + "name": "balanceOfBatch", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "tokenIds", + "type": "uint256[]" + } + ], + "name": "burnKnowledgeAssetsTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "string", + "name": "publishOperationId", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "knowledgeAssetsAmount", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "startEpoch", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "endEpoch", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + } + ], + "name": "createKnowledgeCollection", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "currentTotalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBurned", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getBurnedAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getByteSize", + "outputs": [ + { + "internalType": "uint88", + "name": "", + "type": "uint88" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getEndEpoch", + "outputs": [ + { + "internalType": "uint40", + "name": "", + "type": "uint40" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getKnowledgeAssetsAmount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getKnowledgeAssetsRange", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getKnowledgeCollection", + "outputs": [ + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "merkleRoots", + "type": "tuple[]" + }, + { + "internalType": "uint256[]", + "name": "burned", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "minted", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "startEpoch", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "endEpoch", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + } + ], + "internalType": "struct KnowledgeCollectionLib.KnowledgeCollection", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "getKnowledgeCollectionId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getKnowledgeCollectionMetadata", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "", + "type": "tuple[]" + }, + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getLatestKnowledgeCollectionId", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getLatestMerkleRoot", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getLatestMerkleRootObject", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getLatestMerkleRootPublisher", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getLatestMerkleRootTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getMerkleRootByIndex", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getMerkleRootObjectByIndex", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot", + "name": "", + "type": "tuple" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getMerkleRootPublisherByIndex", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getMerkleRootTimestampByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMerkleRoots", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getStartEpoch", + "outputs": [ + { + "internalType": "uint40", + "name": "", + "type": "uint40" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "getTokenAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTotalTokenAmount", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "address", + "name": "operator", + "type": "address" + } + ], + "name": "isApprovedForAll", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "isKnowledgeAssetBurned", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "isKnowledgeCollectionOwner", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "isOwnerOf", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "isPartOfKnowledgeCollection", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "knowledgeCollectionMaxSize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "knowledgeCollections", + "outputs": [ + { + "internalType": "uint256", + "name": "minted", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint40", + "name": "startEpoch", + "type": "uint40" + }, + { + "internalType": "uint40", + "name": "endEpoch", + "type": "uint40" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + }, + { + "internalType": "bool", + "name": "isImmutable", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mintKnowledgeAssetsTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "popMerkleRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + } + ], + "name": "pushMerkleRoot", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeBatchTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "safeTransferFrom", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setApprovalForAll", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "_burned", + "type": "uint256[]" + } + ], + "name": "setBurned", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint88", + "name": "_byteSize", + "type": "uint88" + } + ], + "name": "setByteSize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint40", + "name": "_endEpoch", + "type": "uint40" + } + ], + "name": "setEndEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "internalType": "struct KnowledgeCollectionLib.MerkleRoot[]", + "name": "_merkleRoots", + "type": "tuple[]" + } + ], + "name": "setMerkleRoots", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_minted", + "type": "uint256" + } + ], + "name": "setMinted", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint40", + "name": "_startEpoch", + "type": "uint40" + } + ], + "name": "setStartEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "uint96", + "name": "_tokenAmount", + "type": "uint96" + } + ], + "name": "setTokenAmount", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "baseURI", + "type": "string" + } + ], + "name": "setURI", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "tokenContract", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "tokensOfOwner", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "uint256", + "name": "start", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "stop", + "type": "uint256" + } + ], + "name": "tokensOfOwnerIn", + "outputs": [ + { + "internalType": "uint256[]", + "name": "", + "type": "uint256[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBurned", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalMinted", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "custodian", + "type": "address" + } + ], + "name": "transferTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "publisher", + "type": "address" + }, + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "string", + "name": "updateOperationId", + "type": "string" + }, + { + "internalType": "bytes32", + "name": "merkleRoot", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "mintKnowledgeAssetsAmount", + "type": "uint256" + }, + { + "internalType": "uint256[]", + "name": "knowledgeAssetsToBurn", + "type": "uint256[]" + }, + { + "internalType": "uint88", + "name": "byteSize", + "type": "uint88" + }, + { + "internalType": "uint96", + "name": "tokenAmount", + "type": "uint96" + } + ], + "name": "updateKnowledgeCollection", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "uri", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawMisplacedEther", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenContractAddress", + "type": "address" + } + ], + "name": "withdrawMisplacedTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] From 12aaeabbecd075c378e5c8c6ef18f645fbd80bc4 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:49:37 +0100 Subject: [PATCH 06/31] Update DefaultParameters --- dkg/constants.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dkg/constants.py b/dkg/constants.py index 679a135..0d12f10 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -37,6 +37,8 @@ class DefaultParameters(Enum): MAX_NUMBER_OF_RETRIES: int = 5 FREQUENCY: int = 5 + IMMUTABLE: bool = False + ZERO_ADDRESS: str = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { From b66ec2057d9c0389964dbbe9f9a58da2f03a926b Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:51:57 +0100 Subject: [PATCH 07/31] Create kc and ka tools --- dkg/utils/knowledge_asset_tools.py | 5 + dkg/utils/knowledge_collection_tools.py | 236 ++++++++++++++++++++++++ dkg/utils/rdf.py | 199 +------------------- 3 files changed, 246 insertions(+), 194 deletions(-) create mode 100644 dkg/utils/knowledge_asset_tools.py create mode 100644 dkg/utils/knowledge_collection_tools.py diff --git a/dkg/utils/knowledge_asset_tools.py b/dkg/utils/knowledge_asset_tools.py new file mode 100644 index 0000000..2c2ac14 --- /dev/null +++ b/dkg/utils/knowledge_asset_tools.py @@ -0,0 +1,5 @@ +from uuid import uuid4 + + +def generate_named_node(): + return f"uuid:{uuid4()}" diff --git a/dkg/utils/knowledge_collection_tools.py b/dkg/utils/knowledge_collection_tools.py new file mode 100644 index 0000000..6c5ad4f --- /dev/null +++ b/dkg/utils/knowledge_collection_tools.py @@ -0,0 +1,236 @@ +from typing import Literal +from dkg.constants import CHUNK_BYTE_SIZE +from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset +from dkg.types import JSONLD, NQuads +from pyld import jsonld +from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM +from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral +from uuid import uuid4 +from web3 import Web3 +import math + + +def normalize_dataset( + dataset: JSONLD | NQuads, + input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + output_format=DEFAULT_RDF_FORMAT, + algorithm=DEFAULT_CANON_ALGORITHM, +) -> NQuads: + normalization_options = { + "algorithm": algorithm, + "format": output_format, + } + + match input_format.lower(): + case "json-ld" | "jsonld": + pass + case "n-quads" | "nquads": + normalization_options["inputFormat"] = "application/n-quads" + case _: + raise DatasetInputFormatNotSupported( + f"Dataset input format isn't supported: {input_format}. " + "Supported formats: JSON-LD / N-Quads." + ) + + n_quads = jsonld.normalize(dataset, normalization_options) + assertion = [quad for quad in n_quads.split("\n") if quad] + + if not assertion: + raise InvalidDataset("Invalid dataset, no quads were extracted.") + + return assertion + + +def is_empty_dict(dictionary: dict): + return len(dictionary.keys()) == 0 and isinstance(dictionary, dict) + + +def format_dataset( + content: dict, + input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", + output_format=DEFAULT_RDF_FORMAT, + algorithm=DEFAULT_CANON_ALGORITHM, +): + private_assertion = None + if content.get("private") and not is_empty_dict(content.get("private")): + private_assertion = normalize_dataset( + content.get("private"), input_format, output_format, algorithm + ) + elif not content.get("public"): + content = {"public": content} + + public_assertion = [] + if content.get("public"): + public_assertion = normalize_dataset( + content.get("public"), input_format, output_format, algorithm + ) + + if ( + public_assertion + and len(public_assertion) == 0 + and private_assertion + and len(private_assertion) == 0 + ): + raise ValueError("File format is corrupted, no n-quads are extracted.") + + dataset = {"public": public_assertion} + if private_assertion: + dataset["private"] = private_assertion + + return dataset + + +def split_into_chunks(quads, chunk_size_bytes=32): + # Concatenate the quads with newline characters + concatenated_quads = "\n".join(quads) + + # Encode the concatenated string to bytes + encoded_bytes = concatenated_quads.encode("utf-8") + + # Split the encoded bytes into chunks + chunks = [] + start = 0 + + while start < len(encoded_bytes): + end = min(start + chunk_size_bytes, len(encoded_bytes)) + chunk = encoded_bytes[start:end] + chunks.append(chunk.decode("utf-8")) # Decode bytes back to string + start = end + + return chunks + + +def calculate_merkle_root(quads: list[str], chunk_size_bytes: int = CHUNK_BYTE_SIZE): + chunks = split_into_chunks(quads, chunk_size_bytes) + + # Create leaves using solidityKeccak256 equivalent + leaves = [ + bytes.fromhex(Web3.solidity_keccak(["string", "uint256"], [chunk, index]).hex()) + for index, chunk in enumerate(chunks) + ] + + while len(leaves) > 1: + next_level = [] + + for i in range(0, len(leaves), 2): + left = leaves[i] + + if i + 1 >= len(leaves): + next_level.append(left) + break + + right = leaves[i + 1] + + # Combine and sort the leaves + combined = [left, right] + combined.sort() + + # Calculate the hash of the combined leaves + hash_value = Web3.keccak(b"".join(combined)) + next_level.append(hash_value) + + leaves = next_level + + return f"0x{leaves[0].hex()}" + + +def generate_missing_ids_for_blank_nodes(nquads_list: list[str] | None) -> list[str]: + if not nquads_list: + return [""] + + generated_ids = {} + + def replace_blank_node(term): + # Handle blank nodes + if isinstance(term, BNode): + if str(term) not in generated_ids: + generated_ids[str(term)] = URIRef(f"uuid:{str(uuid4())}") + return generated_ids[str(term)] + + return term # Return IRIs or Literals unchanged + + # Create a temporary graph for parsing individual quads + result = [] + + # Process each N-Quad string individually to maintain order + for nquad in nquads_list: + if not nquad.strip(): + continue + + # Parse single N-Quad + g = Graph() + g.parse(data=nquad, format="nquads") + + # Get the triple and replace blank nodes + for s, p, o in g: + updated_quad = ( + replace_blank_node(s), + replace_blank_node(p), + replace_blank_node(o), + ) + # Format as N-Quad string + result.append( + f"{updated_quad[0].n3()} {updated_quad[1].n3()} {updated_quad[2].n3()} ." + ) + + return result + + +def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): + grouped = {} + + # Process each quad in original order + for nquad in nquads_list: + if not nquad.strip(): # Skip empty lines + continue + + # Parse single quad + g = Graph() + g.parse(data=nquad, format="nquads") + quad = next(iter(g)) + subject, predicate, obj = quad + + # Get subject key + subject_key = ( + f"<<<{subject.subject}> <{subject.predicate}> <{subject.object}>>" + if hasattr(subject, "subject") + else f"<{subject}>" + ) + + # Initialize group if needed + if subject_key not in grouped: + grouped[subject_key] = [] + + # Format object + object_value = f'"{obj}"' if isinstance(obj, RDFLiteral) else f"<{obj}>" + + # Add quad to group + quad_string = f"{subject_key} <{predicate}> {object_value} ." + grouped[subject_key].append(quad_string) + + # Return grouped quads (sorted if requested) + grouped_items = sorted(grouped.items()) if sort else grouped.items() + return [quads for _, quads in grouped_items] + + +def calculate_number_of_chunks(quads, chunk_size_bytes=CHUNK_BYTE_SIZE): + # Concatenate the quads with newline characters + concatenated_quads = "\n".join(quads) + + total_size_bytes = len(concatenated_quads.encode("utf-8")) + + # Calculate and return the number of chunks + return math.ceil(total_size_bytes / chunk_size_bytes) + + +def count_distinct_subjects(nquads_list: list[str]) -> int: + # Create a new RDF graph + graph = Graph() + + # Parse the joined N-Quads + graph.parse(data="\n".join(nquads_list), format="nquads") + + # Extract unique subjects using set comprehension + subjects = {str(quad[0]) for quad in graph} + + return len(subjects) diff --git a/dkg/utils/rdf.py b/dkg/utils/rdf.py index 06eced2..b01548b 100644 --- a/dkg/utils/rdf.py +++ b/dkg/utils/rdf.py @@ -17,19 +17,15 @@ from typing import Literal -from rdflib.plugins.parsers.nquads import NQuadsParser -from io import StringIO - -from dkg.constants import CHUNK_BYTE_SIZE, PRIVATE_ASSERTION_PREDICATE +from dkg.constants import ( + PRIVATE_ASSERTION_PREDICATE, + DEFAULT_RDF_FORMAT, + DEFAULT_CANON_ALGORITHM, +) from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset from dkg.types import JSONLD, HexStr, NQuads from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes from pyld import jsonld -from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM -from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral -from uuid import uuid4 -from web3 import Web3 -import math def normalize_dataset( @@ -89,188 +85,3 @@ def format_content( "public": public_assertion, "private": private_assertion if content.get("private", None) else {}, } - - -def is_empty_dict(dictionary: dict): - return len(dictionary.keys()) == 0 and isinstance(dictionary, dict) - - -def format_dataset( - content: dict, - input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - output_format=DEFAULT_RDF_FORMAT, - algorithm=DEFAULT_CANON_ALGORITHM, -): - private_assertion = None - if content.get("private") and not is_empty_dict(content.get("private")): - private_assertion = normalize_dataset( - content.get("private"), input_format, output_format, algorithm - ) - elif not content.get("public"): - content = {"public": content} - - public_assertion = [] - if content.get("public"): - public_assertion = normalize_dataset( - content.get("public"), input_format, output_format, algorithm - ) - - if ( - public_assertion - and len(public_assertion) == 0 - and private_assertion - and len(private_assertion) == 0 - ): - raise ValueError("File format is corrupted, no n-quads are extracted.") - - dataset = {"public": public_assertion} - if private_assertion: - dataset["private"] = private_assertion - - return dataset - - -def generate_missing_ids_for_blank_nodes(nquads_list: list[str]) -> list[str]: - generated_ids = {} - - def replace_blank_node(term): - # Handle blank nodes - if isinstance(term, BNode): - if str(term) not in generated_ids: - generated_ids[str(term)] = URIRef(f"uuid:{str(uuid4())}") - return generated_ids[str(term)] - - # Handle nested quads (RDF-star) - if hasattr(term, "subject"): # Check if term is a quad - return Graph().quad( - replace_blank_node(term.subject), - replace_blank_node(term.predicate), - replace_blank_node(term.object), - ) - - return term # Return IRIs or Literals unchanged - - # Create a graph and parse the N-Quads - g = Graph() - g.parse(data="".join(nquads_list)) - - # Create new graph for updated quads - updated_graph = Graph() - - # Process each quad and replace blank nodes - for quad in g: - updated_quad = ( - replace_blank_node(quad[0]), # subject - replace_blank_node(quad[1]), # predicate - replace_blank_node(quad[2]), # object - ) - updated_graph.add(updated_quad) - - # Serialize back to N-Quads format and split into lines - result = updated_graph.serialize(format="nquads").strip().split("\n") - return [line for line in result if line] # Remove empty - - -def group_nquads_by_subject(nquads_list: list[str], sort: bool = False): - grouped = {} - - # Process each quad in original order - for nquad in nquads_list: - if not nquad.strip(): # Skip empty lines - continue - - # Parse single quad - g = Graph() - g.parse(data=nquad, format="nquads") - quad = next(iter(g)) - subject, predicate, obj = quad - - # Get subject key - subject_key = ( - f"<<<{subject.subject}> <{subject.predicate}> <{subject.object}>>" - if hasattr(subject, "subject") - else f"<{subject}>" - ) - - # Initialize group if needed - if subject_key not in grouped: - grouped[subject_key] = [] - - # Format object - object_value = f'"{obj}"' if isinstance(obj, RDFLiteral) else f"<{obj}>" - - # Add quad to group - quad_string = f"{subject_key} <{predicate}> {object_value} ." - grouped[subject_key].append(quad_string) - - # Return grouped quads (sorted if requested) - grouped_items = sorted(grouped.items()) if sort else grouped.items() - return [quads for _, quads in grouped_items] - - -def split_into_chunks(quads, chunk_size_bytes=32): - # Concatenate the quads with newline characters - concatenated_quads = "\n".join(quads) - - # Encode the concatenated string to bytes - encoded_bytes = concatenated_quads.encode("utf-8") - - # Split the encoded bytes into chunks - chunks = [] - start = 0 - - while start < len(encoded_bytes): - end = min(start + chunk_size_bytes, len(encoded_bytes)) - chunk = encoded_bytes[start:end] - chunks.append(chunk.decode("utf-8")) # Decode bytes back to string - start = end - - return chunks - - -def calculate_merkle_root(quads: list[str], chunk_size_bytes: int = CHUNK_BYTE_SIZE): - chunks = split_into_chunks(quads, chunk_size_bytes) - - # Create leaves using solidityKeccak256 equivalent - leaves = [ - bytes.fromhex(Web3.solidity_keccak(["string", "uint256"], [chunk, index]).hex()) - for index, chunk in enumerate(chunks) - ] - - while len(leaves) > 1: - next_level = [] - - for i in range(0, len(leaves), 2): - left = leaves[i] - - if i + 1 >= len(leaves): - next_level.append(left) - break - - right = leaves[i + 1] - - # Combine and sort the leaves - combined = [left, right] - combined.sort() - - # Calculate the hash of the combined leaves - hash_value = Web3.keccak(b"".join(combined)) - next_level.append(hash_value) - - leaves = next_level - - return f"0x{leaves[0].hex()}" - - -def generate_named_node(): - return f"uuid:{uuid4()}" - - -def calculate_number_of_chunks(quads, chunk_size_bytes=CHUNK_BYTE_SIZE): - # Concatenate the quads with newline characters - concatenated_quads = "\n".join(quads) - - total_size_bytes = len(concatenated_quads.encode("utf-8")) - - # Calculate and return the number of chunks - return math.ceil(total_size_bytes / chunk_size_bytes) From fb35143900a151bf01b720bf399255a2274f55c7 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:54:28 +0100 Subject: [PATCH 08/31] Finish v8 create --- dkg/asset.py | 330 +++++++++++++++++++++++++++----- dkg/providers/node_http.py | 2 +- dkg/utils/blockchain_request.py | 69 ++++++- dkg/utils/node_request.py | 7 + 4 files changed, 362 insertions(+), 46 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 61cf419..1a0fff3 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -16,11 +16,11 @@ # under the License. import json +import time import math import re import hashlib -from typing import Literal, Type - +from typing import Literal, Type, Dict, Optional, Any from pyld import jsonld from web3 import Web3 from web3.constants import ADDRESS_ZERO @@ -30,6 +30,7 @@ from eth_abi.packed import encode_packed from eth_account.messages import encode_defunct from eth_account import Account +from hexbytes import HexBytes from dkg.constants import ( DEFAULT_HASH_FUNCTION_ID, @@ -62,7 +63,11 @@ from dkg.method import Method from dkg.module import Module from dkg.types import JSONLD, UAL, Address, AgreementData, HexStr, Wei -from dkg.utils.blockchain_request import BlockchainRequest +from dkg.utils.blockchain_request import ( + BlockchainRequest, + KnowledgeCollectionResult, + AllowanceResult, +) from dkg.utils.decorators import retry from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes from dkg.utils.metadata import ( @@ -79,14 +84,10 @@ from dkg.utils.rdf import ( format_content, normalize_dataset, - format_dataset, - generate_missing_ids_for_blank_nodes, - group_nquads_by_subject, - generate_named_node, - calculate_merkle_root, - calculate_number_of_chunks, ) from dkg.utils.ual import format_ual, parse_ual +import dkg.utils.knowledge_collection_tools as kc_tools +import dkg.utils.knowledge_asset_tools as ka_tools class KnowledgeAsset(Module): @@ -218,10 +219,181 @@ def decrease_allowance( _create = Method(BlockchainRequest.create_asset) _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) - + _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) + _epoch_length = Method(BlockchainRequest.epoch_length) + _get_stake_weighted_average_ask = Method( + BlockchainRequest.get_stake_weighted_average_ask + ) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) _local_store = Method(NodeRequest.local_store) _publish = Method(NodeRequest.publish) + _finality_status = Method(NodeRequest.finality_status) + + _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) + _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) + _decrease_allowance = Method(BlockchainRequest.decrease_allowance) + + def get_operation_status_object( + self, operation_result: Dict[str, Any], operation_id: str + ) -> Dict[str, Any]: + """ + Creates an operation status object from operation result and ID. + + Args: + operation_result: Dictionary containing operation result data + operation_id: The ID of the operation + + Returns: + Dictionary containing operation status information + """ + # Check if error_type exists in operation_result.data + operation_data = ( + {"status": operation_result.get("status"), **operation_result.get("data")} + if operation_result.get("data", {}).get("errorType") + else {"status": operation_result.get("status")} + ) + + return {"operationId": operation_id, **operation_data} + + def finality_status( + self, + ual: str, + required_confirmations: int, + max_number_of_retries: int, + frequency: int, + ): + retries = 0 + finality = 0 + + while finality < required_confirmations and retries <= max_number_of_retries: + if retries > max_number_of_retries: + raise Exception( + f"Unable to achieve required confirmations. " + f"Max number of retries ({max_number_of_retries}) reached." + ) + + retries += 1 + + # Sleep between attempts (except for first try) + if retries > 1: + time.sleep(frequency) + + try: + response = self._finality_status(ual) + finality = response.get("finality", 0) + except Exception: + finality = 0 + + return finality + + def increase_knowledge_collection_allowance( + self, sender: str, token_amount: str + ) -> AllowanceResult: + """ + Increases the allowance for knowledge collection if necessary. + + Args: + sender: The address of the sender + token_amount: The amount of tokens to check/increase allowance for + + Returns: + AllowanceResult containing whether allowance was increased and the gap + """ + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") + + allowance = self._get_current_allowance(sender, knowledge_collection_address) + allowance_gap = int(token_amount) - int(allowance) + + if allowance_gap > 0: + self._increase_allowance(knowledge_collection_address, allowance_gap) + + return AllowanceResult( + allowance_increased=True, allowance_gap=allowance_gap + ) + + return AllowanceResult(allowance_increased=False, allowance_gap=allowance_gap) + + def create_knowledge_collection( + self, + request: dict, + paranet_ka_contract: Optional[Address] = None, + paranet_token_id: Optional[int] = None, + ) -> KnowledgeCollectionResult: + """ + Creates a knowledge collection on the blockchain. + + Args: + request: dict containing all collection parameters + paranet_ka_contract: Optional paranet contract address + paranet_token_id: Optional paranet token ID + blockchain: Blockchain configuration + + Returns: + KnowledgeCollectionResult containing collection ID and transaction receipt + + Raises: + BlockchainError: If the collection creation fails + """ + sender = self.manager.blockchain_provider.account.address + service_agreement_v1_address = None + allowance_increased = False + allowance_gap = 0 + + try: + # Handle allowance + if request.get("payer"): + pass + else: + allowance_result = self.increase_knowledge_collection_allowance( + sender=sender, + token_amount=request.get("tokenAmount"), + ) + allowance_increased = allowance_result.allowance_increased + allowance_gap = allowance_result.allowance_gap + + if not paranet_ka_contract and not paranet_token_id: + receipt = self._create_knowledge_collection( + request.get("publishOperationId"), + Web3.to_bytes(hexstr=request.get("merkleRoot")), + request.get("knowledgeAssetsAmount"), + request.get("byteSize"), + request.get("epochs"), + int(request.get("tokenAmount")), + request.get("isImmutable"), + request.get("paymaster"), + request.get("publisherNodeIdentityId"), + Web3.to_bytes(hexstr=request.get("publisherNodeR")), + Web3.to_bytes(hexstr=request.get("publisherNodeVS")), + request.get("identityIds"), + [Web3.to_bytes(hexstr=x) for x in request.get("r")], + [Web3.to_bytes(hexstr=x) for x in request.get("vs")], + ) + else: + receipt = self._mint_knowledge_asset( + paranet_ka_contract, + paranet_token_id, + list(request.values()), + ) + + event_data = self.manager.blockchain_provider.decode_logs_event( + receipt=receipt, + contract_name="KnowledgeCollectionStorage", + event_name="KnowledgeCollectionCreated", + ) + collection_id = ( + int(getattr(event_data[0].get("args", {}), "id", None)) + if event_data + else None + ) + + return KnowledgeCollectionResult( + knowledge_collection_id=collection_id, receipt=receipt + ) + + except Exception as e: + if allowance_increased: + self._decrease_allowance(service_agreement_v1_address, allowance_gap) + raise e def process_content(self, content: str) -> list: return [line.strip() for line in content.split("\n") if line.strip() != ""] @@ -263,7 +435,7 @@ def get_operation_status_dict(self, operation_result, operation_id): return {"operationId": operation_id, **operation_data} def get_message_signer_address(self, dataset_root: str, signature: dict): - message = encode_defunct(Web3.to_bytes(dataset_root)) + message = encode_defunct(HexBytes(dataset_root)) r, s, v = signature.get("r"), signature.get("s"), signature.get("v") r = r[2:] if r.startswith("0x") else r s = s[2:] if s.startswith("0x") else s @@ -275,7 +447,7 @@ def get_message_signer_address(self, dataset_root: str, signature: dict): def create( self, content: dict[Literal["public", "private"], JSONLD], - epochs_number: int, + epochs_num: int, minimum_number_of_finalization_confirmations: int, minimum_number_of_node_replications: int, token_amount: Wei | None = None, @@ -301,34 +473,34 @@ def create( if private_content and isinstance(private_content, str): dataset["private"] = self.process_content(private_content) else: - dataset = format_dataset(content) + dataset = kc_tools.format_dataset(content) public_triples_grouped = [] - # TODO: Uncomment and test this - # dataset["public"] = generate_missing_ids_for_blank_nodes(dataset.get("public")) + dataset["public"] = kc_tools.generate_missing_ids_for_blank_nodes( + dataset.get("public") + ) if dataset.get("private") and len(dataset.get("private")): - # TODO: Uncomment and test this - # dataset["private"] = generate_missing_ids_for_blank_nodes( - # dataset.get("private") - # ) + dataset["private"] = kc_tools.generate_missing_ids_for_blank_nodes( + dataset.get("private") + ) # Group private triples by subject and flatten - private_triples_grouped = group_nquads_by_subject( + private_triples_grouped = kc_tools.group_nquads_by_subject( dataset.get("private"), True ) dataset["private"] = list(chain.from_iterable(private_triples_grouped)) # Compute private root and add to public - private_root = calculate_merkle_root(dataset.get("private")) + private_root = kc_tools.calculate_merkle_root(dataset.get("private")) dataset["public"].append( - f'<{generate_named_node()}> <${PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' + f'<{ka_tools.generate_named_node()}> <{PRIVATE_ASSERTION_PREDICATE}> "{private_root}" .' ) # Compute private root and add to public - public_triples_grouped = group_nquads_by_subject( + public_triples_grouped = kc_tools.group_nquads_by_subject( dataset.get("public"), True ) @@ -355,17 +527,16 @@ def create( private_subject in public_subject_dict ): # Check if there's a public pair # If there's a public pair, insert a representation in that group - # TODO: Test this public_index = public_subject_dict.get(private_subject) self.insert_triple_sorted( - public_triples_grouped.get(public_index), - f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{generate_named_node()}> .", + public_triples_grouped[public_index], + f"{private_subject} <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", ) else: # If no public pair, maintain separate list, inserting sorted by hash self.insert_triple_sorted( private_triple_subject_hashes_grouped_without_public_pair, - f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{generate_named_node()}> .", + f"<{PRIVATE_HASH_SUBJECT_PREFIX}{private_subject_hash}> <{PRIVATE_RESOURCE_PREDICATE}> <{ka_tools.generate_named_node()}> .", ) for triple in private_triple_subject_hashes_grouped_without_public_pair: @@ -373,26 +544,24 @@ def create( dataset["public"] = list(chain.from_iterable(public_triples_grouped)) else: - # TODO: Test this # No private triples, just group and flatten public - public_triples_grouped = group_nquads_by_subject( + public_triples_grouped = kc_tools.group_nquads_by_subject( dataset.get("public"), True ) dataset["public"] = list(chain.from_iterable(public_triples_grouped)) # Calculate the number of chunks - number_of_chunks = calculate_number_of_chunks( + number_of_chunks = kc_tools.calculate_number_of_chunks( dataset.get("public"), CHUNK_BYTE_SIZE ) dataset_size = number_of_chunks * CHUNK_BYTE_SIZE # Validate the assertion size in bytes - # TODO: Move into validation service once developed if dataset_size > MAX_FILE_SIZE: raise ValueError(f"File size limit is {MAX_FILE_SIZE / (1024 * 1024)}MB.") # Calculate the Merkle root - dataset_root = calculate_merkle_root(dataset.get("public")) + dataset_root = kc_tools.calculate_merkle_root(dataset.get("public")) # Get the contract address for KnowledgeCollectionStorage content_asset_storage_address = self._get_asset_storage_address( @@ -456,21 +625,94 @@ def create( except Exception: continue - # result["operation"]["publish"] = { - # "operationId": operation_id, - # "status": operation_result["status"], - # } + if token_amount: + estimated_publishing_cost = token_amount + else: + time_until_next_epoch = self._time_until_next_epoch() + epoch_length = self._epoch_length() + stake_weighted_average_ask = self._get_stake_weighted_average_ask() + + # Convert to integers and perform calculation + # Note: In Python we use regular int as it handles arbitrary precision automatically + estimated_publishing_cost = ( + ( + int(stake_weighted_average_ask) + * ( + int(epochs_num) * int(1e18) + + (int(time_until_next_epoch) * int(1e18)) / int(epoch_length) + ) + * int(dataset_size) + ) + / 1024 + / int(1e18) + ) + + knowledge_collection_id = None + mint_knowledge_asset_receipt = None + + knowledge_collection_result = self.create_knowledge_collection( + { + "publishOperationId": publish_operation_id, + "merkleRoot": dataset_root, + "knowledgeAssetsAmount": kc_tools.count_distinct_subjects( + dataset.get("public") + ), + "byteSize": dataset_size, + "epochs": epochs_num, + "tokenAmount": str(estimated_publishing_cost), + "isImmutable": DefaultParameters.IMMUTABLE.value, + "paymaster": DefaultParameters.ZERO_ADDRESS.value, + "publisherNodeIdentityId": publisher_node_identity_id, + "publisherNodeR": publisher_node_r, + "publisherNodeVS": publisher_node_vs, + "identityIds": identity_ids, + "r": r, + "vs": vs, + }, + None, + None, + ) + knowledge_collection_id = knowledge_collection_result.knowledge_collection_id + mint_knowledge_asset_receipt = knowledge_collection_result.receipt - # if operation_result["status"] == OperationStatus.COMPLETED: - # operation_id = self._local_store(assertions_list)["operationId"] - # operation_result = self.get_operation_result(operation_id, "local-store") + ual = format_ual( + blockchain_id, content_asset_storage_address, knowledge_collection_id + ) - # result["operation"]["localStore"] = { - # "operationId": operation_id, - # "status": operation_result["status"], - # } + finality_status_result = 0 + if minimum_number_of_finalization_confirmations > 0: + finality_status_result = self.finality_status( + ual, + minimum_number_of_finalization_confirmations, + 300, + 2, + ) - # return result + return json.loads( + Web3.to_json( + { + "UAL": ual, + "datasetRoot": dataset_root, + "signatures": publish_operation_result.get("data", {}).get( + "signatures" + ), + "operation": { + "mintKnowledgeAsset": mint_knowledge_asset_receipt, + "publish": self.get_operation_status_object( + publish_operation_result, publish_operation_id + ), + "finality": { + "status": "FINALIZED" + if finality_status_result + >= minimum_number_of_finalization_confirmations + else "NOT FINALIZED" + }, + "numberOfConfirmations": finality_status_result, + "requiredConfirmations": minimum_number_of_finalization_confirmations, + }, + } + ) + ) def local_store( self, diff --git a/dkg/providers/node_http.py b/dkg/providers/node_http.py index c096ca2..8316d6c 100644 --- a/dkg/providers/node_http.py +++ b/dkg/providers/node_http.py @@ -26,7 +26,7 @@ class NodeHTTPProvider: def __init__( - self, + self, endpoint_uri: URI | str, api_version: str = "v1", auth_token: str | None = None, diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index fc5b379..f351765 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -16,7 +16,7 @@ # under the License. from dataclasses import dataclass, field -from typing import Type +from typing import Type, Dict, Any from dkg.dataclasses import ParanetIncentivizationType from dkg.types import Address, HexStr, Wei @@ -52,6 +52,18 @@ class ContractCall(ContractInteraction): pass +@dataclass +class KnowledgeCollectionResult: + knowledge_collection_id: int + receipt: Dict[str, Any] + + +@dataclass +class AllowanceResult: + allowance_increased: bool + allowance_gap: int + + class BlockchainRequest: chain_id = JSONRPCRequest("chain_id") get_block = JSONRPCRequest("get_block", args={"block_identifier": str | int}) @@ -73,6 +85,24 @@ class BlockchainRequest: args={"identityId": int, "_key": Address, "_purpose": int}, ) + time_until_next_epoch = ContractCall( + contract="Chronos", + function="timeUntilNextEpoch", + args={}, + ) + + epoch_length = ContractCall( + contract="Chronos", + function="epochLength", + args={}, + ) + + get_stake_weighted_average_ask = ContractCall( + contract="AskStorage", + function="getStakeWeightedAverageAsk", + args={}, + ) + allowance = ContractCall( contract="Token", function="allowance", @@ -401,3 +431,40 @@ class BlockchainRequest: function="claimIncentivizationProposalVoterReward", args={}, ) + + create_knowledge_collection = ContractTransaction( + contract="KnowledgeCollection", + function="createKnowledgeCollection", + args={ + "publishOperationId": str, + "merkleRoot": bytes, + "knowledgeAssetsAmount": int, + "byteSize": int, + "epochs": int, + "tokenAmount": int, + "isImmutable": bool, + "paymaster": Address, + "publisherNodeIdentityId": int, + "publisherNodeR": bytes, + "publisherNodeVS": bytes, + "identityIds": list[int], + "r": list[bytes], + "vs": list[bytes], + }, + ) + + mint_knowledge_asset = ContractTransaction( + contract="Paranet", + function="mintKnowledgeAsset", + args={ + "paranetKAStorageContract": Address, + "paranetKATokenId": int, + "knowledgeAssetArgs": dict, + }, + ) + + decrease_allowance = ContractTransaction( + contract="Token", + function="decreaseAllowance", + args={"spender": Address, "subtractedValue": int}, + ) diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index 340c650..ea90f36 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -68,6 +68,13 @@ class NodeRequest: "minimumNumberOfNodeReplications": int, }, ) + + finality_status = NodeCall( + method=HTTPRequestMethod.GET, + path="finality", + params={"ual": str}, + ) + get = NodeCall( method=HTTPRequestMethod.POST, path="get", From ba92b28f1599e8562a8924457f73f40920580a5f Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 15:57:52 +0100 Subject: [PATCH 09/31] Update demo --- examples/demo.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/examples/demo.py b/examples/demo.py index 9bddbf9..61a3538 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -16,6 +16,7 @@ # under the License. import json +import time from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider @@ -130,8 +131,9 @@ def print_json(json_dict: dict): divider() +start_time = time.time() create_asset_result = dkg.asset.create(content, 2, 3, 1, "100") -print("======================== ASSET CREATED") +print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") print_json(create_asset_result) divider() From 54180e6a6263f838ef549d135877704ed9c2d729 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Wed, 8 Jan 2025 16:33:42 +0100 Subject: [PATCH 10/31] Added input service --- dkg/asset.py | 283 +++++----------------------------- dkg/constants.py | 48 +++--- dkg/main.py | 9 +- dkg/providers/node_http.py | 10 +- dkg/services/input_service.py | 162 +++++++++++++++++++ 5 files changed, 244 insertions(+), 268 deletions(-) create mode 100644 dkg/services/input_service.py diff --git a/dkg/asset.py b/dkg/asset.py index 35791a4..d1ead06 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -32,7 +32,6 @@ PRIVATE_ASSERTION_PREDICATE, PRIVATE_CURRENT_REPOSITORY, PRIVATE_HISTORICAL_REPOSITORY, - DEFAULT_PARAMETERS, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -71,8 +70,9 @@ class KnowledgeAsset(Module): - def __init__(self, manager: DefaultRequestManager): + def __init__(self, manager: DefaultRequestManager, input_service): self.manager = manager + self.input_service = input_service _owner = Method(BlockchainRequest.owner_of) @@ -562,20 +562,36 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: _get = Method(NodeRequest.get) _query = Method(NodeRequest.query) - def get_v8(self, ual: UAL) -> dict: + def get(self, ual: UAL, options=None) -> dict: + if options is None: + options = {} + + arguments = self.input_service.get_asset_get_arguments(options) + + max_number_of_retries = arguments["max_number_of_retries"] + frequency = arguments["frequency"] + state = arguments["state"] + include_metadata = arguments["include_metadata"] + content_type = arguments["content_type"] + validate = arguments["validate"] + output_format = arguments["output_format"] + auth_token = arguments["auth_token"] + hash_function_id = arguments["hash_function_id"] + paranet_ual = arguments["paranet_ual"] + subject_ual = arguments["subject_ual"] + + id_field = f"{ual}:{state}" if state else ual get_public_operation_id: NodeResponseDict = self._get( - ual, - DEFAULT_PARAMETERS["CONTENT_TYPE"], - DEFAULT_PARAMETERS["INCLUDE_METADATA"], - DEFAULT_PARAMETERS["HASH_FUNCTION_ID"], - DEFAULT_PARAMETERS["PARANET_UAL"], - DEFAULT_PARAMETERS["GET_SUBJECT_UAL"], + id_field, + content_type, + include_metadata, + hash_function_id, + paranet_ual, + subject_ual, )["operationId"] get_public_operation_result = self.get_operation_result( - get_public_operation_id, - "get", - DEFAULT_PARAMETERS["MAX_NUMBER_OF_RETRIES"], + get_public_operation_id, "get", max_number_of_retries, frequency ) def get_operation_status_object(self, operation_result, operation_id): @@ -592,7 +608,7 @@ def get_operation_status_object(self, operation_result, operation_id): return {"operationId": operation_id, **operation_data} - if DEFAULT_PARAMETERS["GET_SUBJECT_UAL"]: + if subject_ual: if get_public_operation_result["data"]: return { "operation": { @@ -635,7 +651,7 @@ def get_operation_status_object(self, operation_result, operation_id): }, } - if DEFAULT_PARAMETERS["GET_SUBJECT_UAL"]: + if validate: is_valid = True # #TODO: Implement assertion validation logic if not is_valid: get_public_operation_result["data"] = { @@ -648,18 +664,17 @@ def get_operation_status_object(self, operation_result, operation_id): ) formatted_metadata = None - if DEFAULT_PARAMETERS["OUTPUT_FORMAT"] == "JSON-LD": + if output_format == "JSON-LD": formatted_assertion = self.to_jsonld(formatted_assertion) - if DEFAULT_PARAMETERS["INCLUDE_METADATA"]: - print("USAO") + if include_metadata: formatted_metadata = self.to_jsonld("\n".join(metadata)) - if DEFAULT_PARAMETERS["OUTPUT_FORMAT"] == "N-QUADS": + if output_format == "N-QUADS": formatted_assertion = self.to_nquads( formatted_assertion, "application/n-quads" ) - if DEFAULT_PARAMETERS["INCLUDE_METADATA"]: + if include_metadata: formatted_metadata = self.to_nquads( "\n".join(metadata), "application/n-quads" ) @@ -673,231 +688,11 @@ def get_operation_status_object(self, operation_result, operation_id): }, } - if DEFAULT_PARAMETERS["INCLUDE_METADATA"] and metadata: + if include_metadata and metadata: result["metadata"] = formatted_metadata return result - def get( - self, - ual: UAL, - state: str | HexStr | int = KnowledgeAssetEnumStates.LATEST, - content_visibility: str = KnowledgeAssetContentVisibility.ALL, - output_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - validate: bool = True, - ) -> dict[str, UAL | HexStr | list[JSONLD] | dict[str, str]]: - state = ( - state.upper() - if (isinstance(state, str) and not re.match(r"^0x[a-fA-F0-9]{64}$", state)) - else state - ) - content_visibility = content_visibility.upper() - output_format = output_format.upper() - - token_id = parse_ual(ual)["token_id"] - - def handle_latest_finalized_state(token_id: int) -> tuple[HexStr, bool]: - return Web3.to_hex(self._get_latest_assertion_id(token_id)), True - - is_state_finalized = False - - match state: - case ( - KnowledgeAssetEnumStates.LATEST - | KnowledgeAssetEnumStates.LATEST_FINALIZED - ): - public_assertion_id, is_state_finalized = handle_latest_finalized_state( - token_id - ) - - case _ if isinstance(state, int): - assertion_ids = [ - Web3.to_hex(assertion_id) - for assertion_id in self._get_assertion_ids(token_id) - ] - if 0 <= state < (states_number := len(assertion_ids)): - public_assertion_id = assertion_ids[state] - - if state == states_number - 1: - is_state_finalized = True - else: - raise InvalidStateOption(f"State index {state} is out of range.") - - case _ if isinstance(state, str) and re.match( - r"^0x[a-fA-F0-9]{64}$", state - ): - assertion_ids = [ - Web3.to_hex(assertion_id) - for assertion_id in self._get_assertion_ids(token_id) - ] - - if state in assertion_ids: - public_assertion_id = state - - if state == assertion_ids[-1]: - is_state_finalized = True - else: - raise InvalidStateOption( - f"Given state hash: {state} is not a part of the KA." - ) - - case _: - raise InvalidStateOption(f"Invalid state option: {state}.") - - get_public_operation_id: NodeResponseDict = self._get( - ual, public_assertion_id, hashFunctionId=1 - )["operationId"] - - get_public_operation_result = self.get_operation_result( - get_public_operation_id, "get" - ) - public_assertion = get_public_operation_result["data"].get("assertion", None) - - if public_assertion is None: - raise MissingKnowledgeAssetState("Unable to find state on the network!") - - if validate: - root = MerkleTree( - hash_assertion_with_indexes(public_assertion), sort_pairs=True - ).root - if root != public_assertion_id: - raise InvalidKnowledgeAsset( - f"State: {public_assertion_id}. " f"Merkle Tree Root: {root}" - ) - - result = {"operation": {}} - if content_visibility != KnowledgeAssetContentVisibility.PRIVATE: - formatted_public_assertion = public_assertion - - match output_format: - case "NQUADS" | "N-QUADS": - formatted_public_assertion: list[JSONLD] = jsonld.from_rdf( - "\n".join(public_assertion), - {"algorithm": "URDNA2015", "format": "application/n-quads"}, - ) - case "JSONLD" | "JSON-LD": - formatted_public_assertion = "\n".join(public_assertion) - - case _: - raise DatasetOutputFormatNotSupported( - f"{output_format} isn't supported!" - ) - - if content_visibility == KnowledgeAssetContentVisibility.PUBLIC: - result = { - **result, - "asertion": formatted_public_assertion, - "assertionId": public_assertion_id, - } - else: - result["public"] = { - "assertion": formatted_public_assertion, - "assertionId": public_assertion_id, - } - - result["operation"]["publicGet"] = { - "operationId": get_public_operation_id, - "status": get_public_operation_result["status"], - } - - if content_visibility != KnowledgeAssetContentVisibility.PUBLIC: - private_assertion_link_triples = list( - filter( - lambda element: PRIVATE_ASSERTION_PREDICATE in element, - public_assertion, - ) - ) - - if private_assertion_link_triples: - private_assertion_id = re.search( - r'"(.*?)"', private_assertion_link_triples[0] - ).group(1) - - private_assertion = get_public_operation_result["data"].get( - "privateAssertion", None - ) - - query_private_operation_id: NodeResponseDict | None = None - if private_assertion is None: - query = f""" - CONSTRUCT {{ ?s ?p ?o }} - WHERE {{ - {{ - GRAPH - {{ - ?s ?p ?o . - }} - }} - }} - """ - - query_private_operation_id = self._query( - query, - "CONSTRUCT", - ( - PRIVATE_CURRENT_REPOSITORY - if is_state_finalized - else PRIVATE_HISTORICAL_REPOSITORY - ), - )["operationId"] - - query_private_operation_result = self.get_operation_result( - query_private_operation_id, "query" - ) - - private_assertion = normalize_dataset( - query_private_operation_result["data"], - "N-Quads", - ) - - if validate: - root = MerkleTree( - hash_assertion_with_indexes(private_assertion), - sort_pairs=True, - ).root - if root != private_assertion_id: - raise InvalidKnowledgeAsset( - f"State: {private_assertion_id}. " - f"Merkle Tree Root: {root}" - ) - - match output_format: - case "NQUADS" | "N-QUADS": - formatted_private_assertion: list[JSONLD] = jsonld.from_rdf( - "\n".join(private_assertion), - { - "algorithm": "URDNA2015", - "format": "application/n-quads", - }, - ) - case "JSONLD" | "JSON-LD": - formatted_private_assertion = "\n".join(private_assertion) - - case _: - raise DatasetOutputFormatNotSupported( - f"{output_format} isn't supported!" - ) - - if content_visibility == KnowledgeAssetContentVisibility: - result = { - **result, - "assertion": formatted_private_assertion, - "assertionId": private_assertion_id, - } - else: - result["private"] = { - "assertion": formatted_private_assertion, - "assertionId": private_assertion_id, - } - - if query_private_operation_id is not None: - result["operation"]["queryPrivate"] = { - "operationId": query_private_operation_id, - "status": query_private_operation_result["status"], - } - - return result - _extend_storing_period = Method(BlockchainRequest.extend_asset_storing_period) def extend_storing_period( @@ -1019,17 +814,19 @@ def get_agreement_id(self, contract_address: Address, token_id: int) -> HexStr: _get_operation_result = Method(NodeRequest.get_operation_result) def get_operation_result( - self, operation_id: str, operation: str, max_retries: int = 5 + self, operation_id: str, operation: str, max_retries: int, frequency: int ): @retry( - catch=OperationNotFinished, max_retries=max_retries, base_delay=1, backoff=2 + catch=OperationNotFinished, + max_retries=max_retries, + base_delay=frequency, + backoff=2, ) def _get_opeation_results_(): operation_result = self._get_operation_result( operation_id=operation_id, operation=operation, ) - print(operation_result) validate_operation_status(operation_result) return operation_result diff --git a/dkg/constants.py b/dkg/constants.py index b5b47bd..8999512 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -1,3 +1,5 @@ +from enum import Enum + # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information @@ -19,6 +21,30 @@ "https://ontology.origintrail.io/dkg/1.0#privateAssertionID" ) + +class DefaultParameters(Enum): + ENVIRONMENT: str = "mainnet" + PORT: int = 8900 + FREQUENCY: int = 5 + MAX_NUMBER_OF_RETRIES: int = 5 + HASH_FUNCTION_ID: int = 1 + IMMUTABLE: bool = False + VALIDATE: bool = True + OUTPUT_FORMAT: str = "JSON-LD" + STATE: None = None + INCLUDE_METADATA: bool = False + CONTENT_TYPE: str = "all" + GRAPH_LOCATION: str = "LOCAL_KG" + GRAPH_STATE: str = "CURRENT" + HANDLE_NOT_MINED_ERROR: bool = False + SIMULATE_TXS: bool = False + FORCE_REPLACE_TXS: bool = False + GAS_LIMIT_MULTIPLIER: int = 1 + PARANET_UAL: None = None + GET_SUBJECT_UAL: bool = False + + +ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { "development": { "hardhat1:31337": { @@ -67,25 +93,3 @@ PRIVATE_HISTORICAL_REPOSITORY = "privateHistory" PRIVATE_CURRENT_REPOSITORY = "privateCurrent" - -DEFAULT_PARAMETERS = { - "ENVIRONMENT": "mainnet", - "PORT": 8900, - "FREQUENCY": 5, - "MAX_NUMBER_OF_RETRIES": 5, - "HASH_FUNCTION_ID": 1, - "IMMUTABLE": False, - "VALIDATE": True, - "OUTPUT_FORMAT": "JSON-LD", - "STATE": None, - "INCLUDE_METADATA": False, - "CONTENT_TYPE": "all", - "GRAPH_LOCATION": "LOCAL_KG", - "GRAPH_STATE": "CURRENT", - "HANDLE_NOT_MINED_ERROR": False, - "SIMULATE_TXS": False, - "FORCE_REPLACE_TXS": False, - "GAS_LIMIT_MULTIPLIER": 1, - "PARANET_UAL": None, - "GET_SUBJECT_UAL": False, -} diff --git a/dkg/main.py b/dkg/main.py index c9c14d4..ec79e91 100644 --- a/dkg/main.py +++ b/dkg/main.py @@ -28,6 +28,7 @@ from dkg.providers import BlockchainProvider, NodeHTTPProvider from dkg.types import UAL, Address, ChecksumAddress from dkg.utils.ual import format_ual, parse_ual +from dkg.services.input_service import InputService class DKG(Module): @@ -56,9 +57,12 @@ def __init__( blockchain_provider: BlockchainProvider, ): self.manager = DefaultRequestManager(node_provider, blockchain_provider) + + self.initialize_services(self.manager) + modules = { "assertion": Assertion(self.manager), - "asset": KnowledgeAsset(self.manager), + "asset": KnowledgeAsset(self.manager, self.input_service), "paranet": Paranet(self.manager), "network": Network(self.manager), "node": Node(self.manager), @@ -66,6 +70,9 @@ def __init__( } self._attach_modules(modules) + def initialize_services(self, manager): + self.input_service = InputService(manager) + @property def node_provider(self) -> NodeHTTPProvider: return self.manager.node_provider diff --git a/dkg/providers/node_http.py b/dkg/providers/node_http.py index 1286655..8316d6c 100644 --- a/dkg/providers/node_http.py +++ b/dkg/providers/node_http.py @@ -25,8 +25,14 @@ class NodeHTTPProvider: - def __init__(self, endpoint_uri: URI | str, auth_token: str | None = None): + def __init__( + self, + endpoint_uri: URI | str, + api_version: str = "v1", + auth_token: str | None = None, + ): self.endpoint_uri = URI(endpoint_uri) + self.api_version = api_version self.auth_token = auth_token def make_request( @@ -36,7 +42,7 @@ def make_request( params: dict[str, Any] = {}, data: dict[str, Any] = {}, ) -> NodeResponseDict: - url = f"{self.endpoint_uri}/{path}" + url = f"{self.endpoint_uri}/{self.api_version}/{path}" headers = ( {"Authorization": f"Bearer {self.auth_token}"} if self.auth_token else {} ) diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py new file mode 100644 index 0000000..a420b77 --- /dev/null +++ b/dkg/services/input_service.py @@ -0,0 +1,162 @@ +from dkg.constants import DefaultParameters, ZERO_ADDRESS + + +class InputService: + def __init__(self, manager): + self.manager = manager + + def get_asset_get_arguments(self, options): + return { + # "blockchain": self.get_blockchain(options), + "endpoint": self.get_endpoint(options), + "port": self.get_port(options), + "max_number_of_retries": self.get_max_number_of_retries(options), + "frequency": self.get_frequency(options), + "state": self.get_state(options), + "include_metadata": self.get_include_metadata(options), + "content_type": self.get_content_type(options), + "validate": self.get_validate(options), + "output_format": self.get_output_format(options), + "auth_token": self.get_auth_token(options), + "hash_function_id": self.get_hash_function_id(options), + "paranet_ual": self.get_paranet_ual(options), + "subject_ual": self.get_subject_ual(options), + } + + def get_asset_create_arguments(self, options): + return { + # "blockchain": self.get_blockchain(options), + "endpoint": self.get_endpoint(options), + "port": self.get_port(options), + "max_number_of_retries": self.get_max_number_of_retries(options), + "frequency": self.get_frequency(options), + "epochs_num": self.get_epochs_num(options), + "hash_function_id": self.get_hash_function_id(options), + "score_function_id": self.get_score_function_id(options), + "immutable": self.get_immutable(options), + "token_amount": self.get_token_amount(options), + "auth_token": self.get_auth_token(options), + "payer": self.get_payer(options), + "minimum_number_of_finalization_confirmations": self.get_minimum_number_of_finalization_confirmations( + options + ) + or 3, + "minimum_number_of_node_replications": self.get_minimum_number_of_node_replications( + options + ), + } + + def get_query_arguments(self, options): + return { + "graph_location": self.get_graph_location(options), + "graph_state": self.get_graph_state(options), + "endpoint": self.get_endpoint(options), + "port": self.get_port(options), + "max_number_of_retries": self.get_max_number_of_retries(options), + "frequency": self.get_frequency(options), + "auth_token": self.get_auth_token(options), + "paranet_ual": self.get_paranet_ual(options), + "repository": self.get_repository(options), + } + + def get_endpoint(self, options): + return ( + options.get("endpoint") or self.manager.node_provider.endpoint_uri or None + ) + + # def get_blockchain(self, options): + # return ( + # options.get("blockchain") + # or self.manager.blockchain_provider.blockchain + # or None + # ) + + def get_port(self, options): + return options.get("port") or DefaultParameters.PORT.value + + def get_max_number_of_retries(self, options): + return ( + options.get("max_number_of_retries") + or DefaultParameters.MAX_NUMBER_OF_RETRIES.value + ) + + def get_frequency(self, options): + return options.get("frequency") or DefaultParameters.FREQUENCY.value + + def get_state(self, options): + return options.get("state") or DefaultParameters.STATE.value + + def get_include_metadata(self, options): + return ( + options.get("include_metadata") or DefaultParameters.INCLUDE_METADATA.value + ) + + def get_content_type(self, options): + return options.get("content_type") or DefaultParameters.CONTENT_TYPE.value + + def get_validate(self, options): + return options.get("validate") or DefaultParameters.VALIDATE.value + + def get_output_format(self, options): + return options.get("output_format") or DefaultParameters.OUTPUT_FORMAT.value + + def get_auth_token(self, options): + return options.get("auth_token") or self.manager.node_provider.auth_token + + def get_hash_function_id(self, options): + return ( + options.get("hash_function_id") or DefaultParameters.HASH_FUNCTION_ID.value + ) + + def get_paranet_ual(self, options): + return options.get("paranet_ual") or DefaultParameters.PARANET_UAL.value + + def get_subject_ual(self, options): + return options.get("subject_ual") or DefaultParameters.GET_SUBJECT_UAL.value + + def get_epochs_num(self, options): + return options.get("epochs_num") or None + + def get_immutable(self, options): + return options.get("immutable") or DefaultParameters.IMMUTABLE.value + + def get_token_amount(self, options): + return options.get("token_amount") or None + + def get_payer(self, options): + return options.get("payer") or ZERO_ADDRESS + + def get_minimum_number_of_finalization_confirmations(self, options): + return options.get("minimum_number_of_finalization_confirmations") or None + + def get_minimum_number_of_node_replications(self, options): + return options.get("minimum_number_of_node_replications") or None + + def get_score_function_id(self, options): + enviroment = ( + options.get("environment") + or self.manager.blockchain_provider.environment + or DefaultParameters.ENVIRONMENT.value + ) + blockchain_name = ( + options.get("immutable") or self.manager.blockchain_provider.blockchain_id + ) + + return ( + DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ + self.manager.blockchain_provider.environment + ][blockchain_id], + ) + + def get_graph_location(self, options): + return ( + options.get("graph_location") + or options.get("paranet_ual") + or DefaultParameters.GRAPH_LOCATION.value + ) + + def get_graph_state(self, options): + return options.get("graph_state") or DefaultParameters.GRAPH_STATE.value + + def get_repository(self, options): + return options.get("repository") or None From ebd411ec40a58d8ec0f9839381a537dddfd542d1 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Wed, 8 Jan 2025 17:13:36 +0100 Subject: [PATCH 11/31] Fixes --- dkg/asset.py | 3 --- dkg/utils/node_request.py | 2 +- examples/demo.py | 8 +++++++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 1a0fff3..1a9e1ef 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -451,9 +451,6 @@ def create( minimum_number_of_finalization_confirmations: int, minimum_number_of_node_replications: int, token_amount: Wei | None = None, - # immutable: bool = False, - # content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - # paranet_ual: UAL | None = None, ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: blockchain_id = self.manager.blockchain_provider.blockchain_id diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index ea90f36..5346a22 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -72,7 +72,7 @@ class NodeRequest: finality_status = NodeCall( method=HTTPRequestMethod.GET, path="finality", - params={"ual": str}, + params={"ual": UAL}, ) get = NodeCall( diff --git a/examples/demo.py b/examples/demo.py index 61a3538..3cfe80c 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -132,7 +132,13 @@ def print_json(json_dict: dict): divider() start_time = time.time() -create_asset_result = dkg.asset.create(content, 2, 3, 1, "100") +create_asset_result = dkg.asset.create( + content=content, + epochs_num=2, + minimum_number_of_finalization_confirmations=3, + minimum_number_of_node_replications=1, + token_amount=100, +) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") print_json(create_asset_result) divider() From d9e03a68a5a29b33dd608511500a43f6175c41dd Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Wed, 8 Jan 2025 17:39:36 +0100 Subject: [PATCH 12/31] Removed private key --- examples/demo.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/demo.py b/examples/demo.py index 2d521fd..18ac712 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -24,7 +24,7 @@ blockchain_provider = BlockchainProvider( "testnet", "base:84532", - private_key="db20be6415f83a8a9f0c129bf20ab99ba15bfb90ac5e34f1848f59c20ea9c068", + private_key="", ) dkg = DKG(node_provider, blockchain_provider) From fdeb5a8026acf2714a57ca4815df9f78345f762a Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 10:02:37 +0100 Subject: [PATCH 13/31] Move private key to .env --- dkg/providers/blockchain.py | 8 ++------ examples/demo.py | 1 - 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/dkg/providers/blockchain.py b/dkg/providers/blockchain.py index 321b5f1..d7e6d26 100644 --- a/dkg/providers/blockchain.py +++ b/dkg/providers/blockchain.py @@ -49,7 +49,6 @@ def __init__( environment: Environment, blockchain_id: str, rpc_uri: URI | None = None, - private_key: DataHexStr | None = None, gas_price: Wei | None = None, verify: bool = True, ): @@ -106,11 +105,8 @@ def __init__( } self._init_contracts() - if ( - private_key is not None - or (private_key_env := os.environ.get("PRIVATE_KEY", None)) is not None - ): - self.set_account(private_key or private_key_env) + if private_key := os.environ.get("PRIVATE_KEY"): + self.set_account(private_key) def make_json_rpc_request(self, endpoint: str, args: dict[str, Any] = {}) -> Any: web3_method = getattr(self.w3.eth, endpoint) diff --git a/examples/demo.py b/examples/demo.py index 3cfe80c..3dada0f 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -25,7 +25,6 @@ blockchain_provider = BlockchainProvider( "development", "hardhat1:31337", - private_key="0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", ) dkg = DKG(node_provider, blockchain_provider) From 31ce77327fc1f93d232737452a6b248a1156edc5 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 9 Jan 2025 10:08:23 +0100 Subject: [PATCH 14/31] Code review changes 1 --- dkg/asset.py | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index d1ead06..38baeb9 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -594,31 +594,17 @@ def get(self, ual: UAL, options=None) -> dict: get_public_operation_id, "get", max_number_of_retries, frequency ) - def get_operation_status_object(self, operation_result, operation_id): - - if "errorType" in operation_result.get("data", {}): - - operation_data = { - "status": operation_result["status"], - **operation_result["data"], - } - else: - - operation_data = {"status": operation_result["status"]} - - return {"operationId": operation_id, **operation_data} - if subject_ual: - if get_public_operation_result["data"]: + if get_public_operation_result.get("data"): return { "operation": { "get": self.get_operation_status_object( get_public_operation_result, get_public_operation_id ), }, - "subjectUALPairs": get_public_operation_result["data"], + "subjectUALPairs": get_public_operation_result.get("data"), } - if get_public_operation_result["status"] != "FAILED": + if get_public_operation_result.get("status") != "FAILED": get_public_operation_result["data"] = { "errorType": "DKG_CLIENT_ERROR", "errorMessage": "Unable to find assertion on the network!", @@ -632,11 +618,11 @@ def get_operation_status_object(self, operation_result, operation_id): ), }, } - metadata = get_public_operation_result["data"] - assertion = get_public_operation_result["data"].get("assertion", None) + metadata = get_public_operation_result.get("data") + assertion = get_public_operation_result.get("data").get("assertion", None) if not assertion: - if get_public_operation_result["status"] != "FAILED": + if get_public_operation_result.get("status") != "FAILED": get_public_operation_result["data"] = { "errorType": "DKG_CLIENT_ERROR", "errorMessage": "Unable to find assertion on the network!", From b90875fd77bbb63422949bf1ebcfbc459563ff5c Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 11:49:08 +0100 Subject: [PATCH 15/31] Update hubs --- dkg/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/dkg/constants.py b/dkg/constants.py index 0d12f10..1752645 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -54,13 +54,13 @@ class DefaultParameters(Enum): }, "devnet": { "base:84532": { - "hub": "0xaA849CAC4FA86f6b7484503f3c7a314772AED6d4", + "hub": "0xE043daF4cC8ae2c720ef95fc82574a37a429c40A", "rpc": "https://sepolia.base.org", } }, "testnet": { "base:84532": { - "hub": "0xCca0eA14540588A09c85cD6A6Fc53eA3A7010692", + "hub": "0xf21CE8f8b01548D97DCFb36869f1ccB0814a4e05", "rpc": "https://sepolia.base.org", } }, From c452b0d280658cc4a4391e8a863568ca2cc9fb04 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 11:49:20 +0100 Subject: [PATCH 16/31] Add abis --- dkg/data/interfaces/AskStorage.json | 366 ++++++++++++++++++++++++++++ dkg/data/interfaces/Chronos.json | 202 +++++++++++++++ 2 files changed, 568 insertions(+) create mode 100644 dkg/data/interfaces/AskStorage.json create mode 100644 dkg/data/interfaces/Chronos.json diff --git a/dkg/data/interfaces/AskStorage.json b/dkg/data/interfaces/AskStorage.json new file mode 100644 index 0000000..db93d48 --- /dev/null +++ b/dkg/data/interfaces/AskStorage.json @@ -0,0 +1,366 @@ +[ + { + "inputs": [ + { + "internalType": "address", + "name": "hubAddress", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "msg", + "type": "string" + } + ], + "name": "UnauthorizedAccess", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddressHub", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "decreaseTotalActiveStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "decreaseWeightedActiveAskSum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getAskBounds", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAskLowerBound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getAskUpperBound", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPrevPricePerKbEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPrevStakeWeightedAverageAsk", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getPricePerKbEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getStakeWeightedAverageAsk", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "hub", + "outputs": [ + { + "internalType": "contract Hub", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "amount", + "type": "uint96" + } + ], + "name": "increaseTotalActiveStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "increaseWeightedActiveAskSum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "parametersStorage", + "outputs": [ + { + "internalType": "contract ParametersStorage", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prevTotalActiveStake", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "prevWeightedActiveAskSum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "_prevTotalActiveStake", + "type": "uint96" + } + ], + "name": "setPrevTotalActiveStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_prevWeightedActiveAskSum", + "type": "uint256" + } + ], + "name": "setPrevWeightedActiveAskSum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "_status", + "type": "bool" + } + ], + "name": "setStatus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint96", + "name": "_totalActiveStake", + "type": "uint96" + } + ], + "name": "setTotalActiveStake", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_weightedActiveAskSum", + "type": "uint256" + } + ], + "name": "setWeightedActiveAskSum", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "status", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalActiveStake", + "outputs": [ + { + "internalType": "uint96", + "name": "", + "type": "uint96" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "weightedActiveAskSum", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] diff --git a/dkg/data/interfaces/Chronos.json b/dkg/data/interfaces/Chronos.json new file mode 100644 index 0000000..0824716 --- /dev/null +++ b/dkg/data/interfaces/Chronos.json @@ -0,0 +1,202 @@ +[ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_startTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_epochLength", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "InvalidEpochLength", + "type": "error" + }, + { + "inputs": [], + "name": "InvalidStartTime", + "type": "error" + }, + { + "inputs": [], + "name": "EPOCH_LENGTH", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "START_TIME", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "elapsedTimeInCurrentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + } + ], + "name": "epochAtTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "epochLength", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + } + ], + "name": "hasEpochElapsed", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "isChronosActive", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "startTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "timeUntilNextEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + } + ], + "name": "timestampForEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalElapsedTime", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } +] From 61d31a3f8c6565052cfa7f8a5937842f6d31adab Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 11:49:40 +0100 Subject: [PATCH 17/31] PR suggesstions --- dkg/asset.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 1a9e1ef..1c858d0 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -266,24 +266,26 @@ def finality_status( finality = 0 while finality < required_confirmations and retries <= max_number_of_retries: + try: + response = self._finality_status(ual) + finality = response.get("finality", 0) + if finality >= required_confirmations: + break + except Exception: + finality = 0 + + retries += 1 + if retries > max_number_of_retries: raise Exception( f"Unable to achieve required confirmations. " f"Max number of retries ({max_number_of_retries}) reached." ) - retries += 1 - # Sleep between attempts (except for first try) if retries > 1: time.sleep(frequency) - try: - response = self._finality_status(ual) - finality = response.get("finality", 0) - except Exception: - finality = 0 - return finality def increase_knowledge_collection_allowance( @@ -630,18 +632,17 @@ def create( stake_weighted_average_ask = self._get_stake_weighted_average_ask() # Convert to integers and perform calculation - # Note: In Python we use regular int as it handles arbitrary precision automatically estimated_publishing_cost = ( ( int(stake_weighted_average_ask) * ( int(epochs_num) * int(1e18) - + (int(time_until_next_epoch) * int(1e18)) / int(epoch_length) + + (int(time_until_next_epoch) * int(1e18)) // int(epoch_length) ) * int(dataset_size) ) - / 1024 - / int(1e18) + // 1024 + // int(1e18) ) knowledge_collection_id = None From f1c9d4123db3e27f70a063e72aec203289f3c6e2 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 9 Jan 2025 13:13:45 +0100 Subject: [PATCH 18/31] Code review 2 --- dkg/asset.py | 15 ++-- dkg/constants.py | 19 ++++- dkg/services/input_service.py | 11 +-- examples/demo.py | 140 ++-------------------------------- 4 files changed, 31 insertions(+), 154 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 38baeb9..413a2a8 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -32,6 +32,7 @@ PRIVATE_ASSERTION_PREDICATE, PRIVATE_CURRENT_REPOSITORY, PRIVATE_HISTORICAL_REPOSITORY, + OutputTypes, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -580,9 +581,9 @@ def get(self, ual: UAL, options=None) -> dict: paranet_ual = arguments["paranet_ual"] subject_ual = arguments["subject_ual"] - id_field = f"{ual}:{state}" if state else ual + ual_with_state = f"{ual}:{state}" if state else ual get_public_operation_id: NodeResponseDict = self._get( - id_field, + ual_with_state, content_type, include_metadata, hash_function_id, @@ -602,7 +603,7 @@ def get(self, ual: UAL, options=None) -> dict: get_public_operation_result, get_public_operation_id ), }, - "subjectUALPairs": get_public_operation_result.get("data"), + "subject_ual_pairs": get_public_operation_result.get("data"), } if get_public_operation_result.get("status") != "FAILED": get_public_operation_result["data"] = { @@ -650,13 +651,13 @@ def get(self, ual: UAL, options=None) -> dict: ) formatted_metadata = None - if output_format == "JSON-LD": + if output_format == OutputTypes.JSONLD.value: formatted_assertion = self.to_jsonld(formatted_assertion) if include_metadata: formatted_metadata = self.to_jsonld("\n".join(metadata)) - if output_format == "N-QUADS": + if output_format == OutputTypes.NQUADS.value: formatted_assertion = self.to_nquads( formatted_assertion, "application/n-quads" ) @@ -808,7 +809,7 @@ def get_operation_result( base_delay=frequency, backoff=2, ) - def _get_opeation_results_(): + def _get_operation_results_(): operation_result = self._get_operation_result( operation_id=operation_id, operation=operation, @@ -817,7 +818,7 @@ def _get_opeation_results_(): return operation_result - return _get_opeation_results_() + return _get_operation_results_() def to_jsonld(self, nquads: str): options = { diff --git a/dkg/constants.py b/dkg/constants.py index 8999512..b0352ff 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -23,7 +23,7 @@ class DefaultParameters(Enum): - ENVIRONMENT: str = "mainnet" + ENVIRONMENT: str = "testnet" PORT: int = 8900 FREQUENCY: int = 5 MAX_NUMBER_OF_RETRIES: int = 5 @@ -44,6 +44,11 @@ class DefaultParameters(Enum): GET_SUBJECT_UAL: bool = False +class OutputTypes(Enum): + NQUADS: str = "N-QUADS" + JSONLD: str = "JSON-LD" + + ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { "development": { @@ -64,9 +69,17 @@ class DefaultParameters(Enum): }, "testnet": { "base:84532": { - "hub": "0xCca0eA14540588A09c85cD6A6Fc53eA3A7010692", + "hub": "0xf21CE8f8b01548D97DCFb36869f1ccB0814a4e05", "rpc": "https://sepolia.base.org", - } + }, + "gnosis:10200": { + "hub": "0x2c08AC4B630c009F709521e56Ac385A6af70650f", + "rpc": "https://rpc.chiadochain.net", + }, + "otp:20430": { + "hub": "0xd7d073b560412c6A7F33dD670d323D01061E5DEb", + "rpc": "https://lofar-testnet.origin-trail.network", + }, }, "mainnet": {}, } diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py index a420b77..5213097 100644 --- a/dkg/services/input_service.py +++ b/dkg/services/input_service.py @@ -7,7 +7,6 @@ def __init__(self, manager): def get_asset_get_arguments(self, options): return { - # "blockchain": self.get_blockchain(options), "endpoint": self.get_endpoint(options), "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), @@ -25,7 +24,6 @@ def get_asset_get_arguments(self, options): def get_asset_create_arguments(self, options): return { - # "blockchain": self.get_blockchain(options), "endpoint": self.get_endpoint(options), "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), @@ -64,13 +62,6 @@ def get_endpoint(self, options): options.get("endpoint") or self.manager.node_provider.endpoint_uri or None ) - # def get_blockchain(self, options): - # return ( - # options.get("blockchain") - # or self.manager.blockchain_provider.blockchain - # or None - # ) - def get_port(self, options): return options.get("port") or DefaultParameters.PORT.value @@ -159,4 +150,4 @@ def get_graph_state(self, options): return options.get("graph_state") or DefaultParameters.GRAPH_STATE.value def get_repository(self, options): - return options.get("repository") or None + return options.get("repository") or "dkg" diff --git a/examples/demo.py b/examples/demo.py index 18ac712..4903b79 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -23,7 +23,9 @@ node_provider = NodeHTTPProvider("https://v6-pegasus-node-04.origin-trail.network:8900") blockchain_provider = BlockchainProvider( "testnet", - "base:84532", + # "base:84532", + # "gnosis:10200", + "otp:20430", private_key="", ) @@ -40,146 +42,16 @@ def print_json(json_dict: dict): print(json.dumps(json_dict, indent=4)) -content = { - "public": { - "@context": ["http://schema.org"], - "@id": "uuid:1", - "company": "OT", - "user": {"@id": "uuid:user:1"}, - "city": {"@id": "uuid:belgrade"}, - }, - "private": { - "@context": ["http://schema.org"], - "@graph": [ - {"@id": "uuid:user:1", "name": "Adam", "lastname": "Smith"}, - {"@id": "uuid:belgrade", "title": "Belgrade", "postCode": "11000"}, - ], - }, -} +content = {} -# divider() - -# info_result = dkg.node.info - -# print("======================== NODE INFO RECEIVED") -# print_json(info_result) - divider() -# formatted_assertions = dkg.assertion.format_graph(content) -# print("======================== ASSET FORMATTED") -# print_json(formatted_assertions) - -# divider() - -# public_assertion_id = dkg.assertion.get_public_assertion_id(content) -# print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") -# print(public_assertion_id) - -# divider() - -# public_assertion_size = dkg.assertion.get_size(content) -# print("======================== PUBLIC ASSERTION SIZE CALCULATED") -# print(public_assertion_size) - -# divider() - -# public_assertion_triples_number = dkg.assertion.get_triples_number(content) -# print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") -# print(public_assertion_triples_number) - -# divider() - -# public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) -# print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") -# print(public_assertion_chunks_number) - -# divider() - -# bid_suggestion = dkg.network.get_bid_suggestion( -# public_assertion_id, -# public_assertion_size, -# 2, -# ) -# print("======================== BID SUGGESTION CALCULATED") -# print(bid_suggestion) - -# divider() - -# current_allowance = dkg.asset.get_current_allowance() -# print("======================== GET CURRENT ALLOWANCE") -# print(current_allowance) -# divider() - -# allowance_increase = dkg.asset.increase_allowance(bid_suggestion) -# print("======================== INCREASE ALLOWANCE") -# print(allowance_increase) - -# divider() - -# allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) -# print("======================== DECREASE ALLOWANCE") -# print(allowance_decrease) - -# divider() - -# allowance_set = dkg.asset.set_allowance(bid_suggestion) -# print("======================== SET ALLOWANCE") -# print(allowance_set) - -# divider() - -# create_asset_result = dkg.asset.create(content, 2) -# print("======================== ASSET CREATED") -# print_json(create_asset_result) -# divider() - -# validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) -# print("======================== VALIDATE UAL") -# print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") -# divider() - -# owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) -# print("======================== GET ASSET OWNER") -# print(owner_result) -# divider() - -# get_asset_result = dkg.asset.get(create_asset_result["UAL"]) -# print("======================== ASSET RESOLVED") -# print_json(get_asset_result) -# divider() - -# get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") -# print("======================== ASSET LATEST RESOLVED") -# print_json(get_latest_asset_result) -# divider() - -# get_latest_finalized_asset_result = dkg.asset.get( -# create_asset_result["UAL"], "latest_finalized", "all" -# ) -# print("======================== ASSET LATEST FINALIZED RESOLVED") -# print_json(get_latest_finalized_asset_result) -# divider() - -get_v8_test = dkg.asset.get_v8( - "did:dkg:base:84532/0xd5550173b0f7b8766ab2770e4ba86caf714a5af5/10176" +get_v8_test = dkg.asset.get( + "did:dkg:otp:20430/0xb4c24fc54bc811c2659c477b65da8648e499fd39/2353" ) print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") print(get_v8_test) # print_json(get_v8_test) divider() - -# get_first_state_by_hash = dkg.asset.get( -# create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" -# ) -# print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") -# print_json(get_first_state_by_hash) -# divider() - -# query_result = dkg.graph.query( -# "construct { ?s ?p ?o } where { ?s ?p ?o . ?p ?o }", "privateCurrent" -# ) -# print("======================== QUERY LOCAL CURRENT RESULT") -# print(query_result) From 21571c24ffef9cede938133eaad11416545ecb74 Mon Sep 17 00:00:00 2001 From: IlijaMar Date: Thu, 9 Jan 2025 14:42:20 +0100 Subject: [PATCH 19/31] Code changes 3 --- dkg/asset.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/dkg/asset.py b/dkg/asset.py index 413a2a8..b2f4e65 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -647,7 +647,12 @@ def get(self, ual: UAL, options=None) -> dict: } formatted_assertion = "\n".join( - assertion.get("public", []) + assertion.get("private", []) + assertion.get("public", []) + + ( + assertion.get("private", []) + if isinstance(assertion.get("private", []), list) + else [] + ) ) formatted_metadata = None From 7b4e1687b8114ced618c38a0d4948bfa619b8bde Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 15:35:07 +0100 Subject: [PATCH 20/31] Update demo --- dkg/asset.py | 4 +- examples/demo.py | 104 +---------------------------------------------- 2 files changed, 3 insertions(+), 105 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 1c858d0..48afc4a 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -360,7 +360,7 @@ def create_knowledge_collection( request.get("knowledgeAssetsAmount"), request.get("byteSize"), request.get("epochs"), - int(request.get("tokenAmount")), + request.get("tokenAmount"), request.get("isImmutable"), request.get("paymaster"), request.get("publisherNodeIdentityId"), @@ -657,7 +657,7 @@ def create( ), "byteSize": dataset_size, "epochs": epochs_num, - "tokenAmount": str(estimated_publishing_cost), + "tokenAmount": estimated_publishing_cost, "isImmutable": DefaultParameters.IMMUTABLE.value, "paymaster": DefaultParameters.ZERO_ADDRESS.value, "publisherNodeIdentityId": publisher_node_identity_id, diff --git a/examples/demo.py b/examples/demo.py index 3dada0f..4d3a2e7 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -66,70 +66,6 @@ def print_json(json_dict: dict): divider() -# formatted_assertions = dkg.assertion.format_graph(content) -# print("======================== ASSET FORMATTED") -# print_json(formatted_assertions) - -# divider() - -# public_assertion_id = dkg.assertion.get_public_assertion_id(content) -# print("======================== PUBLIC ASSERTION ID (MERKLE ROOT) CALCULATED") -# print(public_assertion_id) - -# divider() - -# public_assertion_size = dkg.assertion.get_size(content) -# print("======================== PUBLIC ASSERTION SIZE CALCULATED") -# print(public_assertion_size) - -# divider() - -# public_assertion_triples_number = dkg.assertion.get_triples_number(content) -# print("======================== PUBLIC ASSERTION TRIPLES NUMBER CALCULATED") -# print(public_assertion_triples_number) - -# divider() - -# public_assertion_chunks_number = dkg.assertion.get_chunks_number(content) -# print("======================== PUBLIC ASSERTION CHUNKS NUMBER CALCULATED") -# print(public_assertion_chunks_number) - -# divider() - -# bid_suggestion = dkg.network.get_bid_suggestion( -# public_assertion_id, -# public_assertion_size, -# 2, -# ) -# print("======================== BID SUGGESTION CALCULATED") -# print(bid_suggestion) - -# divider() - -# current_allowance = dkg.asset.get_current_allowance() -# print("======================== GET CURRENT ALLOWANCE") -# print(current_allowance) - -# divider() - -# allowance_increase = dkg.asset.increase_allowance(bid_suggestion) -# print("======================== INCREASE ALLOWANCE") -# print(allowance_increase) - -# divider() - -# allowance_decrease = dkg.asset.decrease_allowance(bid_suggestion // 3) -# print("======================== DECREASE ALLOWANCE") -# print(allowance_decrease) - -# divider() - -# allowance_set = dkg.asset.set_allowance(bid_suggestion) -# print("======================== SET ALLOWANCE") -# print(allowance_set) - -divider() - start_time = time.time() create_asset_result = dkg.asset.create( content=content, @@ -140,46 +76,8 @@ def print_json(json_dict: dict): ) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") print_json(create_asset_result) -divider() -# validate_ual = dkg.asset.is_valid_ual(create_asset_result["UAL"]) -# print("======================== VALIDATE UAL") -# print(f"Is {create_asset_result['UAL']} a valid UAL: {validate_ual}") -# divider() - -# owner_result = dkg.asset.get_owner(create_asset_result["UAL"]) -# print("======================== GET ASSET OWNER") -# print(owner_result) -# divider() - -# get_asset_result = dkg.asset.get(create_asset_result["UAL"]) -# print("======================== ASSET RESOLVED") -# print_json(get_asset_result) -# divider() - -# get_latest_asset_result = dkg.asset.get(create_asset_result["UAL"], "latest", "all") -# print("======================== ASSET LATEST RESOLVED") -# print_json(get_latest_asset_result) -# divider() - -# get_latest_finalized_asset_result = dkg.asset.get( -# create_asset_result["UAL"], "latest_finalized", "all" -# ) -# print("======================== ASSET LATEST FINALIZED RESOLVED") -# print_json(get_latest_finalized_asset_result) -# divider() - -# get_first_state_by_index = dkg.asset.get(create_asset_result["UAL"], 0, "all") -# print("======================== ASSET FIRST STATE (GET BY STATE INDEX) RESOLVED") -# print_json(get_first_state_by_index) -# divider() - -# get_first_state_by_hash = dkg.asset.get( -# create_asset_result["UAL"], create_asset_result["publicAssertionId"], "all" -# ) -# print("======================== ASSET FIRST STATE (GET BY STATE HASH) RESOLVED") -# print_json(get_first_state_by_hash) -# divider() +divider() query_operation_result = dkg.graph.query( """ From aa2d662d0e7b79e82a7b8f5efef60591998dea91 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 16:57:52 +0100 Subject: [PATCH 21/31] Merge create query get --- dkg/asset.py | 109 +++++++++++++++------------------- dkg/constants.py | 14 ++++- dkg/graph.py | 47 ++++++++++----- dkg/main.py | 2 +- dkg/services/input_service.py | 44 +++----------- examples/demo.py | 17 +++--- 6 files changed, 109 insertions(+), 124 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index f05ee10..84173df 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -18,7 +18,6 @@ import json import time import math -import re import hashlib from typing import Literal, Type, Dict, Optional, Any from pyld import jsonld @@ -36,28 +35,20 @@ DEFAULT_HASH_FUNCTION_ID, DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS, PRIVATE_ASSERTION_PREDICATE, - PRIVATE_CURRENT_REPOSITORY, - PRIVATE_HISTORICAL_REPOSITORY, PRIVATE_RESOURCE_PREDICATE, PRIVATE_HASH_SUBJECT_PREFIX, CHUNK_BYTE_SIZE, MAX_FILE_SIZE, + DEFAULT_RDF_FORMAT, Operations, - DefaultParameters, OutputTypes, ) from dkg.dataclasses import ( BidSuggestionRange, - KnowledgeAssetContentVisibility, - KnowledgeAssetEnumStates, NodeResponseDict, ) from dkg.exceptions import ( - DatasetOutputFormatNotSupported, - InvalidKnowledgeAsset, - InvalidStateOption, InvalidTokenAmount, - MissingKnowledgeAssetState, OperationNotFinished, ) from dkg.manager import DefaultRequestManager @@ -82,10 +73,7 @@ StoreTypes, validate_operation_status, ) -from dkg.utils.rdf import ( - format_content, - normalize_dataset, -) +from dkg.utils.rdf import format_content from dkg.utils.ual import format_ual, parse_ual import dkg.utils.knowledge_collection_tools as kc_tools import dkg.utils.knowledge_asset_tools as ka_tools @@ -451,11 +439,23 @@ def get_message_signer_address(self, dataset_root: str, signature: dict): def create( self, content: dict[Literal["public", "private"], JSONLD], - epochs_num: int, - minimum_number_of_finalization_confirmations: int, - minimum_number_of_node_replications: int, - token_amount: Wei | None = None, + options: dict = {}, ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: + arguments = self.input_service.get_asset_create_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + epochs_num = arguments.get("epochs_num") + hash_function_id = arguments.get("hash_function_id") + immutable = arguments.get("immutable") + token_amount = arguments.get("token_amount") + payer = arguments.get("payer") + minimum_number_of_finalization_confirmations = arguments.get( + "minimum_number_of_finalization_confirmations" + ) + minimum_number_of_node_replications = arguments.get( + "minimum_number_of_node_replications" + ) blockchain_id = self.manager.blockchain_provider.blockchain_id dataset = {} @@ -573,12 +573,14 @@ def create( dataset_root, dataset, blockchain_id, - DEFAULT_HASH_FUNCTION_ID, + hash_function_id, minimum_number_of_node_replications, )["operationId"] publish_operation_result = self.get_operation_result( - Operations.PUBLISH.value, publish_operation_id, + Operations.PUBLISH.value, + max_number_of_retries, + frequency, ) if publish_operation_result.get( @@ -660,8 +662,8 @@ def create( "byteSize": dataset_size, "epochs": epochs_num, "tokenAmount": estimated_publishing_cost, - "isImmutable": DefaultParameters.IMMUTABLE.value, - "paymaster": DefaultParameters.ZERO_ADDRESS.value, + "isImmutable": immutable, + "paymaster": payer, "publisherNodeIdentityId": publisher_node_identity_id, "publisherNodeR": publisher_node_r, "publisherNodeVS": publisher_node_vs, @@ -914,23 +916,19 @@ def burn(self, ual: UAL) -> dict[str, UAL | TxReceipt]: _get = Method(NodeRequest.get) _query = Method(NodeRequest.query) - def get(self, ual: UAL, options=None) -> dict: - if options is None: - options = {} - + def get(self, ual: UAL, options: dict = {}) -> dict: arguments = self.input_service.get_asset_get_arguments(options) - max_number_of_retries = arguments["max_number_of_retries"] - frequency = arguments["frequency"] - state = arguments["state"] - include_metadata = arguments["include_metadata"] - content_type = arguments["content_type"] - validate = arguments["validate"] - output_format = arguments["output_format"] - auth_token = arguments["auth_token"] - hash_function_id = arguments["hash_function_id"] - paranet_ual = arguments["paranet_ual"] - subject_ual = arguments["subject_ual"] + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + state = arguments.get("state") + include_metadata = arguments.get("include_metadata") + content_type = arguments.get("content_type") + validate = arguments.get("validate") + output_format = arguments.get("output_format") + hash_function_id = arguments.get("hash_function_id") + paranet_ual = arguments.get("paranet_ual") + subject_ual = arguments.get("subject_ual") ual_with_state = f"{ual}:{state}" if state else ual get_public_operation_id: NodeResponseDict = self._get( @@ -943,7 +941,10 @@ def get(self, ual: UAL, options=None) -> dict: )["operationId"] get_public_operation_result = self.get_operation_result( - get_public_operation_id, "get", max_number_of_retries, frequency + get_public_operation_id, + Operations.GET.value, + max_number_of_retries, + frequency, ) if subject_ual: @@ -971,7 +972,7 @@ def get(self, ual: UAL, options=None) -> dict: }, } metadata = get_public_operation_result.get("data") - assertion = get_public_operation_result.get("data").get("assertion", None) + assertion = get_public_operation_result.get("data", {}).get("assertion", None) if not assertion: if get_public_operation_result.get("status") != "FAILED": @@ -993,15 +994,15 @@ def get(self, ual: UAL, options=None) -> dict: is_valid = True # #TODO: Implement assertion validation logic if not is_valid: get_public_operation_result["data"] = { - "errorType": "DKG_CLIENT_ERROR", - "errorMessage": "Calculated root hashes don't match!", + "error_type": "DKG_CLIENT_ERROR", + "error_message": "Calculated root hashes don't match!", } formatted_assertion = "\n".join( assertion.get("public", []) + ( - assertion.get("private", []) - if isinstance(assertion.get("private", []), list) + assertion.get("private") + if isinstance(assertion.get("private"), list) else [] ) ) @@ -1015,11 +1016,11 @@ def get(self, ual: UAL, options=None) -> dict: if output_format == OutputTypes.NQUADS.value: formatted_assertion = self.to_nquads( - formatted_assertion, "application/n-quads" + formatted_assertion, DEFAULT_RDF_FORMAT ) if include_metadata: formatted_metadata = self.to_nquads( - "\n".join(metadata), "application/n-quads" + "\n".join(metadata), DEFAULT_RDF_FORMAT ) result = { @@ -1165,7 +1166,7 @@ def get_operation_result( base_delay=frequency, backoff=2, ) - def _get_operation_results_(): + def retry_get_operation_result(): operation_result = self._get_operation_result( operation_id=operation_id, operation=operation, @@ -1174,7 +1175,7 @@ def _get_operation_results_(): return operation_result - return _get_operation_results_() + return retry_get_operation_result() def to_jsonld(self, nquads: str): options = { @@ -1201,17 +1202,3 @@ def to_nquads(self, content, input_format): except Exception as e: raise ValueError(f"Error processing content: {e}") - - def get_operation_status_object(self, operation_result, operation_id): - if operation_result.get("data", {}).get("errorType"): - operation_data = { - "status": operation_result["status"], - **operation_result["data"], - } - else: - operation_data = {"status": operation_result["status"]} - - return { - "operationId": operation_id, - **operation_data, - } diff --git a/dkg/constants.py b/dkg/constants.py index a318e5d..7aa10a7 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -23,6 +23,16 @@ "https://ontology.origintrail.io/dkg/1.0#privateMerkleRoot" ) +PRIVATE_HASH_SUBJECT_PREFIX = "https://ontology.origintrail.io/dkg/1.0#metadata-hash:" + +PRIVATE_RESOURCE_PREDICATE = ( + "https://ontology.origintrail.io/dkg/1.0#representsPrivateResource" +) + +CHUNK_BYTE_SIZE = 32 + +MAX_FILE_SIZE = 10000000 + class DefaultParameters(Enum): ENVIRONMENT: str = "testnet" @@ -36,14 +46,13 @@ class DefaultParameters(Enum): STATE: None = None INCLUDE_METADATA: bool = False CONTENT_TYPE: str = "all" - GRAPH_LOCATION: str = "LOCAL_KG" - GRAPH_STATE: str = "CURRENT" HANDLE_NOT_MINED_ERROR: bool = False SIMULATE_TXS: bool = False FORCE_REPLACE_TXS: bool = False GAS_LIMIT_MULTIPLIER: int = 1 PARANET_UAL: None = None GET_SUBJECT_UAL: bool = False + REPOSITORY: str = "dkg" class OutputTypes(Enum): @@ -86,7 +95,6 @@ class OutputTypes(Enum): "mainnet": {}, } -DEFAULT_HASH_FUNCTION_ID = 1 DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS = { "development": {"hardhat1:31337": 2, "hardhat2:31337": 2, "otp:2043": 2}, "devnet": { diff --git a/dkg/graph.py b/dkg/graph.py index 025b0fb..3c7fa28 100644 --- a/dkg/graph.py +++ b/dkg/graph.py @@ -25,11 +25,13 @@ from dkg.types import NQuads from dkg.utils.decorators import retry from dkg.utils.node_request import NodeRequest, validate_operation_status +from dkg.constants import Operations class Graph(Module): - def __init__(self, manager: DefaultRequestManager): + def __init__(self, manager: DefaultRequestManager, input_service): self.manager = manager + self.input_service = input_service _query = Method(NodeRequest.query) _get_operation_result = Method(NodeRequest.get_operation_result) @@ -37,28 +39,43 @@ def __init__(self, manager: DefaultRequestManager): def query( self, query: str, - repository: str | None = None, - paranet_ual: str | None = None, + options: dict = {}, ) -> NQuads: + arguments = self.input_service.get_query_arguments(options) + + max_number_of_retries = arguments.get("max_number_of_retries") + frequency = arguments.get("frequency") + paranet_ual = arguments.get("paranet_ual") + repository = arguments.get("repository") + parsed_query = parseQuery(query) query_type = parsed_query[1].name.replace("Query", "").upper() - operation_id: NodeResponseDict = self._query(query, query_type, repository, paranet_ual)[ - "operationId" - ] - operation_result = self.get_operation_result(operation_id, "query") + operation_id: NodeResponseDict = self._query( + query, query_type, repository, paranet_ual + )["operationId"] + operation_result = self.get_operation_result( + operation_id, Operations.QUERY.value, max_number_of_retries, frequency + ) return operation_result["data"] - @retry(catch=OperationNotFinished, max_retries=5, base_delay=1, backoff=2) def get_operation_result( - self, operation_id: str, operation: str - ) -> NodeResponseDict: - operation_result = self._get_operation_result( - operation_id=operation_id, - operation=operation, + self, operation_id: str, operation: str, max_retries: int, frequency: int + ): + @retry( + catch=OperationNotFinished, + max_retries=max_retries, + base_delay=frequency, + backoff=2, ) + def retry_get_operation_result(): + operation_result = self._get_operation_result( + operation_id=operation_id, + operation=operation, + ) + validate_operation_status(operation_result) - validate_operation_status(operation_result) + return operation_result - return operation_result + return retry_get_operation_result() diff --git a/dkg/main.py b/dkg/main.py index ec79e91..00fd427 100644 --- a/dkg/main.py +++ b/dkg/main.py @@ -66,7 +66,7 @@ def __init__( "paranet": Paranet(self.manager), "network": Network(self.manager), "node": Node(self.manager), - "graph": Graph(self.manager), + "graph": Graph(self.manager, self.input_service), } self._attach_modules(modules) diff --git a/dkg/services/input_service.py b/dkg/services/input_service.py index 5213097..9efb31a 100644 --- a/dkg/services/input_service.py +++ b/dkg/services/input_service.py @@ -1,4 +1,8 @@ -from dkg.constants import DefaultParameters, ZERO_ADDRESS +from dkg.constants import ( + DefaultParameters, + ZERO_ADDRESS, + DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS, +) class InputService: @@ -7,8 +11,6 @@ def __init__(self, manager): def get_asset_get_arguments(self, options): return { - "endpoint": self.get_endpoint(options), - "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), "frequency": self.get_frequency(options), "state": self.get_state(options), @@ -16,7 +18,6 @@ def get_asset_get_arguments(self, options): "content_type": self.get_content_type(options), "validate": self.get_validate(options), "output_format": self.get_output_format(options), - "auth_token": self.get_auth_token(options), "hash_function_id": self.get_hash_function_id(options), "paranet_ual": self.get_paranet_ual(options), "subject_ual": self.get_subject_ual(options), @@ -24,8 +25,6 @@ def get_asset_get_arguments(self, options): def get_asset_create_arguments(self, options): return { - "endpoint": self.get_endpoint(options), - "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), "frequency": self.get_frequency(options), "epochs_num": self.get_epochs_num(options), @@ -33,7 +32,6 @@ def get_asset_create_arguments(self, options): "score_function_id": self.get_score_function_id(options), "immutable": self.get_immutable(options), "token_amount": self.get_token_amount(options), - "auth_token": self.get_auth_token(options), "payer": self.get_payer(options), "minimum_number_of_finalization_confirmations": self.get_minimum_number_of_finalization_confirmations( options @@ -46,25 +44,12 @@ def get_asset_create_arguments(self, options): def get_query_arguments(self, options): return { - "graph_location": self.get_graph_location(options), - "graph_state": self.get_graph_state(options), - "endpoint": self.get_endpoint(options), - "port": self.get_port(options), "max_number_of_retries": self.get_max_number_of_retries(options), "frequency": self.get_frequency(options), - "auth_token": self.get_auth_token(options), "paranet_ual": self.get_paranet_ual(options), "repository": self.get_repository(options), } - def get_endpoint(self, options): - return ( - options.get("endpoint") or self.manager.node_provider.endpoint_uri or None - ) - - def get_port(self, options): - return options.get("port") or DefaultParameters.PORT.value - def get_max_number_of_retries(self, options): return ( options.get("max_number_of_retries") @@ -91,9 +76,6 @@ def get_validate(self, options): def get_output_format(self, options): return options.get("output_format") or DefaultParameters.OUTPUT_FORMAT.value - def get_auth_token(self, options): - return options.get("auth_token") or self.manager.node_provider.auth_token - def get_hash_function_id(self, options): return ( options.get("hash_function_id") or DefaultParameters.HASH_FUNCTION_ID.value @@ -134,20 +116,8 @@ def get_score_function_id(self, options): ) return ( - DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], + DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[enviroment][blockchain_name], ) - def get_graph_location(self, options): - return ( - options.get("graph_location") - or options.get("paranet_ual") - or DefaultParameters.GRAPH_LOCATION.value - ) - - def get_graph_state(self, options): - return options.get("graph_state") or DefaultParameters.GRAPH_STATE.value - def get_repository(self, options): - return options.get("repository") or "dkg" + return options.get("repository") or DefaultParameters.REPOSITORY.value diff --git a/examples/demo.py b/examples/demo.py index d07eaa4..ea2ab80 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -69,19 +69,22 @@ def print_json(json_dict: dict): start_time = time.time() create_asset_result = dkg.asset.create( content=content, - epochs_num=2, - minimum_number_of_finalization_confirmations=3, - minimum_number_of_node_replications=1, - token_amount=100, + options={ + "epochs_num": 2, + "minimum_number_of_finalization_confirmations": 3, + "minimum_number_of_node_replications": 1, + "token_amount": 100, + }, ) print(f"======================== ASSET CREATED in {time.time() - start_time} seconds") print_json(create_asset_result) divider() -get_v8_test = dkg.asset.get( - "did:dkg:otp:20430/0xb4c24fc54bc811c2659c477b65da8648e499fd39/2353" -) +start_time = time.time() +get_v8_test = dkg.asset.get(create_asset_result.get("UAL")) +print(f"======================== ASSET GET in {time.time() - start_time} seconds") +print_json(get_v8_test) divider() From 089f5dd6af19e682fdb7587faa66cdaf557965aa Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Thu, 9 Jan 2025 17:34:50 +0100 Subject: [PATCH 22/31] Add constants --- dkg/asset.py | 8 ++++---- dkg/constants.py | 18 ++++++++++++++++++ dkg/network.py | 4 ++-- dkg/utils/blockchain_request.py | 6 ------ 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 84173df..fe6b601 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -32,7 +32,6 @@ from hexbytes import HexBytes from dkg.constants import ( - DEFAULT_HASH_FUNCTION_ID, DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS, PRIVATE_ASSERTION_PREDICATE, PRIVATE_RESOURCE_PREDICATE, @@ -42,6 +41,7 @@ DEFAULT_RDF_FORMAT, Operations, OutputTypes, + DefaultParameters, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -746,7 +746,7 @@ def local_store( public_assertion_metadata["size"], content_asset_storage_address, public_assertion_id, - DEFAULT_HASH_FUNCTION_ID, + DefaultParameters.HASH_FUNCTION_ID.value, token_amount or BidSuggestionRange.LOW, )["bidSuggestion"] ) @@ -1065,7 +1065,7 @@ def extend_storing_period( latest_finalized_state_size, content_asset_storage_address, latest_finalized_state, - DEFAULT_HASH_FUNCTION_ID, + DefaultParameters.HASH_FUNCTION_ID.value, token_amount or BidSuggestionRange.LOW, )["bidSuggestion"] ) @@ -1124,7 +1124,7 @@ def add_tokens( latest_finalized_state_size, content_asset_storage_address, latest_finalized_state, - DEFAULT_HASH_FUNCTION_ID, + DefaultParameters.HASH_FUNCTION_ID.value, token_amount or BidSuggestionRange.LOW, )["bidSuggestion"] ) - sum(agreement_data.tokensInfo) diff --git a/dkg/constants.py b/dkg/constants.py index 7aa10a7..ceef7eb 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -60,6 +60,24 @@ class OutputTypes(Enum): JSONLD: str = "JSON-LD" +class Environments(Enum): + DEVELOPMENT: str = "development" + DEVNET: str = "devnet" + TESTNET: str = "testnet" + MAINNET: str = "mainnet" + + +class Blockchains(Enum): + HARDHAT_1: str = "hardhat1:31337" + HARDHAT_2: str = "hardhat2:31337" + BASE_DEVNET: str = "base:84532" + GNOSIS_DEVNET: str = "gnosis:10200" + NEUROWEB_DEVNET: str = "otp:20430" + BASE_TESTNET: str = "base:84532" + GNOSIS_TESTNET: str = "gnosis:10200" + NEUROWEB_TESTNET: str = "otp:20430" + + ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" BLOCKCHAINS = { "development": { diff --git a/dkg/network.py b/dkg/network.py index 47f4fbc..405baa2 100644 --- a/dkg/network.py +++ b/dkg/network.py @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -from dkg.constants import DEFAULT_HASH_FUNCTION_ID +from dkg.constants import DefaultParameters from dkg.dataclasses import BidSuggestionRange from dkg.manager import DefaultRequestManager from dkg.method import Method @@ -50,7 +50,7 @@ def get_bid_suggestion( size_in_bytes, content_asset_storage_address, public_assertion_id, - DEFAULT_HASH_FUNCTION_ID, + DefaultParameters.HASH_FUNCTION_ID.value, range, ) diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index f351765..f8d1bd8 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -462,9 +462,3 @@ class BlockchainRequest: "knowledgeAssetArgs": dict, }, ) - - decrease_allowance = ContractTransaction( - contract="Token", - function="decreaseAllowance", - args={"spender": Address, "subtractedValue": int}, - ) From e2278165cb2002685a14919cd805397b71825912 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 09:33:51 +0100 Subject: [PATCH 23/31] Update demo --- examples/demo.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/demo.py b/examples/demo.py index ea2ab80..77e35f4 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -20,11 +20,12 @@ from dkg import DKG from dkg.providers import BlockchainProvider, NodeHTTPProvider +from dkg.constants import Environments, Blockchains node_provider = NodeHTTPProvider(endpoint_uri="http://localhost:8900", api_version="v1") blockchain_provider = BlockchainProvider( - "development", - "hardhat1:31337", + Environments.DEVELOPMENT.value, + Blockchains.HARDHAT_1.value, ) dkg = DKG(node_provider, blockchain_provider) From 4c5e9e88479e24fe817f8cdf390cae7f6dcf2460 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 11:15:00 +0100 Subject: [PATCH 24/31] Fix decrease allowance issue --- dkg/asset.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index fe6b601..09b1f45 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -42,6 +42,7 @@ Operations, OutputTypes, DefaultParameters, + ZERO_ADDRESS, ) from dkg.dataclasses import ( BidSuggestionRange, @@ -279,7 +280,7 @@ def finality_status( return finality def increase_knowledge_collection_allowance( - self, sender: str, token_amount: str + self, sender: str, token_amount: str, knowledge_collection_address: str ) -> AllowanceResult: """ Increases the allowance for knowledge collection if necessary. @@ -291,8 +292,6 @@ def increase_knowledge_collection_allowance( Returns: AllowanceResult containing whether allowance was increased and the gap """ - knowledge_collection_address = self._get_contract_address("KnowledgeCollection") - allowance = self._get_current_allowance(sender, knowledge_collection_address) allowance_gap = int(token_amount) - int(allowance) @@ -327,18 +326,19 @@ def create_knowledge_collection( BlockchainError: If the collection creation fails """ sender = self.manager.blockchain_provider.account.address - service_agreement_v1_address = None + knowledge_collection_address = self._get_contract_address("KnowledgeCollection") allowance_increased = False allowance_gap = 0 try: # Handle allowance - if request.get("payer"): + if request.get("paymaster") and request.get("paymaster") != ZERO_ADDRESS: pass else: allowance_result = self.increase_knowledge_collection_allowance( sender=sender, token_amount=request.get("tokenAmount"), + knowledge_collection_address=knowledge_collection_address, ) allowance_increased = allowance_result.allowance_increased allowance_gap = allowance_result.allowance_gap @@ -384,7 +384,7 @@ def create_knowledge_collection( except Exception as e: if allowance_increased: - self._decrease_allowance(service_agreement_v1_address, allowance_gap) + self._decrease_allowance(knowledge_collection_address, allowance_gap) raise e def process_content(self, content: str) -> list: From 1397a896ebc93b20682755e1aa851daeb61a7205 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 12:55:15 +0100 Subject: [PATCH 25/31] remove local store from constants --- dkg/constants.py | 1 - 1 file changed, 1 deletion(-) diff --git a/dkg/constants.py b/dkg/constants.py index ceef7eb..515b108 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -139,7 +139,6 @@ class Blockchains(Enum): class Operations(Enum): PUBLISH = "publish" GET = "get" - LOCAL_STORE = "local-store" QUERY = "query" PUBLISH_PARANET = "publishParanet" FINALITY = "finality" From 4f6534db822b357da1711019d2d06f10646e6f58 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 13:32:37 +0100 Subject: [PATCH 26/31] Update demo jsonld and query --- examples/demo.py | 84 ++++++++++++++---------------------------------- 1 file changed, 25 insertions(+), 59 deletions(-) diff --git a/examples/demo.py b/examples/demo.py index 77e35f4..4b56b6e 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -42,22 +42,30 @@ def print_json(json_dict: dict): content = { - "private": { - "@context": "https://www.schema.org", - "@id": "urn:eu-pp:safety-test:3oRIwPtUOJapwNSAGZTzCOWR9bEo", - "@type": "ProductSafetyTest", - "testType": "Functional Safety Test", - "testResults": "Fail", - "relatedProduct": [ - { - "@id": "urn:epc:id:sgtin:59G1yu8uivSRKLLu", - "name": "59G1yu8uivSRKLLu", + "public": { + "@context": "https://schema.org", + "@id": "https://ford.mustang/2024", + "@type": "Car", + "name": "Ford Mustang", + "brand": {"@type": "Brand", "name": "Ford"}, + "model": "Mustang", + "manufacturer": {"@type": "Organization", "name": "Ford Motor Company"}, + "fuelType": "Gasoline", + "numberOfDoors": 2, + "vehicleEngine": { + "@type": "EngineSpecification", + "engineType": "V8", + "enginePower": { + "@type": "QuantitativeValue", + "value": "450", + "unitCode": "BHP", }, - ], - }, + }, + "driveWheelConfiguration": "RWD", + "speed": {"@type": "QuantitativeValue", "value": "240", "unitCode": "KMH"}, + } } - divider() info_result = dkg.node.info @@ -91,54 +99,12 @@ def print_json(json_dict: dict): query_operation_result = dkg.graph.query( """ - PREFIX gs1: - PREFIX schema: - SELECT ?recipeNameRaw ?baseUal - WHERE { - ?recipe a schema:Recipe ; - GRAPH ?ual { - ?recipe schema:name ?recipeNameRaw ; - } - FILTER (STRSTARTS(STR(?ual), "did:dkg:base:84532/0x4e8ebfce9a0f4be374709f1ef2791e8ca6371ecb/")) - BIND (REPLACE(STR(?ual), "(did:dkg:base:[^/]+/[^/]+/[^/]+)(/.*)?", "$1") AS ?baseUal) - } - """ -) -print("======================== ASSET QUERY") -print(query_operation_result) - -divider() - -query_operation_result = dkg.graph.query( - """ - CONSTRUCT { ?s ?p ?o .} - WHERE { - GRAPH ?g { ?s ?p ?o . } - VALUES ?g { - - - } - } - """ -) -print("======================== ASSET QUERY") -print(query_operation_result) - -divider() - -query_operation_result = dkg.graph.query( - """ - CONSTRUCT { ?s ?p ?o . } + PREFIX SCHEMA: + SELECT ?s ?modelName WHERE { - { - GRAPH { ?s ?p ?o . } - } - UNION - { - GRAPH { ?s ?p ?o . } - } + ?s schema:model ?modelName . } """ ) print("======================== ASSET QUERY") -print(query_operation_result) +print_json(query_operation_result) From f22a5c2baf3a9142ca6b1647a59fa65fd600bac4 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 13:59:07 +0100 Subject: [PATCH 27/31] Update demo --- examples/demo.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/demo.py b/examples/demo.py index 4b56b6e..b802045 100644 --- a/examples/demo.py +++ b/examples/demo.py @@ -91,9 +91,9 @@ def print_json(json_dict: dict): divider() start_time = time.time() -get_v8_test = dkg.asset.get(create_asset_result.get("UAL")) +get_result = dkg.asset.get(create_asset_result.get("UAL")) print(f"======================== ASSET GET in {time.time() - start_time} seconds") -print_json(get_v8_test) +print_json(get_result) divider() From 4ee73c0beb37a743cfff6eada8de6adab75f78c5 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 15:25:19 +0100 Subject: [PATCH 28/31] Remove local_store, service_agreeement functions and add_tokens --- dkg/asset.py | 265 +------------------------------- dkg/utils/blockchain_request.py | 21 --- dkg/utils/node_request.py | 7 +- 3 files changed, 3 insertions(+), 290 deletions(-) diff --git a/dkg/asset.py b/dkg/asset.py index 09b1f45..70b57d9 100644 --- a/dkg/asset.py +++ b/dkg/asset.py @@ -17,13 +17,11 @@ import json import time -import math import hashlib -from typing import Literal, Type, Dict, Optional, Any +from typing import Literal, Dict, Optional, Any from pyld import jsonld from web3 import Web3 from web3.constants import ADDRESS_ZERO -from web3.exceptions import ContractLogicError from web3.types import TxReceipt from itertools import chain from eth_abi.packed import encode_packed @@ -32,7 +30,6 @@ from hexbytes import HexBytes from dkg.constants import ( - DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS, PRIVATE_ASSERTION_PREDICATE, PRIVATE_RESOURCE_PREDICATE, PRIVATE_HASH_SUBJECT_PREFIX, @@ -49,32 +46,23 @@ NodeResponseDict, ) from dkg.exceptions import ( - InvalidTokenAmount, OperationNotFinished, ) from dkg.manager import DefaultRequestManager from dkg.method import Method from dkg.module import Module -from dkg.types import JSONLD, UAL, Address, AgreementData, HexStr, Wei +from dkg.types import JSONLD, UAL, Address, HexStr, Wei from dkg.utils.blockchain_request import ( BlockchainRequest, KnowledgeCollectionResult, AllowanceResult, ) from dkg.utils.decorators import retry -from dkg.utils.merkle import MerkleTree, hash_assertion_with_indexes -from dkg.utils.metadata import ( - generate_agreement_id, - generate_assertion_metadata, - generate_keyword, -) from dkg.utils.node_request import ( NodeRequest, OperationStatus, - StoreTypes, validate_operation_status, ) -from dkg.utils.rdf import format_content from dkg.utils.ual import format_ual, parse_ual import dkg.utils.knowledge_collection_tools as kc_tools import dkg.utils.knowledge_asset_tools as ka_tools @@ -152,62 +140,10 @@ def is_valid_ual(self, ual: UAL) -> bool: _get_contract_address = Method(BlockchainRequest.get_contract_address) _get_current_allowance = Method(BlockchainRequest.allowance) - - def get_current_allowance(self, spender: Address | None = None) -> Wei: - if spender is None: - spender = self._get_contract_address("ServiceAgreementV1") - - return int( - self._get_current_allowance( - self.manager.blockchain_provider.account.address, spender - ) - ) - _increase_allowance = Method(BlockchainRequest.increase_allowance) _decrease_allowance = Method(BlockchainRequest.decrease_allowance) - - def set_allowance(self, token_amount: Wei, spender: Address | None = None) -> Wei: - if spender is None: - spender = self._get_contract_address("ServiceAgreementV1") - - current_allowance = self.get_current_allowance(spender) - - allowance_difference = token_amount - current_allowance - - if allowance_difference > 0: - self._increase_allowance(spender, allowance_difference) - elif allowance_difference < 0: - self._decrease_allowance(spender, -allowance_difference) - - return allowance_difference - - def increase_allowance( - self, token_amount: Wei, spender: Address | None = None - ) -> Wei: - if spender is None: - spender = self._get_contract_address("ServiceAgreementV1") - - self._increase_allowance(spender, token_amount) - - return token_amount - - def decrease_allowance( - self, token_amount: Wei, spender: Address | None = None - ) -> Wei: - if spender is None: - spender = self._get_contract_address("ServiceAgreementV1") - - current_allowance = self.get_current_allowance(spender) - subtracted_value = min(token_amount, current_allowance) - - self._decrease_allowance(spender, subtracted_value) - - return subtracted_value - _chain_id = Method(BlockchainRequest.chain_id) - _get_asset_storage_address = Method(BlockchainRequest.get_asset_storage_address) - _create = Method(BlockchainRequest.create_asset) _mint_paranet_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) _key_is_operational_wallet = Method(BlockchainRequest.key_is_operational_wallet) _time_until_next_epoch = Method(BlockchainRequest.time_until_next_epoch) @@ -216,13 +152,10 @@ def decrease_allowance( BlockchainRequest.get_stake_weighted_average_ask ) _get_bid_suggestion = Method(NodeRequest.bid_suggestion) - _local_store = Method(NodeRequest.local_store) _publish = Method(NodeRequest.publish) _finality_status = Method(NodeRequest.finality_status) - _create_knowledge_collection = Method(BlockchainRequest.create_knowledge_collection) _mint_knowledge_asset = Method(BlockchainRequest.mint_knowledge_asset) - _decrease_allowance = Method(BlockchainRequest.decrease_allowance) def get_operation_status_object( self, operation_result: Dict[str, Any], operation_id: str @@ -716,133 +649,6 @@ def create( ) ) - def local_store( - self, - content: dict[Literal["public", "private"], JSONLD], - epochs_number: int, - token_amount: Wei | None = None, - immutable: bool = False, - content_type: Literal["JSON-LD", "N-Quads"] = "JSON-LD", - paranet_ual: UAL | None = None, - ) -> dict[str, UAL | HexStr | dict[str, dict[str, str] | TxReceipt]]: - blockchain_id = self.manager.blockchain_provider.blockchain_id - assertions = format_content(content, content_type) - - public_assertion_id = MerkleTree( - hash_assertion_with_indexes(assertions["public"]), - sort_pairs=True, - ).root - public_assertion_metadata = generate_assertion_metadata(assertions["public"]) - - content_asset_storage_address = self._get_asset_storage_address( - "ContentAssetStorage" - ) - - if token_amount is None: - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_number, - public_assertion_metadata["size"], - content_asset_storage_address, - public_assertion_id, - DefaultParameters.HASH_FUNCTION_ID.value, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - - current_allowance = self.get_current_allowance() - if is_allowance_increased := current_allowance < token_amount: - self.increase_allowance(token_amount) - - result = {"publicAssertionId": public_assertion_id, "operation": {}} - - try: - receipt: TxReceipt = self._create( - { - "assertionId": Web3.to_bytes(hexstr=public_assertion_id), - "size": public_assertion_metadata["size"], - "triplesNumber": public_assertion_metadata["triples_number"], - "chunksNumber": public_assertion_metadata["chunks_number"], - "tokenAmount": token_amount, - "epochsNumber": epochs_number, - "scoreFunctionId": DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS[ - self.manager.blockchain_provider.environment - ][blockchain_id], - "immutable_": immutable, - } - ) - except ContractLogicError as err: - if is_allowance_increased: - self.decrease_allowance(token_amount) - raise err - - events = self.manager.blockchain_provider.decode_logs_event( - receipt, - "ContentAsset", - "AssetMinted", - ) - token_id = events[0].args["tokenId"] - - result["UAL"] = format_ual( - blockchain_id, content_asset_storage_address, token_id - ) - result["operation"]["mintKnowledgeAsset"] = json.loads(Web3.to_json(receipt)) - - assertions_list = [ - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": public_assertion_id, - "assertion": assertions["public"], - "storeType": StoreTypes.TRIPLE_PARANET, - "paranetUAL": paranet_ual, - } - ] - - if content.get("private", None): - assertions_list.append( - { - "blockchain": blockchain_id, - "contract": content_asset_storage_address, - "tokenId": token_id, - "assertionId": MerkleTree( - hash_assertion_with_indexes(assertions["private"]), - sort_pairs=True, - ).root, - "assertion": assertions["private"], - "storeType": StoreTypes.TRIPLE_PARANET, - "paranetUAL": paranet_ual, - } - ) - - operation_id = self._local_store(assertions_list)["operationId"] - operation_result = self.get_operation_result(operation_id, "local-store") - - result["operation"]["localStore"] = { - "operationId": operation_id, - "status": operation_result["status"], - } - - if operation_result["status"] == OperationStatus.COMPLETED: - parsed_paranet_ual = parse_ual(paranet_ual) - paranet_knowledge_asset_storage, paranet_knowledge_asset_token_id = ( - parsed_paranet_ual["contract_address"], - parsed_paranet_ual["token_id"], - ) - - receipt: TxReceipt = self._submit_knowledge_asset( - paranet_knowledge_asset_storage, - paranet_knowledge_asset_token_id, - content_asset_storage_address, - token_id, - ) - - result["operation"]["submitToParanet"] = json.loads(Web3.to_json(receipt)) - - return result - _submit_knowledge_asset = Method(BlockchainRequest.submit_knowledge_asset) def submit_to_paranet( @@ -1081,80 +887,13 @@ def extend_storing_period( _get_block = Method(BlockchainRequest.get_block) - _get_service_agreement_data = Method(BlockchainRequest.get_service_agreement_data) _get_assertion_size = Method(BlockchainRequest.get_assertion_size) - _add_tokens = Method(BlockchainRequest.increase_asset_token_amount) - - def add_tokens( - self, - ual: UAL, - token_amount: Wei | None = None, - ) -> dict[str, UAL | TxReceipt]: - parsed_ual = parse_ual(ual) - blockchain_id, content_asset_storage_address, token_id = ( - parsed_ual["blockchain"], - parsed_ual["contract_address"], - parsed_ual["token_id"], - ) - - if token_amount is None: - agreement_id = self.get_agreement_id( - content_asset_storage_address, token_id - ) - # TODO: Dynamic types for namedtuples? - agreement_data: Type[AgreementData] = self._get_service_agreement_data( - agreement_id - ) - - timestamp_now = self._get_block("latest")["timestamp"] - current_epoch = math.floor( - (timestamp_now - agreement_data.startTime) / agreement_data.epochLength - ) - epochs_left = agreement_data.epochsNumber - current_epoch - - latest_finalized_state = self._get_latest_assertion_id(token_id) - latest_finalized_state_size = self._get_assertion_size( - latest_finalized_state - ) - - token_amount = int( - self._get_bid_suggestion( - blockchain_id, - epochs_left, - latest_finalized_state_size, - content_asset_storage_address, - latest_finalized_state, - DefaultParameters.HASH_FUNCTION_ID.value, - token_amount or BidSuggestionRange.LOW, - )["bidSuggestion"] - ) - sum(agreement_data.tokensInfo) - - if token_amount <= 0: - raise InvalidTokenAmount( - "Token amount is bigger than default suggested amount, " - "please specify exact token_amount if you still want to add " - "more tokens!" - ) - - receipt: TxReceipt = self._add_tokens(token_id, token_amount) - - return { - "UAL": ual, - "operation": json.loads(Web3.to_json(receipt)), - } def get_owner(self, ual: UAL) -> Address: token_id = parse_ual(ual)["token_id"] return self._owner(token_id) - _get_assertion_id_by_index = Method(BlockchainRequest.get_assertion_id_by_index) - - def get_agreement_id(self, contract_address: Address, token_id: int) -> HexStr: - first_assertion_id = self._get_assertion_id_by_index(token_id, 0) - keyword = generate_keyword(contract_address, first_assertion_id) - return generate_agreement_id(contract_address, token_id, keyword) - _get_operation_result = Method(NodeRequest.get_operation_result) def get_operation_result( diff --git a/dkg/utils/blockchain_request.py b/dkg/utils/blockchain_request.py index f8d1bd8..3b4beda 100644 --- a/dkg/utils/blockchain_request.py +++ b/dkg/utils/blockchain_request.py @@ -119,11 +119,6 @@ class BlockchainRequest: args={"spender": Address, "subtractedValue": Wei}, ) - create_asset = ContractTransaction( - contract="ContentAsset", - function="createAsset", - args={"args": dict[str, bytes | int | Wei | bool]}, - ) burn_asset = ContractTransaction( contract="ContentAsset", function="burnAsset", @@ -134,11 +129,6 @@ class BlockchainRequest: function="extendAssetStoringPeriod", args={"tokenId": int, "epochsNumber": int, "tokenAmount": int}, ) - increase_asset_token_amount = ContractTransaction( - contract="ContentAsset", - function="increaseAssetTokenAmount", - args={"tokenId": int, "tokenAmount": int}, - ) transfer_asset = ContractTransaction( contract="ContentAssetStorage", @@ -150,11 +140,6 @@ class BlockchainRequest: function="getAssertionIds", args={"tokenId": int}, ) - get_assertion_id_by_index = ContractCall( - contract="ContentAssetStorage", - function="getAssertionIdByIndex", - args={"tokenId": int, "index": int}, - ) get_latest_assertion_id = ContractCall( contract="ContentAssetStorage", function="getLatestAssertionId", @@ -172,12 +157,6 @@ class BlockchainRequest: args={"tokenId": int}, ) - get_service_agreement_data = ContractCall( - contract="ServiceAgreementStorageProxy", - function="getAgreementData", - args={"agreementId": bytes | HexStr}, - ) - get_assertion_size = ContractCall( contract="AssertionStorage", function="getAssertionSize", diff --git a/dkg/utils/node_request.py b/dkg/utils/node_request.py index a95d983..e7f937f 100644 --- a/dkg/utils/node_request.py +++ b/dkg/utils/node_request.py @@ -21,7 +21,7 @@ from dkg.dataclasses import BidSuggestionRange, HTTPRequestMethod from dkg.exceptions import OperationFailed, OperationNotFinished -from dkg.types import AutoStrEnumUpperCase, UAL, Address, DataHexStr, NQuads +from dkg.types import AutoStrEnumUpperCase, UAL, Address, DataHexStr @dataclass @@ -52,11 +52,6 @@ class NodeRequest: path="{operation}/{operation_id}", ) - local_store = NodeCall( - method=HTTPRequestMethod.POST, - path="local-store", - data=list[dict[str, str | Address | NQuads]], - ) publish = NodeCall( method=HTTPRequestMethod.POST, path="publish", From 8579b92ef2b14849b6c8aee9f86863ac09ecfb0e Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 15:33:52 +0100 Subject: [PATCH 29/31] Add mainnet info to constants --- dkg/constants.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/dkg/constants.py b/dkg/constants.py index 515b108..2f0dfdf 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -76,6 +76,9 @@ class Blockchains(Enum): BASE_TESTNET: str = "base:84532" GNOSIS_TESTNET: str = "gnosis:10200" NEUROWEB_TESTNET: str = "otp:20430" + BASE_MAINNET: str = "base:8453" + GNOSIS_MAINNET: str = "gnosis:100" + NEUROWEB_MAINNET: str = "otp:2043" ZERO_ADDRESS = "0x0000000000000000000000000000000000000000" @@ -110,7 +113,20 @@ class Blockchains(Enum): "rpc": "https://lofar-testnet.origin-trail.network", }, }, - "mainnet": {}, + "mainnet": { + "base:8453": { + "hub": "0x99Aa571fD5e681c2D27ee08A7b7989DB02541d13", + "rpc": "https://mainnet.base.org", + }, + "gnosis:100": { + "hub": "0x882D0BF07F956b1b94BBfe9E77F47c6fc7D4EC8f", + "rpc": "https://rpc.gnosischain.com/", + }, + "otp:2043": { + "hub": "0x0957e25BD33034948abc28204ddA54b6E1142D6F", + "rpc": "https://astrosat-parachain-rpc.origin-trail.network", + }, + }, } DEFAULT_PROXIMITY_SCORE_FUNCTIONS_PAIR_IDS = { From 110be089a82df69c90d5c9d51cea76dcc17bc873 Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 15:36:21 +0100 Subject: [PATCH 30/31] change default environment from testnet to mainnet --- dkg/constants.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dkg/constants.py b/dkg/constants.py index 2f0dfdf..277b9bd 100644 --- a/dkg/constants.py +++ b/dkg/constants.py @@ -35,7 +35,7 @@ class DefaultParameters(Enum): - ENVIRONMENT: str = "testnet" + ENVIRONMENT: str = "mainnet" PORT: int = 8900 FREQUENCY: int = 5 MAX_NUMBER_OF_RETRIES: int = 5 From b70eb571e07224bd9e32524918487899d011505c Mon Sep 17 00:00:00 2001 From: Zvonimir Date: Fri, 10 Jan 2025 16:00:08 +0100 Subject: [PATCH 31/31] bind graph.create and graph.get to asset --- dkg/main.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/dkg/main.py b/dkg/main.py index 00fd427..bf417b0 100644 --- a/dkg/main.py +++ b/dkg/main.py @@ -70,6 +70,10 @@ def __init__( } self._attach_modules(modules) + # Backwards compatibility + self.graph.get = self.asset.get.__get__(self.asset) + self.graph.create = self.asset.create.__get__(self.asset) + def initialize_services(self, manager): self.input_service = InputService(manager)