dkg 1.1.2__py3-none-any.whl → 8.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dkg/asset.py +589 -683
- dkg/constants.py +102 -40
- dkg/data/interfaces/AskStorage.json +366 -0
- dkg/data/interfaces/Chronos.json +202 -0
- dkg/data/interfaces/Hub.json +294 -2
- dkg/data/interfaces/IdentityStorage.json +400 -0
- dkg/data/interfaces/KnowledgeCollection.json +610 -0
- dkg/data/interfaces/KnowledgeCollectionStorage.json +2312 -0
- dkg/data/interfaces/Paranet.json +656 -135
- dkg/data/interfaces/ParanetIncentivesPoolFactory.json +18 -7
- dkg/data/interfaces/ParanetKnowledgeMinersRegistry.json +20 -4
- dkg/data/interfaces/{ParanetNeurowebIncentivesPool.json → ParanetNeuroIncentivesPool.json} +27 -58
- dkg/data/interfaces/ParanetsRegistry.json +844 -36
- dkg/data/interfaces/Token.json +146 -17
- dkg/dataclasses.py +13 -4
- dkg/exceptions.py +1 -0
- dkg/graph.py +55 -24
- dkg/main.py +18 -2
- dkg/network.py +2 -2
- dkg/node.py +7 -0
- dkg/paranet.py +356 -111
- dkg/providers/blockchain.py +23 -24
- dkg/providers/node_http.py +6 -13
- dkg/services/input_service.py +183 -0
- dkg/services/node_service.py +164 -0
- dkg/types/__init__.py +15 -3
- dkg/types/general.py +15 -8
- dkg/utils/blockchain_request.py +188 -64
- dkg/utils/knowledge_asset_tools.py +5 -0
- dkg/utils/knowledge_collection_tools.py +236 -0
- dkg/utils/merkle.py +1 -1
- dkg/utils/node_request.py +33 -33
- dkg/utils/rdf.py +10 -6
- dkg/utils/string_transformations.py +1 -0
- {dkg-1.1.2.dist-info → dkg-8.0.0.dist-info}/METADATA +36 -26
- dkg-8.0.0.dist-info/RECORD +56 -0
- {dkg-1.1.2.dist-info → dkg-8.0.0.dist-info}/WHEEL +1 -1
- dkg/data/interfaces/AssertionStorage.json +0 -229
- dkg/data/interfaces/ContentAsset.json +0 -801
- dkg/data/interfaces/ContentAssetStorage.json +0 -782
- dkg/data/interfaces/ServiceAgreementStorageProxy.json +0 -1314
- dkg/data/interfaces/UnfinalizedStateStorage.json +0 -171
- dkg-1.1.2.dist-info/RECORD +0 -52
- {dkg-1.1.2.dist-info → dkg-8.0.0.dist-info}/LICENSE +0 -0
- {dkg-1.1.2.dist-info → dkg-8.0.0.dist-info}/NOTICE +0 -0
dkg/utils/blockchain_request.py
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
# under the License.
|
17
17
|
|
18
18
|
from dataclasses import dataclass, field
|
19
|
-
from typing import Type
|
19
|
+
from typing import Type, Dict, Any
|
20
20
|
|
21
21
|
from dkg.dataclasses import ParanetIncentivizationType
|
22
22
|
from dkg.types import Address, HexStr, Wei
|
@@ -52,6 +52,18 @@ class ContractCall(ContractInteraction):
|
|
52
52
|
pass
|
53
53
|
|
54
54
|
|
55
|
+
@dataclass
|
56
|
+
class KnowledgeCollectionResult:
|
57
|
+
knowledge_collection_id: int
|
58
|
+
receipt: Dict[str, Any]
|
59
|
+
|
60
|
+
|
61
|
+
@dataclass
|
62
|
+
class AllowanceResult:
|
63
|
+
allowance_increased: bool
|
64
|
+
allowance_gap: int
|
65
|
+
|
66
|
+
|
55
67
|
class BlockchainRequest:
|
56
68
|
chain_id = JSONRPCRequest("chain_id")
|
57
69
|
get_block = JSONRPCRequest("get_block", args={"block_identifier": str | int})
|
@@ -67,6 +79,30 @@ class BlockchainRequest:
|
|
67
79
|
args={"assetStorageName": str},
|
68
80
|
)
|
69
81
|
|
82
|
+
key_is_operational_wallet = ContractCall(
|
83
|
+
contract="IdentityStorage",
|
84
|
+
function="keyHasPurpose",
|
85
|
+
args={"identityId": int, "_key": Address, "_purpose": int},
|
86
|
+
)
|
87
|
+
|
88
|
+
time_until_next_epoch = ContractCall(
|
89
|
+
contract="Chronos",
|
90
|
+
function="timeUntilNextEpoch",
|
91
|
+
args={},
|
92
|
+
)
|
93
|
+
|
94
|
+
epoch_length = ContractCall(
|
95
|
+
contract="Chronos",
|
96
|
+
function="epochLength",
|
97
|
+
args={},
|
98
|
+
)
|
99
|
+
|
100
|
+
get_stake_weighted_average_ask = ContractCall(
|
101
|
+
contract="AskStorage",
|
102
|
+
function="getStakeWeightedAverageAsk",
|
103
|
+
args={},
|
104
|
+
)
|
105
|
+
|
70
106
|
allowance = ContractCall(
|
71
107
|
contract="Token",
|
72
108
|
function="allowance",
|
@@ -83,48 +119,16 @@ class BlockchainRequest:
|
|
83
119
|
args={"spender": Address, "subtractedValue": Wei},
|
84
120
|
)
|
85
121
|
|
86
|
-
create_asset = ContractTransaction(
|
87
|
-
contract="ContentAsset",
|
88
|
-
function="createAsset",
|
89
|
-
args={"args": dict[str, bytes | int | Wei | bool]},
|
90
|
-
)
|
91
122
|
burn_asset = ContractTransaction(
|
92
123
|
contract="ContentAsset",
|
93
124
|
function="burnAsset",
|
94
125
|
args={"tokenId": int},
|
95
126
|
)
|
96
|
-
update_asset_state = ContractTransaction(
|
97
|
-
contract="ContentAsset",
|
98
|
-
function="updateAssetState",
|
99
|
-
args={
|
100
|
-
"tokenId": int,
|
101
|
-
"assertionId": bytes | HexStr,
|
102
|
-
"size": int,
|
103
|
-
"triplesNumber": int,
|
104
|
-
"chunksNumber": int,
|
105
|
-
"updateTokenAmount": int,
|
106
|
-
},
|
107
|
-
)
|
108
|
-
cancel_asset_state_update = ContractTransaction(
|
109
|
-
contract="ContentAsset",
|
110
|
-
function="cancelAssetStateUpdate",
|
111
|
-
args={"tokenId": int},
|
112
|
-
)
|
113
127
|
extend_asset_storing_period = ContractTransaction(
|
114
128
|
contract="ContentAsset",
|
115
129
|
function="extendAssetStoringPeriod",
|
116
130
|
args={"tokenId": int, "epochsNumber": int, "tokenAmount": int},
|
117
131
|
)
|
118
|
-
increase_asset_token_amount = ContractTransaction(
|
119
|
-
contract="ContentAsset",
|
120
|
-
function="increaseAssetTokenAmount",
|
121
|
-
args={"tokenId": int, "tokenAmount": int},
|
122
|
-
)
|
123
|
-
increase_asset_update_token_amount = ContractTransaction(
|
124
|
-
contract="ContentAsset",
|
125
|
-
function="increaseAssetUpdateTokenAmount",
|
126
|
-
args={"tokenId": int, "tokenAmount": int},
|
127
|
-
)
|
128
132
|
|
129
133
|
transfer_asset = ContractTransaction(
|
130
134
|
contract="ContentAssetStorage",
|
@@ -136,11 +140,6 @@ class BlockchainRequest:
|
|
136
140
|
function="getAssertionIds",
|
137
141
|
args={"tokenId": int},
|
138
142
|
)
|
139
|
-
get_assertion_id_by_index = ContractCall(
|
140
|
-
contract="ContentAssetStorage",
|
141
|
-
function="getAssertionIdByIndex",
|
142
|
-
args={"tokenId": int, "index": int},
|
143
|
-
)
|
144
143
|
get_latest_assertion_id = ContractCall(
|
145
144
|
contract="ContentAssetStorage",
|
146
145
|
function="getLatestAssertionId",
|
@@ -158,18 +157,19 @@ class BlockchainRequest:
|
|
158
157
|
args={"tokenId": int},
|
159
158
|
)
|
160
159
|
|
161
|
-
get_service_agreement_data = ContractCall(
|
162
|
-
contract="ServiceAgreementStorageProxy",
|
163
|
-
function="getAgreementData",
|
164
|
-
args={"agreementId": bytes | HexStr},
|
165
|
-
)
|
166
|
-
|
167
160
|
get_assertion_size = ContractCall(
|
168
161
|
contract="AssertionStorage",
|
169
162
|
function="getAssertionSize",
|
170
163
|
args={"assertionId": bytes | HexStr},
|
171
164
|
)
|
172
165
|
|
166
|
+
# Identity
|
167
|
+
get_identity_id = ContractCall(
|
168
|
+
contract="IdentityStorage",
|
169
|
+
function="getIdentityId",
|
170
|
+
args={"operational": Address},
|
171
|
+
)
|
172
|
+
|
173
173
|
# Paranets
|
174
174
|
register_paranet = ContractTransaction(
|
175
175
|
contract="Paranet",
|
@@ -179,8 +179,121 @@ class BlockchainRequest:
|
|
179
179
|
"paranetKATokenId": int,
|
180
180
|
"paranetName": str,
|
181
181
|
"paranetDescription": str,
|
182
|
+
"nodesAccessPolicy": int,
|
183
|
+
"minersAccessPolicy": int,
|
184
|
+
},
|
185
|
+
)
|
186
|
+
|
187
|
+
add_paranet_curated_nodes = ContractTransaction(
|
188
|
+
contract="Paranet",
|
189
|
+
function="addParanetCuratedNodes",
|
190
|
+
args={
|
191
|
+
"paranetKAStorageContract": Address,
|
192
|
+
"paranetKATokenId": int,
|
193
|
+
"identityIds": list[int],
|
194
|
+
},
|
195
|
+
)
|
196
|
+
|
197
|
+
remove_paranet_curated_nodes = ContractTransaction(
|
198
|
+
contract="Paranet",
|
199
|
+
function="removeParanetCuratedNodes",
|
200
|
+
args={
|
201
|
+
"paranetKAStorageContract": Address,
|
202
|
+
"paranetKATokenId": int,
|
203
|
+
"identityIds": list[int],
|
204
|
+
},
|
205
|
+
)
|
206
|
+
|
207
|
+
request_paranet_curated_node_access = ContractTransaction(
|
208
|
+
contract="Paranet",
|
209
|
+
function="requestParanetCuratedNodeAccess",
|
210
|
+
args={
|
211
|
+
"paranetKAStorageContract": Address,
|
212
|
+
"paranetKATokenId": int,
|
213
|
+
},
|
214
|
+
)
|
215
|
+
|
216
|
+
approve_curated_node = ContractTransaction(
|
217
|
+
contract="Paranet",
|
218
|
+
function="approveCuratedNode",
|
219
|
+
args={
|
220
|
+
"paranetKAStorageContract": Address,
|
221
|
+
"paranetKATokenId": int,
|
222
|
+
"identityId": int,
|
223
|
+
},
|
224
|
+
)
|
225
|
+
|
226
|
+
reject_curated_node = ContractTransaction(
|
227
|
+
contract="Paranet",
|
228
|
+
function="rejectCuratedNode",
|
229
|
+
args={
|
230
|
+
"paranetKAStorageContract": Address,
|
231
|
+
"paranetKATokenId": int,
|
232
|
+
"identityId": int,
|
233
|
+
},
|
234
|
+
)
|
235
|
+
|
236
|
+
get_curated_nodes = ContractCall(
|
237
|
+
contract="ParanetsRegistry",
|
238
|
+
function="getCuratedNodes",
|
239
|
+
args={"paranetId": HexStr},
|
240
|
+
)
|
241
|
+
|
242
|
+
add_paranet_curated_miners = ContractTransaction(
|
243
|
+
contract="Paranet",
|
244
|
+
function="addParanetCuratedMiners",
|
245
|
+
args={
|
246
|
+
"paranetKAStorageContract": Address,
|
247
|
+
"paranetKATokenId": int,
|
248
|
+
"minerAddresses": list[Address],
|
249
|
+
},
|
250
|
+
)
|
251
|
+
|
252
|
+
remove_paranet_curated_miners = ContractTransaction(
|
253
|
+
contract="Paranet",
|
254
|
+
function="removeParanetCuratedMiners",
|
255
|
+
args={
|
256
|
+
"paranetKAStorageContract": Address,
|
257
|
+
"paranetKATokenId": int,
|
258
|
+
"minerAddresses": list[Address],
|
259
|
+
},
|
260
|
+
)
|
261
|
+
|
262
|
+
request_paranet_curated_miner_access = ContractTransaction(
|
263
|
+
contract="Paranet",
|
264
|
+
function="requestParanetCuratedMinerAccess",
|
265
|
+
args={
|
266
|
+
"paranetKAStorageContract": Address,
|
267
|
+
"paranetKATokenId": int,
|
268
|
+
},
|
269
|
+
)
|
270
|
+
|
271
|
+
approve_curated_miner = ContractTransaction(
|
272
|
+
contract="Paranet",
|
273
|
+
function="approveCuratedMiner",
|
274
|
+
args={
|
275
|
+
"paranetKAStorageContract": Address,
|
276
|
+
"paranetKATokenId": int,
|
277
|
+
"minerAddress": Address,
|
278
|
+
},
|
279
|
+
)
|
280
|
+
|
281
|
+
reject_curated_miner = ContractTransaction(
|
282
|
+
contract="Paranet",
|
283
|
+
function="rejectCuratedMiner",
|
284
|
+
args={
|
285
|
+
"paranetKAStorageContract": Address,
|
286
|
+
"paranetKATokenId": int,
|
287
|
+
"minerAddress": Address,
|
182
288
|
},
|
183
289
|
)
|
290
|
+
|
291
|
+
get_knowledge_miners = ContractCall(
|
292
|
+
contract="ParanetsRegistry",
|
293
|
+
function="getKnowledgeMiners",
|
294
|
+
args={"paranetId": HexStr},
|
295
|
+
)
|
296
|
+
|
184
297
|
add_paranet_services = ContractTransaction(
|
185
298
|
contract="Paranet",
|
186
299
|
function="addParanetServices",
|
@@ -201,15 +314,6 @@ class BlockchainRequest:
|
|
201
314
|
"paranetServiceAddresses": list[Address],
|
202
315
|
},
|
203
316
|
)
|
204
|
-
mint_knowledge_asset = ContractTransaction(
|
205
|
-
contract="Paranet",
|
206
|
-
function="mintKnowledgeAsset",
|
207
|
-
args={
|
208
|
-
"paranetKAStorageContract": Address,
|
209
|
-
"paranetKATokenId": int,
|
210
|
-
"knowledgeAssetArgs": dict[str, bytes | int | Wei | bool],
|
211
|
-
},
|
212
|
-
)
|
213
317
|
submit_knowledge_asset = ContractTransaction(
|
214
318
|
contract="Paranet",
|
215
319
|
function="submitKnowledgeAsset",
|
@@ -225,7 +329,6 @@ class BlockchainRequest:
|
|
225
329
|
contract="ParanetIncentivesPoolFactory",
|
226
330
|
function="deployNeuroIncentivesPool",
|
227
331
|
args={
|
228
|
-
"isNativeReward": bool,
|
229
332
|
"paranetKAStorageContract": Address,
|
230
333
|
"paranetKATokenId": int,
|
231
334
|
"tracToNeuroEmissionMultiplier": float,
|
@@ -250,16 +353,6 @@ class BlockchainRequest:
|
|
250
353
|
"paranetId": HexStr,
|
251
354
|
},
|
252
355
|
)
|
253
|
-
process_updated_knowledge_asset_states_metadata = ContractTransaction(
|
254
|
-
contract="Paranet",
|
255
|
-
function="processUpdatedKnowledgeAssetStatesMetadata",
|
256
|
-
args={
|
257
|
-
"paranetKAStorageContract": Address,
|
258
|
-
"paranetKATokenId": int,
|
259
|
-
"start": int,
|
260
|
-
"end": int,
|
261
|
-
},
|
262
|
-
)
|
263
356
|
|
264
357
|
is_knowledge_miner_registered = ContractCall(
|
265
358
|
contract="ParanetsRegistry",
|
@@ -308,3 +401,34 @@ class BlockchainRequest:
|
|
308
401
|
function="claimIncentivizationProposalVoterReward",
|
309
402
|
args={},
|
310
403
|
)
|
404
|
+
|
405
|
+
create_knowledge_collection = ContractTransaction(
|
406
|
+
contract="KnowledgeCollection",
|
407
|
+
function="createKnowledgeCollection",
|
408
|
+
args={
|
409
|
+
"publishOperationId": str,
|
410
|
+
"merkleRoot": bytes,
|
411
|
+
"knowledgeAssetsAmount": int,
|
412
|
+
"byteSize": int,
|
413
|
+
"epochs": int,
|
414
|
+
"tokenAmount": int,
|
415
|
+
"isImmutable": bool,
|
416
|
+
"paymaster": Address,
|
417
|
+
"publisherNodeIdentityId": int,
|
418
|
+
"publisherNodeR": bytes,
|
419
|
+
"publisherNodeVS": bytes,
|
420
|
+
"identityIds": list[int],
|
421
|
+
"r": list[bytes],
|
422
|
+
"vs": list[bytes],
|
423
|
+
},
|
424
|
+
)
|
425
|
+
|
426
|
+
mint_knowledge_asset = ContractTransaction(
|
427
|
+
contract="Paranet",
|
428
|
+
function="mintKnowledgeAsset",
|
429
|
+
args={
|
430
|
+
"paranetKAStorageContract": Address,
|
431
|
+
"paranetKATokenId": int,
|
432
|
+
"knowledgeAssetArgs": dict,
|
433
|
+
},
|
434
|
+
)
|
@@ -0,0 +1,236 @@
|
|
1
|
+
from typing import Literal
|
2
|
+
from dkg.constants import CHUNK_BYTE_SIZE
|
3
|
+
from dkg.exceptions import DatasetInputFormatNotSupported, InvalidDataset
|
4
|
+
from dkg.types import JSONLD, NQuads
|
5
|
+
from pyld import jsonld
|
6
|
+
from dkg.constants import DEFAULT_RDF_FORMAT, DEFAULT_CANON_ALGORITHM
|
7
|
+
from rdflib import Graph, BNode, URIRef, Literal as RDFLiteral
|
8
|
+
from uuid import uuid4
|
9
|
+
from web3 import Web3
|
10
|
+
import math
|
11
|
+
|
12
|
+
|
13
|
+
def normalize_dataset(
|
14
|
+
dataset: JSONLD | NQuads,
|
15
|
+
input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD",
|
16
|
+
output_format=DEFAULT_RDF_FORMAT,
|
17
|
+
algorithm=DEFAULT_CANON_ALGORITHM,
|
18
|
+
) -> NQuads:
|
19
|
+
normalization_options = {
|
20
|
+
"algorithm": algorithm,
|
21
|
+
"format": output_format,
|
22
|
+
}
|
23
|
+
|
24
|
+
match input_format.lower():
|
25
|
+
case "json-ld" | "jsonld":
|
26
|
+
pass
|
27
|
+
case "n-quads" | "nquads":
|
28
|
+
normalization_options["inputFormat"] = "application/n-quads"
|
29
|
+
case _:
|
30
|
+
raise DatasetInputFormatNotSupported(
|
31
|
+
f"Dataset input format isn't supported: {input_format}. "
|
32
|
+
"Supported formats: JSON-LD / N-Quads."
|
33
|
+
)
|
34
|
+
|
35
|
+
n_quads = jsonld.normalize(dataset, normalization_options)
|
36
|
+
assertion = [quad for quad in n_quads.split("\n") if quad]
|
37
|
+
|
38
|
+
if not assertion:
|
39
|
+
raise InvalidDataset("Invalid dataset, no quads were extracted.")
|
40
|
+
|
41
|
+
return assertion
|
42
|
+
|
43
|
+
|
44
|
+
def is_empty_dict(dictionary: dict):
|
45
|
+
return len(dictionary.keys()) == 0 and isinstance(dictionary, dict)
|
46
|
+
|
47
|
+
|
48
|
+
def format_dataset(
|
49
|
+
content: dict,
|
50
|
+
input_format: Literal["JSON-LD", "N-Quads"] = "JSON-LD",
|
51
|
+
output_format=DEFAULT_RDF_FORMAT,
|
52
|
+
algorithm=DEFAULT_CANON_ALGORITHM,
|
53
|
+
):
|
54
|
+
private_assertion = None
|
55
|
+
if content.get("private") and not is_empty_dict(content.get("private")):
|
56
|
+
private_assertion = normalize_dataset(
|
57
|
+
content.get("private"), input_format, output_format, algorithm
|
58
|
+
)
|
59
|
+
elif not content.get("public"):
|
60
|
+
content = {"public": content}
|
61
|
+
|
62
|
+
public_assertion = []
|
63
|
+
if content.get("public"):
|
64
|
+
public_assertion = normalize_dataset(
|
65
|
+
content.get("public"), input_format, output_format, algorithm
|
66
|
+
)
|
67
|
+
|
68
|
+
if (
|
69
|
+
public_assertion
|
70
|
+
and len(public_assertion) == 0
|
71
|
+
and private_assertion
|
72
|
+
and len(private_assertion) == 0
|
73
|
+
):
|
74
|
+
raise ValueError("File format is corrupted, no n-quads are extracted.")
|
75
|
+
|
76
|
+
dataset = {"public": public_assertion}
|
77
|
+
if private_assertion:
|
78
|
+
dataset["private"] = private_assertion
|
79
|
+
|
80
|
+
return dataset
|
81
|
+
|
82
|
+
|
83
|
+
def split_into_chunks(quads, chunk_size_bytes=32):
|
84
|
+
# Concatenate the quads with newline characters
|
85
|
+
concatenated_quads = "\n".join(quads)
|
86
|
+
|
87
|
+
# Encode the concatenated string to bytes
|
88
|
+
encoded_bytes = concatenated_quads.encode("utf-8")
|
89
|
+
|
90
|
+
# Split the encoded bytes into chunks
|
91
|
+
chunks = []
|
92
|
+
start = 0
|
93
|
+
|
94
|
+
while start < len(encoded_bytes):
|
95
|
+
end = min(start + chunk_size_bytes, len(encoded_bytes))
|
96
|
+
chunk = encoded_bytes[start:end]
|
97
|
+
chunks.append(chunk.decode("utf-8")) # Decode bytes back to string
|
98
|
+
start = end
|
99
|
+
|
100
|
+
return chunks
|
101
|
+
|
102
|
+
|
103
|
+
def calculate_merkle_root(quads: list[str], chunk_size_bytes: int = CHUNK_BYTE_SIZE):
|
104
|
+
chunks = split_into_chunks(quads, chunk_size_bytes)
|
105
|
+
|
106
|
+
# Create leaves using solidityKeccak256 equivalent
|
107
|
+
leaves = [
|
108
|
+
bytes.fromhex(Web3.solidity_keccak(["string", "uint256"], [chunk, index]).hex())
|
109
|
+
for index, chunk in enumerate(chunks)
|
110
|
+
]
|
111
|
+
|
112
|
+
while len(leaves) > 1:
|
113
|
+
next_level = []
|
114
|
+
|
115
|
+
for i in range(0, len(leaves), 2):
|
116
|
+
left = leaves[i]
|
117
|
+
|
118
|
+
if i + 1 >= len(leaves):
|
119
|
+
next_level.append(left)
|
120
|
+
break
|
121
|
+
|
122
|
+
right = leaves[i + 1]
|
123
|
+
|
124
|
+
# Combine and sort the leaves
|
125
|
+
combined = [left, right]
|
126
|
+
combined.sort()
|
127
|
+
|
128
|
+
# Calculate the hash of the combined leaves
|
129
|
+
hash_value = Web3.keccak(b"".join(combined))
|
130
|
+
next_level.append(hash_value)
|
131
|
+
|
132
|
+
leaves = next_level
|
133
|
+
|
134
|
+
return f"0x{leaves[0].hex()}"
|
135
|
+
|
136
|
+
|
137
|
+
def generate_missing_ids_for_blank_nodes(nquads_list: list[str] | None) -> list[str]:
|
138
|
+
if not nquads_list:
|
139
|
+
return [""]
|
140
|
+
|
141
|
+
generated_ids = {}
|
142
|
+
|
143
|
+
def replace_blank_node(term):
|
144
|
+
# Handle blank nodes
|
145
|
+
if isinstance(term, BNode):
|
146
|
+
if str(term) not in generated_ids:
|
147
|
+
generated_ids[str(term)] = URIRef(f"uuid:{str(uuid4())}")
|
148
|
+
return generated_ids[str(term)]
|
149
|
+
|
150
|
+
return term # Return IRIs or Literals unchanged
|
151
|
+
|
152
|
+
# Create a temporary graph for parsing individual quads
|
153
|
+
result = []
|
154
|
+
|
155
|
+
# Process each N-Quad string individually to maintain order
|
156
|
+
for nquad in nquads_list:
|
157
|
+
if not nquad.strip():
|
158
|
+
continue
|
159
|
+
|
160
|
+
# Parse single N-Quad
|
161
|
+
g = Graph()
|
162
|
+
g.parse(data=nquad, format="nquads")
|
163
|
+
|
164
|
+
# Get the triple and replace blank nodes
|
165
|
+
for s, p, o in g:
|
166
|
+
updated_quad = (
|
167
|
+
replace_blank_node(s),
|
168
|
+
replace_blank_node(p),
|
169
|
+
replace_blank_node(o),
|
170
|
+
)
|
171
|
+
# Format as N-Quad string
|
172
|
+
result.append(
|
173
|
+
f"{updated_quad[0].n3()} {updated_quad[1].n3()} {updated_quad[2].n3()} ."
|
174
|
+
)
|
175
|
+
|
176
|
+
return result
|
177
|
+
|
178
|
+
|
179
|
+
def group_nquads_by_subject(nquads_list: list[str], sort: bool = False):
|
180
|
+
grouped = {}
|
181
|
+
|
182
|
+
# Process each quad in original order
|
183
|
+
for nquad in nquads_list:
|
184
|
+
if not nquad.strip(): # Skip empty lines
|
185
|
+
continue
|
186
|
+
|
187
|
+
# Parse single quad
|
188
|
+
g = Graph()
|
189
|
+
g.parse(data=nquad, format="nquads")
|
190
|
+
quad = next(iter(g))
|
191
|
+
subject, predicate, obj = quad
|
192
|
+
|
193
|
+
# Get subject key
|
194
|
+
subject_key = (
|
195
|
+
f"<<<{subject.subject}> <{subject.predicate}> <{subject.object}>>"
|
196
|
+
if hasattr(subject, "subject")
|
197
|
+
else f"<{subject}>"
|
198
|
+
)
|
199
|
+
|
200
|
+
# Initialize group if needed
|
201
|
+
if subject_key not in grouped:
|
202
|
+
grouped[subject_key] = []
|
203
|
+
|
204
|
+
# Format object
|
205
|
+
object_value = f'"{obj}"' if isinstance(obj, RDFLiteral) else f"<{obj}>"
|
206
|
+
|
207
|
+
# Add quad to group
|
208
|
+
quad_string = f"{subject_key} <{predicate}> {object_value} ."
|
209
|
+
grouped[subject_key].append(quad_string)
|
210
|
+
|
211
|
+
# Return grouped quads (sorted if requested)
|
212
|
+
grouped_items = sorted(grouped.items()) if sort else grouped.items()
|
213
|
+
return [quads for _, quads in grouped_items]
|
214
|
+
|
215
|
+
|
216
|
+
def calculate_number_of_chunks(quads, chunk_size_bytes=CHUNK_BYTE_SIZE):
|
217
|
+
# Concatenate the quads with newline characters
|
218
|
+
concatenated_quads = "\n".join(quads)
|
219
|
+
|
220
|
+
total_size_bytes = len(concatenated_quads.encode("utf-8"))
|
221
|
+
|
222
|
+
# Calculate and return the number of chunks
|
223
|
+
return math.ceil(total_size_bytes / chunk_size_bytes)
|
224
|
+
|
225
|
+
|
226
|
+
def count_distinct_subjects(nquads_list: list[str]) -> int:
|
227
|
+
# Create a new RDF graph
|
228
|
+
graph = Graph()
|
229
|
+
|
230
|
+
# Parse the joined N-Quads
|
231
|
+
graph.parse(data="\n".join(nquads_list), format="nquads")
|
232
|
+
|
233
|
+
# Extract unique subjects using set comprehension
|
234
|
+
subjects = {str(quad[0]) for quad in graph}
|
235
|
+
|
236
|
+
return len(subjects)
|
dkg/utils/merkle.py
CHANGED
dkg/utils/node_request.py
CHANGED
@@ -21,7 +21,7 @@ from typing import Any, Type
|
|
21
21
|
|
22
22
|
from dkg.dataclasses import BidSuggestionRange, HTTPRequestMethod
|
23
23
|
from dkg.exceptions import OperationFailed, OperationNotFinished
|
24
|
-
from dkg.types import
|
24
|
+
from dkg.types import AutoStrEnumUpperCase, UAL, Address, DataHexStr
|
25
25
|
|
26
26
|
|
27
27
|
@dataclass
|
@@ -52,44 +52,55 @@ class NodeRequest:
|
|
52
52
|
path="{operation}/{operation_id}",
|
53
53
|
)
|
54
54
|
|
55
|
-
local_store = NodeCall(
|
56
|
-
method=HTTPRequestMethod.POST,
|
57
|
-
path="local-store",
|
58
|
-
data=list[dict[str, str | Address | NQuads]],
|
59
|
-
)
|
60
55
|
publish = NodeCall(
|
61
56
|
method=HTTPRequestMethod.POST,
|
62
57
|
path="publish",
|
63
58
|
data={
|
64
|
-
"
|
65
|
-
"
|
59
|
+
"datasetRoot": str,
|
60
|
+
"dataset": dict[str, list[str]],
|
66
61
|
"blockchain": str,
|
67
|
-
"contract": Address,
|
68
|
-
"tokenId": int,
|
69
62
|
"hashFunctionId": int,
|
63
|
+
"minimumNumberOfNodeReplications": int,
|
70
64
|
},
|
71
65
|
)
|
72
|
-
|
66
|
+
|
67
|
+
ask = NodeCall(
|
73
68
|
method=HTTPRequestMethod.POST,
|
74
|
-
path="
|
75
|
-
|
76
|
-
"
|
77
|
-
"
|
78
|
-
"blockchain": str,
|
79
|
-
"contract": Address,
|
80
|
-
"tokenId": int,
|
81
|
-
"hashFunctionId": int,
|
69
|
+
path="ask",
|
70
|
+
params={
|
71
|
+
"ual": UAL,
|
72
|
+
"minimumNumberOfNodeReplications": int,
|
82
73
|
},
|
83
74
|
)
|
75
|
+
|
76
|
+
finality_status = NodeCall(
|
77
|
+
method=HTTPRequestMethod.GET,
|
78
|
+
path="finality",
|
79
|
+
params={"ual": UAL},
|
80
|
+
)
|
81
|
+
|
84
82
|
get = NodeCall(
|
85
83
|
method=HTTPRequestMethod.POST,
|
86
84
|
path="get",
|
87
|
-
data={
|
85
|
+
data={
|
86
|
+
"id": UAL,
|
87
|
+
"contentType": str,
|
88
|
+
"includeMetadata": bool,
|
89
|
+
"hashFunctionId": int,
|
90
|
+
"paranetUAL": UAL,
|
91
|
+
"subjectUAL": UAL,
|
92
|
+
},
|
88
93
|
)
|
94
|
+
|
89
95
|
query = NodeCall(
|
90
96
|
method=HTTPRequestMethod.POST,
|
91
97
|
path="query",
|
92
|
-
data={
|
98
|
+
data={
|
99
|
+
"query": str,
|
100
|
+
"type": str,
|
101
|
+
"repository": str | None,
|
102
|
+
"paranet_ual": str | None,
|
103
|
+
},
|
93
104
|
)
|
94
105
|
|
95
106
|
|
@@ -115,19 +126,9 @@ class PublishOperationStatus(Enum):
|
|
115
126
|
PUBLISH_END = auto()
|
116
127
|
|
117
128
|
|
118
|
-
class UpdateOperationStatus(AutoStrEnumUpperCase):
|
119
|
-
UPDATE_START = auto()
|
120
|
-
UPDATE_INIT_START = auto()
|
121
|
-
UPDATE_INIT_END = auto()
|
122
|
-
UPDATE_REPLICATE_START = auto()
|
123
|
-
UPDATE_REPLICATE_END = auto()
|
124
|
-
VALIDATING_UPDATE_ASSERTION_REMOTE_START = auto()
|
125
|
-
VALIDATING_UPDATE_ASSERTION_REMOTE_END = auto()
|
126
|
-
UPDATE_END = auto()
|
127
|
-
|
128
|
-
|
129
129
|
class StoreTypes(AutoStrEnumUpperCase):
|
130
130
|
TRIPLE = auto()
|
131
|
+
TRIPLE_PARANET = auto()
|
131
132
|
PENDING = auto()
|
132
133
|
|
133
134
|
|
@@ -171,7 +172,6 @@ class OperationStatus(AutoStrEnumUpperCase):
|
|
171
172
|
DIAL_PROTOCOL_END = auto()
|
172
173
|
LOCAL_STORE = LocalStoreOperationStatus
|
173
174
|
PUBLISH = PublishOperationStatus
|
174
|
-
UPDATE = UpdateOperationStatus
|
175
175
|
GET = GetOperationStatus
|
176
176
|
QUERY = QueryOperationStatus
|
177
177
|
|