koi-net 1.2.0b2__py3-none-any.whl → 1.2.0b3__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.
Potentially problematic release.
This version of koi-net might be problematic. Click here for more details.
- koi_net/__init__.py +0 -1
- koi_net/assembler.py +20 -7
- koi_net/cli/models.py +2 -2
- koi_net/config/core.py +71 -0
- koi_net/config/full_node.py +31 -0
- koi_net/config/loader.py +46 -0
- koi_net/config/partial_node.py +18 -0
- koi_net/core.py +15 -23
- koi_net/default_actions.py +1 -2
- koi_net/effector.py +1 -1
- koi_net/entrypoints/__init__.py +2 -0
- koi_net/entrypoints/base.py +5 -0
- koi_net/{poller.py → entrypoints/poller.py} +9 -9
- koi_net/{server.py → entrypoints/server.py} +9 -10
- koi_net/handshaker.py +2 -2
- koi_net/identity.py +1 -1
- koi_net/lifecycle.py +6 -6
- koi_net/network/error_handler.py +1 -1
- koi_net/network/event_queue.py +1 -1
- koi_net/network/poll_event_buffer.py +1 -1
- koi_net/network/resolver.py +1 -1
- koi_net/network/response_handler.py +1 -1
- koi_net/{context.py → processor/context.py} +6 -6
- koi_net/processor/handler.py +4 -1
- koi_net/processor/{handlers.py → knowledge_handlers.py} +6 -6
- koi_net/processor/knowledge_object.py +2 -3
- koi_net/processor/kobj_queue.py +1 -1
- koi_net/processor/pipeline.py +2 -2
- koi_net/protocol/node.py +3 -3
- koi_net/protocol/secure.py +6 -0
- koi_net/secure.py +1 -2
- koi_net/workers/__init__.py +2 -0
- koi_net/{processor → workers}/event_worker.py +8 -8
- koi_net/{processor → workers}/kobj_worker.py +3 -3
- {koi_net-1.2.0b2.dist-info → koi_net-1.2.0b3.dist-info}/METADATA +1 -1
- koi_net-1.2.0b3.dist-info/RECORD +56 -0
- koi_net/config.py +0 -161
- koi_net/interfaces/entrypoint.py +0 -5
- koi_net/sentry.py +0 -13
- koi_net-1.2.0b2.dist-info/RECORD +0 -52
- /koi_net/{interfaces/worker.py → workers/base.py} +0 -0
- {koi_net-1.2.0b2.dist-info → koi_net-1.2.0b3.dist-info}/WHEEL +0 -0
- {koi_net-1.2.0b2.dist-info → koi_net-1.2.0b3.dist-info}/entry_points.txt +0 -0
- {koi_net-1.2.0b2.dist-info → koi_net-1.2.0b3.dist-info}/licenses/LICENSE +0 -0
koi_net/__init__.py
CHANGED
koi_net/assembler.py
CHANGED
|
@@ -2,9 +2,10 @@ import inspect
|
|
|
2
2
|
from typing import Protocol
|
|
3
3
|
from dataclasses import make_dataclass
|
|
4
4
|
|
|
5
|
+
from pydantic import BaseModel
|
|
5
6
|
import structlog
|
|
6
7
|
|
|
7
|
-
from .
|
|
8
|
+
from .entrypoints.base import EntryPoint
|
|
8
9
|
|
|
9
10
|
log = structlog.stdlib.get_logger()
|
|
10
11
|
|
|
@@ -41,13 +42,25 @@ class NodeAssembler(metaclass=BuildOrderer):
|
|
|
41
42
|
@classmethod
|
|
42
43
|
def _build(cls) -> NodeContainer:
|
|
43
44
|
components = {}
|
|
44
|
-
for comp_name in cls._build_order:
|
|
45
|
-
|
|
45
|
+
for comp_name in cls._build_order:
|
|
46
|
+
comp = getattr(cls, comp_name, None)
|
|
46
47
|
|
|
47
|
-
if
|
|
48
|
+
if comp is None:
|
|
48
49
|
raise Exception(f"Couldn't find factory for component '{comp_name}'")
|
|
49
50
|
|
|
50
|
-
|
|
51
|
+
print(comp_name)
|
|
52
|
+
|
|
53
|
+
if not callable(comp):
|
|
54
|
+
print(f"Treating {comp_name} as a literal")
|
|
55
|
+
components[comp_name] = comp
|
|
56
|
+
continue
|
|
57
|
+
|
|
58
|
+
if issubclass(comp, BaseModel):
|
|
59
|
+
print(f"Treating {comp_name} as a pydantic model")
|
|
60
|
+
components[comp_name] = comp
|
|
61
|
+
continue
|
|
62
|
+
|
|
63
|
+
sig = inspect.signature(comp)
|
|
51
64
|
|
|
52
65
|
required_comps = []
|
|
53
66
|
for name, param in sig.parameters.items():
|
|
@@ -58,7 +71,7 @@ class NodeAssembler(metaclass=BuildOrderer):
|
|
|
58
71
|
else:
|
|
59
72
|
s = f"{comp_name} -> {', '.join([name for name, _type in required_comps])}"
|
|
60
73
|
|
|
61
|
-
print(s.replace("graph", "_graph"), end=";\n")
|
|
74
|
+
# print(s.replace("graph", "_graph"), end=";\n")
|
|
62
75
|
|
|
63
76
|
dependencies = {}
|
|
64
77
|
for req_comp_name, req_comp_type in required_comps:
|
|
@@ -67,7 +80,7 @@ class NodeAssembler(metaclass=BuildOrderer):
|
|
|
67
80
|
|
|
68
81
|
dependencies[req_comp_name] = components[req_comp_name]
|
|
69
82
|
|
|
70
|
-
components[comp_name] =
|
|
83
|
+
components[comp_name] = comp(**dependencies)
|
|
71
84
|
|
|
72
85
|
NodeContainer = make_dataclass(
|
|
73
86
|
cls_name="NodeContainer",
|
koi_net/cli/models.py
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
from pydantic import BaseModel,
|
|
1
|
+
from pydantic import BaseModel, PrivateAttr
|
|
2
2
|
from ruamel.yaml import YAML
|
|
3
3
|
|
|
4
4
|
|
|
5
5
|
class KoiNetworkConfig(BaseModel):
|
|
6
|
-
nodes: dict[str, str] =
|
|
6
|
+
nodes: dict[str, str] = {}
|
|
7
7
|
_file_path: str = PrivateAttr(default="koi-net-config.yaml")
|
|
8
8
|
|
|
9
9
|
@classmethod
|
koi_net/config/core.py
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import os
|
|
2
|
+
from pydantic import BaseModel, model_validator
|
|
3
|
+
from dotenv import load_dotenv
|
|
4
|
+
from rid_lib import RIDType
|
|
5
|
+
from rid_lib.types import KoiNetNode
|
|
6
|
+
|
|
7
|
+
from koi_net.protocol.secure import PrivateKey
|
|
8
|
+
from ..protocol.node import NodeProfile
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class NodeContact(BaseModel):
|
|
12
|
+
rid: KoiNetNode | None = None
|
|
13
|
+
url: str | None = None
|
|
14
|
+
|
|
15
|
+
class KoiNetConfig(BaseModel):
|
|
16
|
+
"""Config for KOI-net."""
|
|
17
|
+
|
|
18
|
+
node_name: str
|
|
19
|
+
node_rid: KoiNetNode | None = None
|
|
20
|
+
node_profile: NodeProfile
|
|
21
|
+
|
|
22
|
+
rid_types_of_interest: list[RIDType] = [KoiNetNode]
|
|
23
|
+
|
|
24
|
+
cache_directory_path: str = ".rid_cache"
|
|
25
|
+
event_queues_path: str = "event_queues.json"
|
|
26
|
+
private_key_pem_path: str = "priv_key.pem"
|
|
27
|
+
|
|
28
|
+
first_contact: NodeContact = NodeContact()
|
|
29
|
+
|
|
30
|
+
class EnvConfig(BaseModel):
|
|
31
|
+
"""Config for environment variables.
|
|
32
|
+
|
|
33
|
+
Values set in the config are the variables names, and are loaded
|
|
34
|
+
from the environment at runtime. For example, if the config YAML
|
|
35
|
+
sets `priv_key_password: PRIV_KEY_PASSWORD` accessing
|
|
36
|
+
`priv_key_password` would retrieve the value of `PRIV_KEY_PASSWORD`
|
|
37
|
+
from the environment.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
priv_key_password: str = "PRIV_KEY_PASSWORD"
|
|
41
|
+
|
|
42
|
+
def __init__(self, **kwargs):
|
|
43
|
+
super().__init__(**kwargs)
|
|
44
|
+
load_dotenv()
|
|
45
|
+
|
|
46
|
+
def __getattribute__(self, name):
|
|
47
|
+
value = super().__getattribute__(name)
|
|
48
|
+
if name in type(self).model_fields:
|
|
49
|
+
env_val = os.getenv(value)
|
|
50
|
+
if env_val is None:
|
|
51
|
+
raise ValueError(f"Required environment variable {value} not set")
|
|
52
|
+
return env_val
|
|
53
|
+
return value
|
|
54
|
+
|
|
55
|
+
class NodeConfig(BaseModel):
|
|
56
|
+
koi_net: KoiNetConfig
|
|
57
|
+
env: EnvConfig = EnvConfig()
|
|
58
|
+
|
|
59
|
+
@model_validator(mode="after")
|
|
60
|
+
def generate_rid_cascade(self):
|
|
61
|
+
if not self.koi_net.node_rid:
|
|
62
|
+
priv_key = PrivateKey.generate()
|
|
63
|
+
pub_key = priv_key.public_key()
|
|
64
|
+
|
|
65
|
+
self.koi_net.node_rid = pub_key.to_node_rid(self.koi_net.node_name)
|
|
66
|
+
|
|
67
|
+
with open(self.koi_net.private_key_pem_path, "w") as f:
|
|
68
|
+
f.write(priv_key.to_pem(self.env.priv_key_password))
|
|
69
|
+
|
|
70
|
+
self.koi_net.node_profile.public_key = pub_key.to_der()
|
|
71
|
+
return self
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
from pydantic import BaseModel, model_validator
|
|
2
|
+
from koi_net.config.core import NodeConfig, KoiNetConfig as BaseKoiNetConfig
|
|
3
|
+
from ..protocol.node import NodeProfile as BaseNodeProfile, NodeType, NodeProvides
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class NodeProfile(BaseNodeProfile):
|
|
7
|
+
node_type: NodeType = NodeType.FULL
|
|
8
|
+
|
|
9
|
+
class KoiNetConfig(BaseKoiNetConfig):
|
|
10
|
+
node_profile: NodeProfile
|
|
11
|
+
|
|
12
|
+
class ServerConfig(BaseModel):
|
|
13
|
+
"""Config for the node server (full node only)."""
|
|
14
|
+
|
|
15
|
+
host: str = "127.0.0.1"
|
|
16
|
+
port: int = 8000
|
|
17
|
+
path: str | None = "/koi-net"
|
|
18
|
+
|
|
19
|
+
@property
|
|
20
|
+
def url(self) -> str:
|
|
21
|
+
return f"http://{self.host}:{self.port}{self.path or ''}"
|
|
22
|
+
|
|
23
|
+
class FullNodeConfig(NodeConfig):
|
|
24
|
+
koi_net: KoiNetConfig
|
|
25
|
+
server: ServerConfig = ServerConfig()
|
|
26
|
+
|
|
27
|
+
@model_validator(mode="after")
|
|
28
|
+
def check_url(self):
|
|
29
|
+
if not self.koi_net.node_profile.base_url:
|
|
30
|
+
self.koi_net.node_profile.base_url = self.server.url
|
|
31
|
+
return self
|
koi_net/config/loader.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
from ruamel.yaml import YAML
|
|
2
|
+
from .core import NodeConfig
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
class ConfigLoader:
|
|
6
|
+
_config: NodeConfig
|
|
7
|
+
|
|
8
|
+
_file_path: str = "config.yaml"
|
|
9
|
+
_file_content: str
|
|
10
|
+
|
|
11
|
+
def __init__(self, config_cls: type[NodeConfig]):
|
|
12
|
+
self._config_cls = config_cls
|
|
13
|
+
self.load_from_yaml()
|
|
14
|
+
|
|
15
|
+
def __getattr__(self, name):
|
|
16
|
+
return getattr(self._config, name)
|
|
17
|
+
|
|
18
|
+
def load_from_yaml(self):
|
|
19
|
+
"""Loads config state from YAML file."""
|
|
20
|
+
yaml = YAML()
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
with open(self._file_path, "r") as f:
|
|
24
|
+
self._file_content = f.read()
|
|
25
|
+
config_data = yaml.load(self._file_content)
|
|
26
|
+
self._config = self._config_cls.model_validate(config_data)
|
|
27
|
+
|
|
28
|
+
except FileNotFoundError:
|
|
29
|
+
self._config = self._config_cls()
|
|
30
|
+
|
|
31
|
+
self.save_to_yaml()
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def save_to_yaml(self):
|
|
35
|
+
yaml = YAML()
|
|
36
|
+
|
|
37
|
+
with open(self._file_path, "w") as f:
|
|
38
|
+
try:
|
|
39
|
+
config_data = self._config.model_dump(mode="json")
|
|
40
|
+
yaml.dump(config_data, f)
|
|
41
|
+
except Exception as e:
|
|
42
|
+
if self._file_content:
|
|
43
|
+
f.seek(0)
|
|
44
|
+
f.truncate()
|
|
45
|
+
f.write(self._file_content)
|
|
46
|
+
raise e
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from pydantic import BaseModel
|
|
2
|
+
from koi_net.config.core import NodeConfig, KoiNetConfig
|
|
3
|
+
from ..protocol.node import NodeProfile, NodeType, NodeProvides
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class NodeProfile(NodeProfile):
|
|
7
|
+
base_url: str | None = None
|
|
8
|
+
node_type: NodeType = NodeType.PARTIAL
|
|
9
|
+
|
|
10
|
+
class KoiNetConfig(KoiNetConfig):
|
|
11
|
+
node_profile: NodeProfile
|
|
12
|
+
|
|
13
|
+
class PollerConfig(BaseModel):
|
|
14
|
+
polling_interval: int = 5
|
|
15
|
+
|
|
16
|
+
class PartialNodeConfig(NodeConfig):
|
|
17
|
+
koi_net: KoiNetConfig
|
|
18
|
+
poller: PollerConfig = PollerConfig()
|
koi_net/core.py
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
from rid_lib.ext import Cache
|
|
2
|
+
|
|
3
|
+
from .config.loader import ConfigLoader
|
|
2
4
|
from .assembler import NodeAssembler
|
|
3
|
-
from .config.
|
|
4
|
-
from .context import HandlerContext
|
|
5
|
+
from .config.core import NodeConfig
|
|
6
|
+
from .processor.context import HandlerContext
|
|
5
7
|
from .effector import Effector
|
|
6
8
|
from .handshaker import Handshaker
|
|
7
9
|
from .identity import NodeIdentity
|
|
8
|
-
from .
|
|
10
|
+
from .workers import KnowledgeProcessingWorker, EventProcessingWorker
|
|
9
11
|
from .lifecycle import NodeLifecycle
|
|
10
12
|
from .network.error_handler import ErrorHandler
|
|
11
13
|
from .network.event_queue import EventQueue
|
|
@@ -14,8 +16,11 @@ from .network.request_handler import RequestHandler
|
|
|
14
16
|
from .network.resolver import NetworkResolver
|
|
15
17
|
from .network.response_handler import ResponseHandler
|
|
16
18
|
from .network.poll_event_buffer import PollEventBuffer
|
|
17
|
-
from .
|
|
18
|
-
from .processor.
|
|
19
|
+
from .processor.pipeline import KnowledgePipeline
|
|
20
|
+
from .processor.kobj_queue import KobjQueue
|
|
21
|
+
from .secure import Secure
|
|
22
|
+
from .entrypoints import NodeServer, NodePoller
|
|
23
|
+
from .processor.knowledge_handlers import (
|
|
19
24
|
basic_manifest_handler,
|
|
20
25
|
basic_network_output_filter,
|
|
21
26
|
basic_rid_handler,
|
|
@@ -24,28 +29,15 @@ from .processor.handlers import (
|
|
|
24
29
|
forget_edge_on_node_deletion,
|
|
25
30
|
secure_profile_handler
|
|
26
31
|
)
|
|
27
|
-
from .processor.event_worker import EventProcessingWorker
|
|
28
|
-
from .processor.pipeline import KnowledgePipeline
|
|
29
|
-
from .processor.kobj_queue import KobjQueue
|
|
30
|
-
from .secure import Secure
|
|
31
|
-
from .server import NodeServer
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
# factory functions for components with non standard initializiation
|
|
35
|
-
|
|
36
|
-
def make_config() -> BaseConfig:
|
|
37
|
-
return BaseConfig.load_from_yaml()
|
|
38
|
-
|
|
39
|
-
def make_cache(config: BaseConfig) -> Cache:
|
|
40
|
-
return Cache(directory_path=config.koi_net.cache_directory_path)
|
|
41
32
|
|
|
42
33
|
|
|
43
34
|
class BaseNode(NodeAssembler):
|
|
44
|
-
|
|
35
|
+
config_cls = NodeConfig
|
|
45
36
|
kobj_queue = KobjQueue
|
|
46
37
|
event_queue = EventQueue
|
|
47
38
|
poll_event_buf = PollEventBuffer
|
|
48
|
-
|
|
39
|
+
config = ConfigLoader
|
|
40
|
+
knowledge_handlers = [
|
|
49
41
|
basic_rid_handler,
|
|
50
42
|
basic_manifest_handler,
|
|
51
43
|
secure_profile_handler,
|
|
@@ -54,7 +46,8 @@ class BaseNode(NodeAssembler):
|
|
|
54
46
|
basic_network_output_filter,
|
|
55
47
|
forget_edge_on_node_deletion
|
|
56
48
|
]
|
|
57
|
-
cache =
|
|
49
|
+
cache = lambda config: Cache(
|
|
50
|
+
directory_path=config.koi_net.cache_directory_path)
|
|
58
51
|
identity = NodeIdentity
|
|
59
52
|
graph = NetworkGraph
|
|
60
53
|
secure = Secure
|
|
@@ -70,7 +63,6 @@ class BaseNode(NodeAssembler):
|
|
|
70
63
|
event_worker = EventProcessingWorker
|
|
71
64
|
lifecycle = NodeLifecycle
|
|
72
65
|
|
|
73
|
-
|
|
74
66
|
class FullNode(BaseNode):
|
|
75
67
|
entrypoint = NodeServer
|
|
76
68
|
|
koi_net/default_actions.py
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
"""Implementations of default dereference actions."""
|
|
2
2
|
|
|
3
|
-
from .context import ActionContext
|
|
4
3
|
from rid_lib.types import KoiNetNode
|
|
5
4
|
from rid_lib.ext import Bundle
|
|
6
|
-
from .effector import Effector
|
|
5
|
+
from .effector import Effector, ActionContext
|
|
7
6
|
|
|
8
7
|
|
|
9
8
|
@Effector.register_default_action(KoiNetNode)
|
koi_net/effector.py
CHANGED
|
@@ -2,11 +2,11 @@
|
|
|
2
2
|
import time
|
|
3
3
|
import structlog
|
|
4
4
|
|
|
5
|
-
from
|
|
6
|
-
from
|
|
7
|
-
from
|
|
8
|
-
from
|
|
9
|
-
from .
|
|
5
|
+
from .base import EntryPoint
|
|
6
|
+
from ..processor.kobj_queue import KobjQueue
|
|
7
|
+
from ..lifecycle import NodeLifecycle
|
|
8
|
+
from ..network.resolver import NetworkResolver
|
|
9
|
+
from ..config.partial_node import PartialNodeConfig
|
|
10
10
|
|
|
11
11
|
log = structlog.stdlib.get_logger()
|
|
12
12
|
|
|
@@ -16,11 +16,11 @@ class NodePoller(EntryPoint):
|
|
|
16
16
|
kobj_queue: KobjQueue
|
|
17
17
|
lifecycle: NodeLifecycle
|
|
18
18
|
resolver: NetworkResolver
|
|
19
|
-
config:
|
|
19
|
+
config: PartialNodeConfig
|
|
20
20
|
|
|
21
21
|
def __init__(
|
|
22
22
|
self,
|
|
23
|
-
config:
|
|
23
|
+
config: PartialNodeConfig,
|
|
24
24
|
lifecycle: NodeLifecycle,
|
|
25
25
|
kobj_queue: KobjQueue,
|
|
26
26
|
resolver: NetworkResolver,
|
|
@@ -35,7 +35,7 @@ class NodePoller(EntryPoint):
|
|
|
35
35
|
neighbors = self.resolver.poll_neighbors()
|
|
36
36
|
for node_rid in neighbors:
|
|
37
37
|
for event in neighbors[node_rid]:
|
|
38
|
-
self.kobj_queue.
|
|
38
|
+
self.kobj_queue.push(event=event, source=node_rid)
|
|
39
39
|
|
|
40
40
|
def run(self):
|
|
41
41
|
"""Runs polling event loop."""
|
|
@@ -44,6 +44,6 @@ class NodePoller(EntryPoint):
|
|
|
44
44
|
start_time = time.time()
|
|
45
45
|
self.poll()
|
|
46
46
|
elapsed = time.time() - start_time
|
|
47
|
-
sleep_time = self.config.
|
|
47
|
+
sleep_time = self.config.poller.polling_interval - elapsed
|
|
48
48
|
if sleep_time > 0:
|
|
49
49
|
time.sleep(sleep_time)
|
|
@@ -4,21 +4,20 @@ from contextlib import asynccontextmanager
|
|
|
4
4
|
from fastapi import FastAPI, APIRouter
|
|
5
5
|
from fastapi.responses import JSONResponse
|
|
6
6
|
|
|
7
|
-
from
|
|
8
|
-
|
|
9
|
-
from .
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from .
|
|
14
|
-
from .config import NodeConfig
|
|
7
|
+
from .base import EntryPoint
|
|
8
|
+
from ..network.response_handler import ResponseHandler
|
|
9
|
+
from ..protocol.model_map import API_MODEL_MAP
|
|
10
|
+
from ..protocol.api_models import ErrorResponse
|
|
11
|
+
from ..protocol.errors import ProtocolError
|
|
12
|
+
from ..lifecycle import NodeLifecycle
|
|
13
|
+
from ..config.full_node import FullNodeConfig
|
|
15
14
|
|
|
16
15
|
log = structlog.stdlib.get_logger()
|
|
17
16
|
|
|
18
17
|
|
|
19
18
|
class NodeServer(EntryPoint):
|
|
20
19
|
"""Manages FastAPI server and event handling for full nodes."""
|
|
21
|
-
config:
|
|
20
|
+
config: FullNodeConfig
|
|
22
21
|
lifecycle: NodeLifecycle
|
|
23
22
|
response_handler: ResponseHandler
|
|
24
23
|
app: FastAPI
|
|
@@ -26,7 +25,7 @@ class NodeServer(EntryPoint):
|
|
|
26
25
|
|
|
27
26
|
def __init__(
|
|
28
27
|
self,
|
|
29
|
-
config:
|
|
28
|
+
config: FullNodeConfig,
|
|
30
29
|
lifecycle: NodeLifecycle,
|
|
31
30
|
response_handler: ResponseHandler,
|
|
32
31
|
):
|
koi_net/handshaker.py
CHANGED
|
@@ -25,13 +25,13 @@ class Handshaker:
|
|
|
25
25
|
reset the target's cache in case it already knew this node.
|
|
26
26
|
"""
|
|
27
27
|
log.debug(f"Initiating handshake with {target}")
|
|
28
|
-
self.event_queue.
|
|
28
|
+
self.event_queue.push(
|
|
29
29
|
Event.from_rid(
|
|
30
30
|
event_type=EventType.FORGET,
|
|
31
31
|
rid=self.identity.rid),
|
|
32
32
|
target=target
|
|
33
33
|
)
|
|
34
|
-
self.event_queue.
|
|
34
|
+
self.event_queue.push(
|
|
35
35
|
event=Event.from_bundle(
|
|
36
36
|
event_type=EventType.NEW,
|
|
37
37
|
bundle=self.cache.read(self.identity.rid)),
|
koi_net/identity.py
CHANGED
koi_net/lifecycle.py
CHANGED
|
@@ -6,12 +6,12 @@ from rid_lib.types import KoiNetNode
|
|
|
6
6
|
|
|
7
7
|
from .handshaker import Handshaker
|
|
8
8
|
from .network.request_handler import RequestHandler
|
|
9
|
-
from .
|
|
9
|
+
from .workers.kobj_worker import KnowledgeProcessingWorker
|
|
10
10
|
from .network.event_queue import EventQueue
|
|
11
|
-
from .
|
|
11
|
+
from .workers import EventProcessingWorker
|
|
12
12
|
from .protocol.api_models import ErrorResponse
|
|
13
|
-
from .
|
|
14
|
-
from .config import NodeConfig
|
|
13
|
+
from .workers.base import STOP_WORKER
|
|
14
|
+
from .config.core import NodeConfig
|
|
15
15
|
from .processor.kobj_queue import KobjQueue
|
|
16
16
|
from .network.graph import NetworkGraph
|
|
17
17
|
from .identity import NodeIdentity
|
|
@@ -99,7 +99,7 @@ class NodeLifecycle:
|
|
|
99
99
|
|
|
100
100
|
# refresh to reflect changes (if any) in config.yaml
|
|
101
101
|
|
|
102
|
-
self.kobj_queue.
|
|
102
|
+
self.kobj_queue.push(bundle=Bundle.generate(
|
|
103
103
|
rid=self.identity.rid,
|
|
104
104
|
contents=self.identity.profile.model_dump()
|
|
105
105
|
))
|
|
@@ -119,7 +119,7 @@ class NodeLifecycle:
|
|
|
119
119
|
continue
|
|
120
120
|
|
|
121
121
|
for manifest in payload.manifests:
|
|
122
|
-
self.kobj_queue.
|
|
122
|
+
self.kobj_queue.push(
|
|
123
123
|
manifest=manifest,
|
|
124
124
|
source=coordinator
|
|
125
125
|
)
|
koi_net/network/error_handler.py
CHANGED
|
@@ -31,7 +31,7 @@ class ErrorHandler:
|
|
|
31
31
|
|
|
32
32
|
if self.timeout_counter[node] > 3:
|
|
33
33
|
log.debug(f"Exceeded time out limit, forgetting node")
|
|
34
|
-
self.kobj_queue.
|
|
34
|
+
self.kobj_queue.push(rid=node, event_type=EventType.FORGET)
|
|
35
35
|
# do something
|
|
36
36
|
|
|
37
37
|
|
koi_net/network/event_queue.py
CHANGED
|
@@ -20,7 +20,7 @@ class EventQueue:
|
|
|
20
20
|
def __init__(self):
|
|
21
21
|
self.q = Queue()
|
|
22
22
|
|
|
23
|
-
def
|
|
23
|
+
def push(self, event: Event, target: KoiNetNode):
|
|
24
24
|
"""Pushes event to queue of specified node.
|
|
25
25
|
|
|
26
26
|
Event will be sent to webhook or poll queue depending on the
|
koi_net/network/resolver.py
CHANGED
|
@@ -11,7 +11,7 @@ from ..protocol.node import NodeProfile, NodeType
|
|
|
11
11
|
from ..protocol.event import Event
|
|
12
12
|
from ..protocol.api_models import ErrorResponse
|
|
13
13
|
from ..identity import NodeIdentity
|
|
14
|
-
from ..config import NodeConfig
|
|
14
|
+
from ..config.core import NodeConfig
|
|
15
15
|
|
|
16
16
|
log = structlog.stdlib.get_logger()
|
|
17
17
|
|
|
@@ -70,7 +70,7 @@ class ResponseHandler:
|
|
|
70
70
|
log.info(f"Request to broadcast events, received {len(req.events)} event(s)")
|
|
71
71
|
|
|
72
72
|
for event in req.events:
|
|
73
|
-
self.kobj_queue.
|
|
73
|
+
self.kobj_queue.push(event=event, source=source)
|
|
74
74
|
|
|
75
75
|
def poll_events_handler(
|
|
76
76
|
self,
|
|
@@ -2,12 +2,12 @@ from rid_lib.ext import Cache
|
|
|
2
2
|
|
|
3
3
|
from koi_net.effector import Effector
|
|
4
4
|
from koi_net.network.resolver import NetworkResolver
|
|
5
|
-
from .
|
|
6
|
-
from
|
|
7
|
-
from
|
|
8
|
-
from
|
|
9
|
-
from
|
|
10
|
-
from .
|
|
5
|
+
from ..config.core import NodeConfig
|
|
6
|
+
from ..network.graph import NetworkGraph
|
|
7
|
+
from ..network.event_queue import EventQueue
|
|
8
|
+
from ..network.request_handler import RequestHandler
|
|
9
|
+
from ..identity import NodeIdentity
|
|
10
|
+
from .kobj_queue import KobjQueue
|
|
11
11
|
|
|
12
12
|
|
|
13
13
|
class HandlerContext:
|
koi_net/processor/handler.py
CHANGED
|
@@ -2,7 +2,10 @@ from dataclasses import dataclass
|
|
|
2
2
|
from enum import StrEnum
|
|
3
3
|
from typing import Callable
|
|
4
4
|
from rid_lib import RIDType
|
|
5
|
+
|
|
5
6
|
from ..protocol.event import EventType
|
|
7
|
+
from .knowledge_object import KnowledgeObject
|
|
8
|
+
from .context import HandlerContext
|
|
6
9
|
|
|
7
10
|
|
|
8
11
|
class StopChain:
|
|
@@ -32,7 +35,7 @@ class HandlerType(StrEnum):
|
|
|
32
35
|
class KnowledgeHandler:
|
|
33
36
|
"""Handles knowledge processing events of the provided types."""
|
|
34
37
|
|
|
35
|
-
func: Callable
|
|
38
|
+
func: Callable[[HandlerContext, KnowledgeObject], None | KnowledgeObject | StopChain]
|
|
36
39
|
handler_type: HandlerType
|
|
37
40
|
rid_types: list[RIDType] | None
|
|
38
41
|
event_types: list[EventType | None] | None = None
|
|
@@ -7,7 +7,7 @@ from rid_lib.types import KoiNetNode, KoiNetEdge
|
|
|
7
7
|
from koi_net.protocol.node import NodeType
|
|
8
8
|
from .handler import KnowledgeHandler, HandlerType, STOP_CHAIN
|
|
9
9
|
from .knowledge_object import KnowledgeObject
|
|
10
|
-
from
|
|
10
|
+
from .context import HandlerContext
|
|
11
11
|
from ..protocol.event import Event, EventType
|
|
12
12
|
from ..protocol.edge import EdgeProfile, EdgeStatus, EdgeType
|
|
13
13
|
from ..protocol.node import NodeProfile
|
|
@@ -135,7 +135,7 @@ def edge_negotiation_handler(ctx: HandlerContext, kobj: KnowledgeObject):
|
|
|
135
135
|
|
|
136
136
|
if abort:
|
|
137
137
|
event = Event.from_rid(EventType.FORGET, kobj.rid)
|
|
138
|
-
ctx.event_queue.
|
|
138
|
+
ctx.event_queue.push(event, peer_rid, flush=True)
|
|
139
139
|
return STOP_CHAIN
|
|
140
140
|
|
|
141
141
|
else:
|
|
@@ -144,7 +144,7 @@ def edge_negotiation_handler(ctx: HandlerContext, kobj: KnowledgeObject):
|
|
|
144
144
|
edge_profile.status = EdgeStatus.APPROVED
|
|
145
145
|
updated_bundle = Bundle.generate(kobj.rid, edge_profile.model_dump())
|
|
146
146
|
|
|
147
|
-
ctx.kobj_queue.
|
|
147
|
+
ctx.kobj_queue.push(bundle=updated_bundle, event_type=EventType.UPDATE)
|
|
148
148
|
return
|
|
149
149
|
|
|
150
150
|
elif edge_profile.target == ctx.identity.rid:
|
|
@@ -216,7 +216,7 @@ def node_contact_handler(ctx: HandlerContext, kobj: KnowledgeObject):
|
|
|
216
216
|
|
|
217
217
|
# queued for processing
|
|
218
218
|
edge_bundle = Bundle.generate(edge_rid, edge_profile.model_dump())
|
|
219
|
-
ctx.kobj_queue.
|
|
219
|
+
ctx.kobj_queue.push(bundle=edge_bundle)
|
|
220
220
|
|
|
221
221
|
log.info("Catching up on network state")
|
|
222
222
|
|
|
@@ -234,7 +234,7 @@ def node_contact_handler(ctx: HandlerContext, kobj: KnowledgeObject):
|
|
|
234
234
|
|
|
235
235
|
# marked as external since we are handling RIDs from another node
|
|
236
236
|
# will fetch remotely instead of checking local cache
|
|
237
|
-
ctx.kobj_queue.
|
|
237
|
+
ctx.kobj_queue.push(rid=rid, source=kobj.rid)
|
|
238
238
|
log.info("Done")
|
|
239
239
|
|
|
240
240
|
|
|
@@ -296,4 +296,4 @@ def forget_edge_on_node_deletion(ctx: HandlerContext, kobj: KnowledgeObject):
|
|
|
296
296
|
|
|
297
297
|
if kobj.rid in (edge_profile.source, edge_profile.target):
|
|
298
298
|
log.debug("Identified edge with forgotten node")
|
|
299
|
-
ctx.kobj_queue.
|
|
299
|
+
ctx.kobj_queue.push(rid=edge_rid, event_type=EventType.FORGET)
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
from pydantic import BaseModel
|
|
2
2
|
from rid_lib import RID
|
|
3
|
-
from rid_lib.ext import Manifest
|
|
4
|
-
from rid_lib.
|
|
5
|
-
from rid_lib.types.koi_net_node import KoiNetNode
|
|
3
|
+
from rid_lib.ext import Manifest, Bundle
|
|
4
|
+
from rid_lib.types import KoiNetNode
|
|
6
5
|
from ..protocol.event import Event, EventType
|
|
7
6
|
|
|
8
7
|
|
koi_net/processor/kobj_queue.py
CHANGED
koi_net/processor/pipeline.py
CHANGED
|
@@ -13,7 +13,7 @@ from .handler import (
|
|
|
13
13
|
StopChain
|
|
14
14
|
)
|
|
15
15
|
from .knowledge_object import KnowledgeObject
|
|
16
|
-
from
|
|
16
|
+
from .context import HandlerContext
|
|
17
17
|
|
|
18
18
|
log = structlog.stdlib.get_logger()
|
|
19
19
|
|
|
@@ -193,6 +193,6 @@ class KnowledgePipeline:
|
|
|
193
193
|
log.debug("No network targets set")
|
|
194
194
|
|
|
195
195
|
for node in kobj.network_targets:
|
|
196
|
-
self.event_queue.
|
|
196
|
+
self.event_queue.push(kobj.normalized_event, node)
|
|
197
197
|
|
|
198
198
|
kobj = self.call_handler_chain(HandlerType.Final, kobj)
|
koi_net/protocol/node.py
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from enum import StrEnum
|
|
2
|
-
from pydantic import BaseModel
|
|
2
|
+
from pydantic import BaseModel
|
|
3
3
|
from rid_lib import RIDType
|
|
4
4
|
|
|
5
5
|
|
|
@@ -8,8 +8,8 @@ class NodeType(StrEnum):
|
|
|
8
8
|
PARTIAL = "PARTIAL"
|
|
9
9
|
|
|
10
10
|
class NodeProvides(BaseModel):
|
|
11
|
-
event: list[RIDType] =
|
|
12
|
-
state: list[RIDType] =
|
|
11
|
+
event: list[RIDType] = []
|
|
12
|
+
state: list[RIDType] = []
|
|
13
13
|
|
|
14
14
|
class NodeProfile(BaseModel):
|
|
15
15
|
base_url: str | None = None
|
koi_net/protocol/secure.py
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
from rid_lib.types import KoiNetNode
|
|
1
2
|
import structlog
|
|
2
3
|
from base64 import b64decode, b64encode
|
|
3
4
|
from cryptography.hazmat.primitives import hashes
|
|
@@ -134,6 +135,11 @@ class PublicKey:
|
|
|
134
135
|
)
|
|
135
136
|
).decode()
|
|
136
137
|
|
|
138
|
+
def to_node_rid(self, name) -> KoiNetNode:
|
|
139
|
+
return KoiNetNode(
|
|
140
|
+
name=name,
|
|
141
|
+
hash=sha256_hash(self.to_der())
|
|
142
|
+
)
|
|
137
143
|
|
|
138
144
|
def verify(self, signature: str, message: bytes) -> bool:
|
|
139
145
|
# hashed_message = sha256_hash(message.decode())
|
koi_net/secure.py
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import structlog
|
|
2
2
|
from functools import wraps
|
|
3
|
-
|
|
4
3
|
import cryptography.exceptions
|
|
5
4
|
from rid_lib.ext import Bundle, Cache
|
|
6
5
|
from rid_lib.ext.utils import sha256_hash
|
|
@@ -18,7 +17,7 @@ from .protocol.errors import (
|
|
|
18
17
|
InvalidSignatureError,
|
|
19
18
|
InvalidTargetError
|
|
20
19
|
)
|
|
21
|
-
from .config import NodeConfig
|
|
20
|
+
from .config.core import NodeConfig
|
|
22
21
|
|
|
23
22
|
log = structlog.stdlib.get_logger()
|
|
24
23
|
|
|
@@ -6,13 +6,13 @@ import structlog
|
|
|
6
6
|
from rid_lib.ext import Cache
|
|
7
7
|
from rid_lib.types import KoiNetNode
|
|
8
8
|
|
|
9
|
-
from
|
|
10
|
-
from
|
|
11
|
-
from
|
|
12
|
-
from
|
|
13
|
-
from
|
|
14
|
-
from
|
|
15
|
-
from
|
|
9
|
+
from ..config.core import NodeConfig
|
|
10
|
+
from ..network.event_queue import EventQueue, QueuedEvent
|
|
11
|
+
from ..network.request_handler import RequestHandler
|
|
12
|
+
from ..network.poll_event_buffer import PollEventBuffer
|
|
13
|
+
from ..protocol.event import Event
|
|
14
|
+
from ..protocol.node import NodeProfile, NodeType
|
|
15
|
+
from .base import ThreadWorker, STOP_WORKER
|
|
16
16
|
|
|
17
17
|
log = structlog.stdlib.get_logger()
|
|
18
18
|
|
|
@@ -63,7 +63,7 @@ class EventProcessingWorker(ThreadWorker):
|
|
|
63
63
|
return True
|
|
64
64
|
|
|
65
65
|
elif node_profile.node_type == NodeType.PARTIAL:
|
|
66
|
-
self.poll_event_buf.
|
|
66
|
+
self.poll_event_buf.push(item.target, item.event)
|
|
67
67
|
return False
|
|
68
68
|
|
|
69
69
|
elif item.target == self.config.koi_net.first_contact.rid:
|
|
@@ -2,9 +2,9 @@ import queue
|
|
|
2
2
|
import traceback
|
|
3
3
|
import structlog
|
|
4
4
|
|
|
5
|
-
from .pipeline import KnowledgePipeline
|
|
6
|
-
from .kobj_queue import KobjQueue
|
|
7
|
-
from
|
|
5
|
+
from ..processor.pipeline import KnowledgePipeline
|
|
6
|
+
from ..processor.kobj_queue import KobjQueue
|
|
7
|
+
from .base import ThreadWorker, STOP_WORKER
|
|
8
8
|
|
|
9
9
|
log = structlog.stdlib.get_logger()
|
|
10
10
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
koi_net/__init__.py,sha256=9z9lpKDuE7KF-evTBkAZechSvL9eQL4p0-ksmwZwMMU,21
|
|
2
|
+
koi_net/assembler.py,sha256=XR-e0-XHlrbXrZPJoO0tKaPH2xJ80KckfcjOeu9qr4o,3229
|
|
3
|
+
koi_net/core.py,sha256=gnR7moGHYkXHUxoV-mJRxi-tKZuPqvG9lg0jiVfAjXg,2257
|
|
4
|
+
koi_net/default_actions.py,sha256=2y7f9rUaENYRO8traTZbEQ7ySFZP_P8pUqf82bZj8Gk,602
|
|
5
|
+
koi_net/effector.py,sha256=fZEIBtvQQZmJx6HIcRB0jjP_EE00GREWuMQJ5m0uXOc,4937
|
|
6
|
+
koi_net/handshaker.py,sha256=d6s2R2eYxbOfpvRafKHNb_dD7LRdTkF4IsqFu7jQ-sQ,1211
|
|
7
|
+
koi_net/identity.py,sha256=-5YYda4xQ78EeGBspN9whWTuWttsUhZ8gxT2oLDEkpI,574
|
|
8
|
+
koi_net/lifecycle.py,sha256=axmr9KfEXzDT5HMVTVC6komMm9pdPQcODkudp7xVZ1k,4750
|
|
9
|
+
koi_net/logger.py,sha256=EzpQNvNrbi5LmMCobyuN1_wOz5VuMDeaPbLcyMrLKGI,6172
|
|
10
|
+
koi_net/secure.py,sha256=SUJqXScoSXgBs5PeeKtRKyDqGf35tGeNhXhwFa61IXE,4915
|
|
11
|
+
koi_net/utils.py,sha256=4K6BqtifExDUfPP8zJAICgPV1mcabz_MaFB0P0fSnic,411
|
|
12
|
+
koi_net/cli/__init__.py,sha256=Vpq0yLN0ROyF0qQYsyiuWFbjs-zsa90G1DpAv13qaiw,25
|
|
13
|
+
koi_net/cli/commands.py,sha256=5eVsvJAnHjwJdt8MNYrk5zSzWWm1ooiP35bJeQxYIq4,2592
|
|
14
|
+
koi_net/cli/models.py,sha256=9x66SSmIezw61KFbdk7VNoPQTi9JQGxtIlfWMNt5ZfU,1158
|
|
15
|
+
koi_net/config/core.py,sha256=RogkUeDHoQzpvZugqqk_8BkJiGVJX8ekLAZwYXtmsxs,2256
|
|
16
|
+
koi_net/config/full_node.py,sha256=sVxraN_fyM_jFHBhG7LEALHOlYbRvPIONuci8ws_bcA,945
|
|
17
|
+
koi_net/config/loader.py,sha256=3vFVz0V8pv6Ohq9pSMTpa40stYOlFB2do-aBKo7Wr8c,1311
|
|
18
|
+
koi_net/config/partial_node.py,sha256=ALfYXJ4lrMFhKt1nAr-Zn8HBVw9YLBSbN9ykEdwc91E,497
|
|
19
|
+
koi_net/entrypoints/__init__.py,sha256=DdKtM7uXYYZLDaHkzYVOVQh-g2S3bG0xdGAFXok6tj8,61
|
|
20
|
+
koi_net/entrypoints/base.py,sha256=nuaWRD4_0u5Cmieq4MiiJ2NrwOnoC4iaP4ulXXiInmI,85
|
|
21
|
+
koi_net/entrypoints/poller.py,sha256=5oo5Zj2fD43qkE7ai1M_PQi9vxDGbXPoZ4pAjL2H8X4,1472
|
|
22
|
+
koi_net/entrypoints/server.py,sha256=gbmRnSPo-OEaK2TyzTJ_1t-DlmtyARNSiqb07tq74bE,3090
|
|
23
|
+
koi_net/network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
24
|
+
koi_net/network/error_handler.py,sha256=ZH0Py-XuSsnQiSB6rVZ2pywvMcKHr_VywnAiTI8RKEw,1780
|
|
25
|
+
koi_net/network/event_queue.py,sha256=vPrC5-QS0s57ALjdt2ddhNcSMwbvGakCvCKBMx4U6pw,734
|
|
26
|
+
koi_net/network/graph.py,sha256=ZJ1CY-SnYhnZAMm3e9YCbBflk80ZDETnoQKaBk5kLgo,4161
|
|
27
|
+
koi_net/network/poll_event_buffer.py,sha256=Wh4JcGnFaTHbveCzLWcqOzXAU_yk9EkUsukX5hI3pn8,735
|
|
28
|
+
koi_net/network/request_handler.py,sha256=XSX-JAqRua42YOakmia--9NnKcT32Fpoc-7aYfjDpwg,6752
|
|
29
|
+
koi_net/network/resolver.py,sha256=wg9yyJkZbS1G251u4tVav9SeIpH_Aq7FE0rLPvExn3g,5282
|
|
30
|
+
koi_net/network/response_handler.py,sha256=6GewpouDqMl1Ozgfkro_EcUqeJZEfY7msi1U7TQigCY,4212
|
|
31
|
+
koi_net/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
|
+
koi_net/processor/context.py,sha256=64rUQ6Oy3wbA5CtH40hqW7_ZPVDj4Wzw7dtVC0yIxkY,1323
|
|
33
|
+
koi_net/processor/handler.py,sha256=3z1PreLRH_48HU6o9lUD_5CAOgA8O9PuSB9iAusVa_c,2510
|
|
34
|
+
koi_net/processor/knowledge_handlers.py,sha256=H0DTHg2JI4_FvpafHjTMFC2mjjtgTCAew1s7V_fzajE,10908
|
|
35
|
+
koi_net/processor/knowledge_object.py,sha256=NJBNxzYdt_JNYpA71E1vaOuZNIKrkxRpK8l459mjbnc,4129
|
|
36
|
+
koi_net/processor/kobj_queue.py,sha256=tM_ssv2t_2t2A0w_X6rq-Gfxzl0NGCjt387dqTGxKxM,1833
|
|
37
|
+
koi_net/processor/pipeline.py,sha256=4CkOMOXyJ4J17Y5ulnlqJVnINjYqCGI1MBRz2oKylRM,8658
|
|
38
|
+
koi_net/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
+
koi_net/protocol/api_models.py,sha256=lPd_w-sncyrQlTQ__iae9Li1lFARu8nKiMMlXu7-Hls,1856
|
|
40
|
+
koi_net/protocol/consts.py,sha256=bisbVEojPIHlLhkLafBzfIhH25TjNfvTORF1g6YXzIM,243
|
|
41
|
+
koi_net/protocol/edge.py,sha256=PzdEhC43T1KO5iMSEu7I4tiz-7sZxtz41dJfWf-oHA0,1034
|
|
42
|
+
koi_net/protocol/envelope.py,sha256=4SKF4tP1P1ex7UEmYOJt7IP9_8fCWsa_o6ZBOu8SOKk,1877
|
|
43
|
+
koi_net/protocol/errors.py,sha256=uKPQ-TGLouZuK0xd2pXuCQoRTyu_JFsydSCLml13Cz8,595
|
|
44
|
+
koi_net/protocol/event.py,sha256=HxzLN-iCXPyr2YzrswMIkgZYeUdFbBpa5v98dAB06lQ,1328
|
|
45
|
+
koi_net/protocol/model_map.py,sha256=W0quo25HqVkzp8HQ7l_FNTtN4ZX0u7MIqp68Ir81fuk,1671
|
|
46
|
+
koi_net/protocol/node.py,sha256=7GQzHORFr9cP4BqJgir6EGSWCskL-yqmvJksIiLfcWU,409
|
|
47
|
+
koi_net/protocol/secure.py,sha256=_JRwPLLqifQQG_Z8QGeHfICX-pvOsppGvDy6_q8U8I8,5298
|
|
48
|
+
koi_net/workers/__init__.py,sha256=cTCXr4X_ONobHJxN0H8x3hvMgDpQnt7AeDbvcWzyz6Y,98
|
|
49
|
+
koi_net/workers/base.py,sha256=IvtXBTVmthUrURmB9Cn9wffeVv9_Cphsk97_GCLb5NQ,294
|
|
50
|
+
koi_net/workers/event_worker.py,sha256=Z-sShvc0jY3bNqN_P3INhAXFNKWP02YAyhzIFX984lk,4140
|
|
51
|
+
koi_net/workers/kobj_worker.py,sha256=VKGZZZMzSjp1NtuNGCUMmOxRFL0YwbLpTd6XlkQWfF0,1239
|
|
52
|
+
koi_net-1.2.0b3.dist-info/METADATA,sha256=PM-J7K9mH88xHgSeuDpcawOAQU8J8W3BqUJJ90cTUGY,37347
|
|
53
|
+
koi_net-1.2.0b3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
54
|
+
koi_net-1.2.0b3.dist-info/entry_points.txt,sha256=l7He_JTyXrfKIHkttnPWXHI717v8WpLLfCduL5QcEWA,40
|
|
55
|
+
koi_net-1.2.0b3.dist-info/licenses/LICENSE,sha256=03mgCL5qth2aD9C3F3qNVs4sFJSpK9kjtYCyOwdSp7s,1069
|
|
56
|
+
koi_net-1.2.0b3.dist-info/RECORD,,
|
koi_net/config.py
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
import os
|
|
2
|
-
from rid_lib import RIDType
|
|
3
|
-
from ruamel.yaml import YAML
|
|
4
|
-
from pydantic import BaseModel, Field, PrivateAttr
|
|
5
|
-
from dotenv import load_dotenv
|
|
6
|
-
from rid_lib.ext.utils import sha256_hash
|
|
7
|
-
from rid_lib.types import KoiNetNode
|
|
8
|
-
from .protocol.secure import PrivateKey
|
|
9
|
-
from .protocol.node import NodeProfile, NodeType
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
class ServerConfig(BaseModel):
|
|
13
|
-
"""Config for the node server (full node only)."""
|
|
14
|
-
|
|
15
|
-
host: str = "127.0.0.1"
|
|
16
|
-
port: int = 8000
|
|
17
|
-
path: str | None = "/koi-net"
|
|
18
|
-
|
|
19
|
-
@property
|
|
20
|
-
def url(self) -> str:
|
|
21
|
-
return f"http://{self.host}:{self.port}{self.path or ''}"
|
|
22
|
-
|
|
23
|
-
class NodeContact(BaseModel):
|
|
24
|
-
rid: KoiNetNode | None = None
|
|
25
|
-
url: str | None = None
|
|
26
|
-
|
|
27
|
-
class KoiNetConfig(BaseModel):
|
|
28
|
-
"""Config for KOI-net."""
|
|
29
|
-
|
|
30
|
-
node_name: str
|
|
31
|
-
node_rid: KoiNetNode | None = None
|
|
32
|
-
node_profile: NodeProfile
|
|
33
|
-
|
|
34
|
-
rid_types_of_interest: list[RIDType] = Field(
|
|
35
|
-
default_factory=lambda: [KoiNetNode])
|
|
36
|
-
|
|
37
|
-
cache_directory_path: str = ".rid_cache"
|
|
38
|
-
event_queues_path: str = "event_queues.json"
|
|
39
|
-
private_key_pem_path: str = "priv_key.pem"
|
|
40
|
-
polling_interval: int = 5
|
|
41
|
-
|
|
42
|
-
first_contact: NodeContact = Field(default_factory=NodeContact)
|
|
43
|
-
|
|
44
|
-
_priv_key: PrivateKey | None = PrivateAttr(default=None)
|
|
45
|
-
|
|
46
|
-
class EnvConfig(BaseModel):
|
|
47
|
-
"""Config for environment variables.
|
|
48
|
-
|
|
49
|
-
Values set in the config are the variables names, and are loaded
|
|
50
|
-
from the environment at runtime. For example, if the config YAML
|
|
51
|
-
sets `priv_key_password: PRIV_KEY_PASSWORD` accessing
|
|
52
|
-
`priv_key_password` would retrieve the value of `PRIV_KEY_PASSWORD`
|
|
53
|
-
from the environment.
|
|
54
|
-
"""
|
|
55
|
-
|
|
56
|
-
priv_key_password: str | None = "PRIV_KEY_PASSWORD"
|
|
57
|
-
|
|
58
|
-
def __init__(self, **kwargs):
|
|
59
|
-
super().__init__(**kwargs)
|
|
60
|
-
load_dotenv()
|
|
61
|
-
|
|
62
|
-
def __getattribute__(self, name):
|
|
63
|
-
value = super().__getattribute__(name)
|
|
64
|
-
if name in type(self).model_fields:
|
|
65
|
-
env_val = os.getenv(value)
|
|
66
|
-
if env_val is None:
|
|
67
|
-
raise ValueError(f"Required environment variable {value} not set")
|
|
68
|
-
return env_val
|
|
69
|
-
return value
|
|
70
|
-
|
|
71
|
-
class NodeConfig(BaseModel):
|
|
72
|
-
"""Base configuration class for all nodes.
|
|
73
|
-
|
|
74
|
-
Designed to be extensible for custom node implementations. Classes
|
|
75
|
-
inheriting from `NodeConfig` may add additional config groups.
|
|
76
|
-
"""
|
|
77
|
-
|
|
78
|
-
server: ServerConfig = Field(default_factory=ServerConfig)
|
|
79
|
-
koi_net: KoiNetConfig
|
|
80
|
-
env: EnvConfig = Field(default_factory=EnvConfig)
|
|
81
|
-
|
|
82
|
-
_file_path: str = PrivateAttr(default="config.yaml")
|
|
83
|
-
_file_content: str | None = PrivateAttr(default=None)
|
|
84
|
-
|
|
85
|
-
@classmethod
|
|
86
|
-
def load_from_yaml(
|
|
87
|
-
cls,
|
|
88
|
-
file_path: str = "config.yaml",
|
|
89
|
-
generate_missing: bool = True
|
|
90
|
-
):
|
|
91
|
-
"""Loads config state from YAML file.
|
|
92
|
-
|
|
93
|
-
Defaults to `config.yaml`. If `generate_missing` is set to
|
|
94
|
-
`True`, a private key and RID will be generated if not already
|
|
95
|
-
present in the config.
|
|
96
|
-
"""
|
|
97
|
-
yaml = YAML()
|
|
98
|
-
|
|
99
|
-
try:
|
|
100
|
-
with open(file_path, "r") as f:
|
|
101
|
-
file_content = f.read()
|
|
102
|
-
config_data = yaml.load(file_content)
|
|
103
|
-
config = cls.model_validate(config_data)
|
|
104
|
-
config._file_content = file_content
|
|
105
|
-
|
|
106
|
-
except FileNotFoundError:
|
|
107
|
-
# empty_fields = {}
|
|
108
|
-
# for name, field in cls.model_fields.items():
|
|
109
|
-
|
|
110
|
-
# if field.default is None or field.default_factory is None:
|
|
111
|
-
# print(empty_fields)
|
|
112
|
-
config = cls()
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
config._file_path = file_path
|
|
116
|
-
|
|
117
|
-
if generate_missing:
|
|
118
|
-
if not config.koi_net.node_rid:
|
|
119
|
-
priv_key = PrivateKey.generate()
|
|
120
|
-
pub_key = priv_key.public_key()
|
|
121
|
-
|
|
122
|
-
config.koi_net.node_rid = KoiNetNode(
|
|
123
|
-
config.koi_net.node_name,
|
|
124
|
-
sha256_hash(pub_key.to_der())
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
with open(config.koi_net.private_key_pem_path, "w") as f:
|
|
128
|
-
f.write(
|
|
129
|
-
priv_key.to_pem(config.env.priv_key_password)
|
|
130
|
-
)
|
|
131
|
-
|
|
132
|
-
config.koi_net.node_profile.public_key = pub_key.to_der()
|
|
133
|
-
|
|
134
|
-
if config.koi_net.node_profile.node_type == NodeType.FULL:
|
|
135
|
-
config.koi_net.node_profile.base_url = (
|
|
136
|
-
config.koi_net.node_profile.base_url or config.server.url
|
|
137
|
-
)
|
|
138
|
-
|
|
139
|
-
config.save_to_yaml()
|
|
140
|
-
|
|
141
|
-
return config
|
|
142
|
-
|
|
143
|
-
def save_to_yaml(self):
|
|
144
|
-
"""Saves config state to YAML file.
|
|
145
|
-
|
|
146
|
-
File path is set by `load_from_yaml` class method.
|
|
147
|
-
"""
|
|
148
|
-
|
|
149
|
-
yaml = YAML()
|
|
150
|
-
|
|
151
|
-
with open(self._file_path, "w") as f:
|
|
152
|
-
try:
|
|
153
|
-
config_data = self.model_dump(mode="json")
|
|
154
|
-
yaml.dump(config_data, f)
|
|
155
|
-
except Exception as e:
|
|
156
|
-
if self._file_content:
|
|
157
|
-
f.seek(0)
|
|
158
|
-
f.truncate()
|
|
159
|
-
f.write(self._file_content)
|
|
160
|
-
raise e
|
|
161
|
-
|
koi_net/interfaces/entrypoint.py
DELETED
koi_net/sentry.py
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
# import sentry_sdk
|
|
2
|
-
# from sentry_sdk.integrations.logging import LoggingIntegration
|
|
3
|
-
|
|
4
|
-
# sentry_sdk.init(
|
|
5
|
-
# dsn="https://7bbafef3c7dbd652506db3cb2aca9f98@o4510149352357888.ingest.us.sentry.io/4510149355765760",
|
|
6
|
-
# # Add data like request headers and IP for users,
|
|
7
|
-
# # see https://docs.sentry.io/platforms/python/data-management/data-collected/ for more info
|
|
8
|
-
# send_default_pii=True,
|
|
9
|
-
# enable_logs=True,
|
|
10
|
-
# integrations=[
|
|
11
|
-
# LoggingIntegration(sentry_logs_level=None)
|
|
12
|
-
# ]
|
|
13
|
-
# )
|
koi_net-1.2.0b2.dist-info/RECORD
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
koi_net/__init__.py,sha256=ZJQHfYaMtu3Qv6ZtKxq49N0T1GbVd3dvrjXZdeNYnQw,41
|
|
2
|
-
koi_net/assembler.py,sha256=kV7qB1xnPvAVUrunaNgx4f9lb2qQlvlA4zZs1xKq62Q,2831
|
|
3
|
-
koi_net/config.py,sha256=yV53GFQrJchyKKRs3sOhj27pyM6rwiUhIgDZ81rvZ48,5238
|
|
4
|
-
koi_net/context.py,sha256=mBKMR1o6Tqy_cyhj7_niGkMSMOQeEMPhP9cpNDlML1s,1323
|
|
5
|
-
koi_net/core.py,sha256=owbJYN_kCMwKz3ecWXt_tQXOEECL_q1uq4CcFAuR6EA,2428
|
|
6
|
-
koi_net/default_actions.py,sha256=y9oaDeb3jJGSvVbuonmyGWkKWlzpEX3V32MjgEuYWc8,622
|
|
7
|
-
koi_net/effector.py,sha256=0hW2NnHWjVZyRPXWh_X_0EBxqpCJBBhJCHFvB6uC3SM,4941
|
|
8
|
-
koi_net/handshaker.py,sha256=sd2bYe7Fh5hCTq5q18_knKWAMzvH5a6zHzCcBKbkhWQ,1229
|
|
9
|
-
koi_net/identity.py,sha256=jZjTSlgO8aJhfOx6-ppQVveHih6h0dP2Gtbsw6GGdTI,569
|
|
10
|
-
koi_net/lifecycle.py,sha256=AhJCkXHuBhUHMXXAzI3akz0pTRE77aNEHwjsnbe98TE,4775
|
|
11
|
-
koi_net/logger.py,sha256=EzpQNvNrbi5LmMCobyuN1_wOz5VuMDeaPbLcyMrLKGI,6172
|
|
12
|
-
koi_net/poller.py,sha256=OZLYAMHxXxM75ENetHd_nnNaiiZTSpMgeP3xxAphVEg,1463
|
|
13
|
-
koi_net/secure.py,sha256=qayAzO7xWF8wa33rmNCTupVVaYXwNuimlXpPFWJfQT8,4911
|
|
14
|
-
koi_net/sentry.py,sha256=9UCVMPoEzua3KMUHe4inciqEnqTF_gNSQO2zhpUN8ts,506
|
|
15
|
-
koi_net/server.py,sha256=GJbkHp2BmDhSHWdF6PObLus7f0BiMZuhcZALj7kNiF4,3087
|
|
16
|
-
koi_net/utils.py,sha256=4K6BqtifExDUfPP8zJAICgPV1mcabz_MaFB0P0fSnic,411
|
|
17
|
-
koi_net/cli/__init__.py,sha256=Vpq0yLN0ROyF0qQYsyiuWFbjs-zsa90G1DpAv13qaiw,25
|
|
18
|
-
koi_net/cli/commands.py,sha256=5eVsvJAnHjwJdt8MNYrk5zSzWWm1ooiP35bJeQxYIq4,2592
|
|
19
|
-
koi_net/cli/models.py,sha256=ON-rqMgHDng3J2hbBbGYzkynaWc9Tq4QfOJIu_6pFuA,1190
|
|
20
|
-
koi_net/interfaces/entrypoint.py,sha256=8FEG1r0YIws_1AojTtIPWB-Th3GOS3U2qi89RlyBJYs,80
|
|
21
|
-
koi_net/interfaces/worker.py,sha256=IvtXBTVmthUrURmB9Cn9wffeVv9_Cphsk97_GCLb5NQ,294
|
|
22
|
-
koi_net/network/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
23
|
-
koi_net/network/error_handler.py,sha256=4i_r7EWBW52_bhdmyU-1A_Cnu0Q-jHO9O1EXgO1NGws,1784
|
|
24
|
-
koi_net/network/event_queue.py,sha256=JqSMRk_PvBn5hlnUKF2jl9uxaOCX793fwZsblx-pEKs,743
|
|
25
|
-
koi_net/network/graph.py,sha256=ZJ1CY-SnYhnZAMm3e9YCbBflk80ZDETnoQKaBk5kLgo,4161
|
|
26
|
-
koi_net/network/poll_event_buffer.py,sha256=PO9HnmlhQ0V-uPGOf5b15GhbJtjAzEfMDf6TtsQLtPA,734
|
|
27
|
-
koi_net/network/request_handler.py,sha256=XSX-JAqRua42YOakmia--9NnKcT32Fpoc-7aYfjDpwg,6752
|
|
28
|
-
koi_net/network/resolver.py,sha256=i8YsdIYVo9--YYW5AK9PO-f_lpXIVKZONImJ9wYMySY,5277
|
|
29
|
-
koi_net/network/response_handler.py,sha256=OyEd_5ltQf-sdGDI4QalPuHVLqrSMpAjRQCDtlNR8WU,4216
|
|
30
|
-
koi_net/processor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
-
koi_net/processor/event_worker.py,sha256=z6Zef5TFDokwywSNzaMh6oDmEaAoss6m--dRHHmU3YY,4190
|
|
32
|
-
koi_net/processor/handler.py,sha256=PJlQCPfKm3zYsJrwmGIw5xZmc6vArKz_UoeJuXBj16Y,2356
|
|
33
|
-
koi_net/processor/handlers.py,sha256=rGvjrud72szKBM8rhZRrQ2qO8Ng97oGLIfUG9Af-oxw,10934
|
|
34
|
-
koi_net/processor/knowledge_object.py,sha256=0VyBOqkCoINMK3fqYhLlXU-Ri7gKEpJloDHfhaGITxg,4172
|
|
35
|
-
koi_net/processor/kobj_queue.py,sha256=A4jdS0WCrL-fg3Kl8bHPbzIjSfYNGOBBqzCbSJhfMZ4,1837
|
|
36
|
-
koi_net/processor/kobj_worker.py,sha256=26DG8fU3hLbKZmS6mcuOEnUWcVLkq-1fl8AGNLrYFY0,1237
|
|
37
|
-
koi_net/processor/pipeline.py,sha256=FpU3nORIeJxJuX8QHTSqIji8iMU69GuTR4UMeThOzUo,8668
|
|
38
|
-
koi_net/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
39
|
-
koi_net/protocol/api_models.py,sha256=lPd_w-sncyrQlTQ__iae9Li1lFARu8nKiMMlXu7-Hls,1856
|
|
40
|
-
koi_net/protocol/consts.py,sha256=bisbVEojPIHlLhkLafBzfIhH25TjNfvTORF1g6YXzIM,243
|
|
41
|
-
koi_net/protocol/edge.py,sha256=PzdEhC43T1KO5iMSEu7I4tiz-7sZxtz41dJfWf-oHA0,1034
|
|
42
|
-
koi_net/protocol/envelope.py,sha256=4SKF4tP1P1ex7UEmYOJt7IP9_8fCWsa_o6ZBOu8SOKk,1877
|
|
43
|
-
koi_net/protocol/errors.py,sha256=uKPQ-TGLouZuK0xd2pXuCQoRTyu_JFsydSCLml13Cz8,595
|
|
44
|
-
koi_net/protocol/event.py,sha256=HxzLN-iCXPyr2YzrswMIkgZYeUdFbBpa5v98dAB06lQ,1328
|
|
45
|
-
koi_net/protocol/model_map.py,sha256=W0quo25HqVkzp8HQ7l_FNTtN4ZX0u7MIqp68Ir81fuk,1671
|
|
46
|
-
koi_net/protocol/node.py,sha256=KH_SjHDzW-V4pn2tqpTDhIzfuCgKgM1YqCafyofLN3k,466
|
|
47
|
-
koi_net/protocol/secure.py,sha256=y3-l0ldQ4oQ6ReEmunDy0ncF836kZvLdGFeEgmuJw44,5110
|
|
48
|
-
koi_net-1.2.0b2.dist-info/METADATA,sha256=t4T3T0cGyG24XvptQg6vy10B8_gHCWGW-s0PntA9aX8,37347
|
|
49
|
-
koi_net-1.2.0b2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
50
|
-
koi_net-1.2.0b2.dist-info/entry_points.txt,sha256=l7He_JTyXrfKIHkttnPWXHI717v8WpLLfCduL5QcEWA,40
|
|
51
|
-
koi_net-1.2.0b2.dist-info/licenses/LICENSE,sha256=03mgCL5qth2aD9C3F3qNVs4sFJSpK9kjtYCyOwdSp7s,1069
|
|
52
|
-
koi_net-1.2.0b2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|