kept 0.0.1__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.
- kept/__init__.py +3 -0
- kept/app/__init__.py +0 -0
- kept/app/cli/__init__.py +0 -0
- kept/app/cli/commands/__init__.py +0 -0
- kept/app/cli/commands/get.py +167 -0
- kept/app/cli/keeper.py +41 -0
- kept/core/__init__.py +0 -0
- kept/core/authentication.py +284 -0
- kept/core/exceptions.py +14 -0
- kept/core/tcp/__init__.py +0 -0
- kept/core/tcp/client.py +235 -0
- kept/core/tcp/server.py +216 -0
- kept/db/__init__.py +0 -0
- kept/db/basing.py +78 -0
- kept/essr/__init__.py +0 -0
- kept/essr/client/__init__.py +4 -0
- kept/essr/client/client.py +457 -0
- kept/essr/client/handlers.py +86 -0
- kept/essr/client/requests.py +208 -0
- kept/essr/client/responses.py +57 -0
- kept/essr/server/__init__.py +15 -0
- kept/essr/server/applications.py +355 -0
- kept/essr/server/datastructures.py +188 -0
- kept/essr/server/requests.py +180 -0
- kept/essr/server/responses.py +373 -0
- kept/essr/server/types.py +14 -0
- kept/hk/__init__.py +0 -0
- kept/hk/configing.py +201 -0
- kept/hk/essring.py +583 -0
- kept/mcp/__init__.py +0 -0
- kept/mcp/client/__init__.py +0 -0
- kept/mcp/client/essr.py +385 -0
- kept/mcp/server/__init__.py +0 -0
- kept/mcp/server/essr.py +781 -0
- kept/mcp/server/essr_manager.py +279 -0
- kept/mcp/shared/__init__.py +0 -0
- kept/mcp/shared/_essr_utils.py +74 -0
- kept-0.0.1.dist-info/METADATA +20 -0
- kept-0.0.1.dist-info/RECORD +43 -0
- kept-0.0.1.dist-info/WHEEL +5 -0
- kept-0.0.1.dist-info/entry_points.txt +2 -0
- kept-0.0.1.dist-info/licenses/LICENSE +201 -0
- kept-0.0.1.dist-info/top_level.txt +1 -0
kept/__init__.py
ADDED
kept/app/__init__.py
ADDED
|
File without changes
|
kept/app/cli/__init__.py
ADDED
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
heki.app.cli module
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import argparse
|
|
8
|
+
import asyncio
|
|
9
|
+
from urllib.parse import urlparse, parse_qs
|
|
10
|
+
|
|
11
|
+
from keri import help
|
|
12
|
+
from keri import kering
|
|
13
|
+
from keri.app import connecting
|
|
14
|
+
from keri.app.cli.common import existing
|
|
15
|
+
|
|
16
|
+
from kept.core.authentication import CryptSigner
|
|
17
|
+
from kept.essr.client import AsyncClient
|
|
18
|
+
|
|
19
|
+
parser = argparse.ArgumentParser(
|
|
20
|
+
description="Perform an kurl (essr encoded) request against the provided URL."
|
|
21
|
+
)
|
|
22
|
+
parser.set_defaults(handler=lambda args: asyncio.run(launch(args)))
|
|
23
|
+
parser.add_argument("url", help="ESSR URL to process", metavar="<url>")
|
|
24
|
+
parser.add_argument(
|
|
25
|
+
"--name",
|
|
26
|
+
"-n",
|
|
27
|
+
help="keystore name and file location of KERI keystore",
|
|
28
|
+
required=False,
|
|
29
|
+
default="owl",
|
|
30
|
+
)
|
|
31
|
+
parser.add_argument("--alias", action="store", required=False, default="owl")
|
|
32
|
+
parser.add_argument(
|
|
33
|
+
"--base",
|
|
34
|
+
"-b",
|
|
35
|
+
help="additional optional prefix to file location of KERI keystore",
|
|
36
|
+
required=False,
|
|
37
|
+
default="",
|
|
38
|
+
)
|
|
39
|
+
parser.add_argument(
|
|
40
|
+
"--passcode",
|
|
41
|
+
"-p",
|
|
42
|
+
help="21 character encryption passcode for keystore (is not saved)",
|
|
43
|
+
dest="bran",
|
|
44
|
+
default=None,
|
|
45
|
+
) # passcode => bran
|
|
46
|
+
parser.add_argument("--remote", action="store", required=False, default=None)
|
|
47
|
+
|
|
48
|
+
parser.add_argument(
|
|
49
|
+
"--json", "-j", help="JSON data to send with request", type=str, default=None
|
|
50
|
+
)
|
|
51
|
+
parser.add_argument(
|
|
52
|
+
"--header",
|
|
53
|
+
"-H",
|
|
54
|
+
help='HTTP header in format "Name: Value"',
|
|
55
|
+
action="append",
|
|
56
|
+
default=[],
|
|
57
|
+
)
|
|
58
|
+
parser.add_argument(
|
|
59
|
+
"--files",
|
|
60
|
+
"-F",
|
|
61
|
+
help='HTTP header in format "Name: Value"',
|
|
62
|
+
action="append",
|
|
63
|
+
default=[],
|
|
64
|
+
)
|
|
65
|
+
parser.add_argument(
|
|
66
|
+
"--data", "-d", help="Form data to send with request", type=str, default=None
|
|
67
|
+
)
|
|
68
|
+
parser.add_argument(
|
|
69
|
+
"--timeout",
|
|
70
|
+
"-t",
|
|
71
|
+
help="Timeout in seconds for waiting for response",
|
|
72
|
+
type=int,
|
|
73
|
+
default=10,
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
logger = help.ogler.getLogger()
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
async def launch(args):
|
|
80
|
+
# Arguments from the command line
|
|
81
|
+
name = args.name
|
|
82
|
+
alias = args.alias
|
|
83
|
+
bran = args.bran
|
|
84
|
+
|
|
85
|
+
parsed = urlparse(args.url)
|
|
86
|
+
|
|
87
|
+
# Override name, alias and passcode if provided in the URL
|
|
88
|
+
if parsed.username:
|
|
89
|
+
name = parsed.username
|
|
90
|
+
|
|
91
|
+
if parsed.password:
|
|
92
|
+
if ":" in parsed.password:
|
|
93
|
+
alias, bran = parsed.password.split(":", maxsplit=1)
|
|
94
|
+
else:
|
|
95
|
+
alias = parsed.password
|
|
96
|
+
|
|
97
|
+
with existing.existingHab(name=name, alias=alias, base=args.base, bran=bran) as (
|
|
98
|
+
hby,
|
|
99
|
+
hab,
|
|
100
|
+
):
|
|
101
|
+
if not hab:
|
|
102
|
+
raise kering.ConfigurationError(
|
|
103
|
+
f"Identifier '{alias}' must already exist, exiting."
|
|
104
|
+
)
|
|
105
|
+
org = connecting.Organizer(hby=hby)
|
|
106
|
+
|
|
107
|
+
# Determine the remote identifier to use, start with the --remote argument, then fallback to the hostname
|
|
108
|
+
root = args.remote
|
|
109
|
+
|
|
110
|
+
if not root:
|
|
111
|
+
root = parsed.hostname
|
|
112
|
+
|
|
113
|
+
target = None
|
|
114
|
+
if root in hby.kevers:
|
|
115
|
+
target = hby.kevers[root].pre
|
|
116
|
+
else:
|
|
117
|
+
contacts = org.find("alias", root)
|
|
118
|
+
for contact in contacts:
|
|
119
|
+
if contact["alias"] == root:
|
|
120
|
+
target = contact["id"]
|
|
121
|
+
|
|
122
|
+
if not target:
|
|
123
|
+
raise kering.ConfigurationError(
|
|
124
|
+
f"Invalid identifier '{root}' for {args.url}, not found"
|
|
125
|
+
)
|
|
126
|
+
|
|
127
|
+
# Build request parameters from arguments
|
|
128
|
+
headers = {}
|
|
129
|
+
for header in args.header:
|
|
130
|
+
name, value = header.split(":", 1)
|
|
131
|
+
headers[name.strip()] = value.strip()
|
|
132
|
+
|
|
133
|
+
data = None
|
|
134
|
+
if args.data:
|
|
135
|
+
if args.data.startswith("@"):
|
|
136
|
+
f = open(args.data[1:], "r")
|
|
137
|
+
data = f.read()
|
|
138
|
+
else:
|
|
139
|
+
data = args.data.encode("utf-8")
|
|
140
|
+
|
|
141
|
+
return_route = "/owl/response"
|
|
142
|
+
|
|
143
|
+
# Parse query parameters into dictionary
|
|
144
|
+
query_params = {}
|
|
145
|
+
if parsed.query:
|
|
146
|
+
parsed_params = parse_qs(parsed.query)
|
|
147
|
+
query_params = {
|
|
148
|
+
k: v[0] if len(v) == 1 else v for k, v in parsed_params.items()
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
client = AsyncClient(
|
|
152
|
+
params=query_params,
|
|
153
|
+
return_route=return_route,
|
|
154
|
+
headers=list(headers.items()),
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
crypt_signer = CryptSigner(hby=hby, hab=hab, encryption_target=target)
|
|
158
|
+
response = await client.request(
|
|
159
|
+
crypt_signer=crypt_signer,
|
|
160
|
+
url=args.url,
|
|
161
|
+
json=args.json,
|
|
162
|
+
files=None, # TODO: support files from the commandline, maybe?
|
|
163
|
+
data=data,
|
|
164
|
+
)
|
|
165
|
+
|
|
166
|
+
print(response.headers)
|
|
167
|
+
print(await response.aread())
|
kept/app/cli/keeper.py
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
kept.app.cli module
|
|
4
|
+
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
import multicommand
|
|
8
|
+
from keri import help
|
|
9
|
+
|
|
10
|
+
from keri.app import directing
|
|
11
|
+
from kept.app.cli import commands
|
|
12
|
+
|
|
13
|
+
logger = help.ogler.getLogger()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def main():
|
|
17
|
+
parser = multicommand.create_parser(commands)
|
|
18
|
+
args = parser.parse_args()
|
|
19
|
+
|
|
20
|
+
if not hasattr(args, "handler"):
|
|
21
|
+
parser.print_help()
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
try:
|
|
25
|
+
doers = args.handler(args)
|
|
26
|
+
directing.runController(doers=doers, expire=0.0)
|
|
27
|
+
|
|
28
|
+
except Exception as ex:
|
|
29
|
+
import os
|
|
30
|
+
|
|
31
|
+
if os.getenv("DEBUG_KEPT"):
|
|
32
|
+
import traceback
|
|
33
|
+
|
|
34
|
+
traceback.print_exc()
|
|
35
|
+
else:
|
|
36
|
+
print(f"ERR: {ex}")
|
|
37
|
+
return -1
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
if __name__ == "__main__":
|
|
41
|
+
main()
|
kept/core/__init__.py
ADDED
|
File without changes
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import math
|
|
2
|
+
import random
|
|
3
|
+
|
|
4
|
+
import cbor
|
|
5
|
+
import pysodium
|
|
6
|
+
from keri import kering, help, core
|
|
7
|
+
from keri.core import coring, serdering, MtrDex
|
|
8
|
+
from keri.core.counting import CtrDex_1_0
|
|
9
|
+
from keri.db import dbing
|
|
10
|
+
from keri.help import helping
|
|
11
|
+
from keri.kering import ConfigurationError
|
|
12
|
+
from keri.peer import exchanging
|
|
13
|
+
|
|
14
|
+
from kept.db import basing
|
|
15
|
+
|
|
16
|
+
logger = help.ogler.getLogger()
|
|
17
|
+
|
|
18
|
+
CHUNK_SIZE = 65536
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class CryptSigner:
|
|
22
|
+
|
|
23
|
+
def __init__(self, hby, hab, rt=None, encryption_target=None):
|
|
24
|
+
"""Factory for creating delegates for a give Delegator Hab1
|
|
25
|
+
|
|
26
|
+
Parameters:
|
|
27
|
+
hby (Habery): database environment and Hab factory
|
|
28
|
+
rt (RouteTable): RACK database environment
|
|
29
|
+
hab (Hab): delegator's hab
|
|
30
|
+
|
|
31
|
+
"""
|
|
32
|
+
self.hby = hby
|
|
33
|
+
self._hab = hab
|
|
34
|
+
self.rt = (
|
|
35
|
+
rt
|
|
36
|
+
if rt is not None
|
|
37
|
+
else basing.RouteTable(name=hby.name, reopen=True, temp=hby.temp)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
self.encryption_target = encryption_target
|
|
41
|
+
self.scan = set()
|
|
42
|
+
|
|
43
|
+
def make(
|
|
44
|
+
self,
|
|
45
|
+
count=10,
|
|
46
|
+
algo="randy",
|
|
47
|
+
salt=None,
|
|
48
|
+
icount=1,
|
|
49
|
+
isith="1",
|
|
50
|
+
ncount=1,
|
|
51
|
+
nsith="1",
|
|
52
|
+
):
|
|
53
|
+
"""Create delegates from the delegator
|
|
54
|
+
|
|
55
|
+
Parameters:
|
|
56
|
+
count (int): the number of delegates to create
|
|
57
|
+
algo (str): key generation algo, "salty" or "randy"
|
|
58
|
+
salt: (str): 21 character length key generation salt
|
|
59
|
+
icount (int): number of signing keys to create per delegate
|
|
60
|
+
isith: (str): signing threshold
|
|
61
|
+
ncount (int): number of rotation keys to create per delegate
|
|
62
|
+
nsith: (str): rotation threshold
|
|
63
|
+
|
|
64
|
+
Returns:
|
|
65
|
+
list: a list of delegate Habs
|
|
66
|
+
|
|
67
|
+
"""
|
|
68
|
+
start = 0
|
|
69
|
+
for hab in self.hby.habs.values():
|
|
70
|
+
if hab.name.startswith(hab.name):
|
|
71
|
+
start += 1
|
|
72
|
+
|
|
73
|
+
anchors = list()
|
|
74
|
+
delegates = list()
|
|
75
|
+
for idx in range(count):
|
|
76
|
+
alias = f"{self._hab.name}-{idx + start}"
|
|
77
|
+
|
|
78
|
+
if self.hby.habByName(alias) is not None:
|
|
79
|
+
raise ValueError(
|
|
80
|
+
f"{alias} is already in use, please pick another alias prefix"
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
kwargs = dict()
|
|
84
|
+
kwargs["algo"] = algo
|
|
85
|
+
if algo == "salty":
|
|
86
|
+
if salt is None or len(salt) != 24:
|
|
87
|
+
raise ValueError("Salt is required and must be 24 characters long")
|
|
88
|
+
|
|
89
|
+
kwargs["salt"] = salt
|
|
90
|
+
kwargs["icount"] = int(icount)
|
|
91
|
+
kwargs["isith"] = int(isith)
|
|
92
|
+
kwargs["ncount"] = int(ncount)
|
|
93
|
+
kwargs["nsith"] = int(nsith)
|
|
94
|
+
|
|
95
|
+
elif algo == "randy":
|
|
96
|
+
kwargs["salt"] = None
|
|
97
|
+
kwargs["icount"] = int(icount)
|
|
98
|
+
kwargs["isith"] = int(isith)
|
|
99
|
+
kwargs["ncount"] = int(ncount)
|
|
100
|
+
kwargs["nsith"] = int(nsith)
|
|
101
|
+
|
|
102
|
+
kwargs["delpre"] = self._hab.pre
|
|
103
|
+
kwargs["estOnly"] = False
|
|
104
|
+
|
|
105
|
+
hab = self.hby.makeHab(name=alias, **kwargs)
|
|
106
|
+
delegates.append(hab)
|
|
107
|
+
anchors.append(dict(i=hab.pre, s="0", d=hab.pre))
|
|
108
|
+
self.rt.dlgs.add(keys=(self._hab.pre,), val=hab.pre)
|
|
109
|
+
|
|
110
|
+
self._hab.interact(data=anchors)
|
|
111
|
+
|
|
112
|
+
for anchor in anchors:
|
|
113
|
+
seqner = coring.Seqner(sn=self._hab.kever.serder.sn)
|
|
114
|
+
couple = seqner.qb64b + self._hab.kever.serder.saidb
|
|
115
|
+
dgkey = dbing.dgKey(anchor["i"], anchor["d"])
|
|
116
|
+
self.hby.db.setAes(
|
|
117
|
+
dgkey, couple
|
|
118
|
+
) # authorizer event seal (delegator/issuer)
|
|
119
|
+
|
|
120
|
+
return delegates
|
|
121
|
+
|
|
122
|
+
def delegates(self, aid):
|
|
123
|
+
return self.rt.dlgs.get(keys=(aid,))
|
|
124
|
+
|
|
125
|
+
def scan_for_delegates(self, aid):
|
|
126
|
+
if aid not in self.scan:
|
|
127
|
+
scan_for_delegates(self.hby, self.rt, aid)
|
|
128
|
+
self.scan.add(aid)
|
|
129
|
+
|
|
130
|
+
@property
|
|
131
|
+
def pre(self):
|
|
132
|
+
return self._hab.pre
|
|
133
|
+
|
|
134
|
+
def hab(self, aid):
|
|
135
|
+
if (
|
|
136
|
+
delegate := self.rt.cur.get(keys=(aid,))
|
|
137
|
+
) is not None and delegate in self.hby.habs:
|
|
138
|
+
return self.hby.habs[delegate]
|
|
139
|
+
|
|
140
|
+
# We don't have a current signing delegate assigned, lets see if we can assign one.
|
|
141
|
+
elif len(delegates := self.delegates(aid)) > 0:
|
|
142
|
+
if (
|
|
143
|
+
delegates
|
|
144
|
+
): # if we have defined delegates, assign the first one as our current signer
|
|
145
|
+
delegate = delegates[0]
|
|
146
|
+
if delegate in self.hby.habs:
|
|
147
|
+
self.rt.cur.pin(keys=(aid,), val=delegate)
|
|
148
|
+
return self.hby.habs[delegate]
|
|
149
|
+
|
|
150
|
+
elif aid in self.hby.habs:
|
|
151
|
+
return self.hby.habs[aid]
|
|
152
|
+
|
|
153
|
+
raise kering.ConfigurationError(f"Unable to find Hab for {aid}")
|
|
154
|
+
|
|
155
|
+
def kever(self, aid):
|
|
156
|
+
delegates = self.delegates(aid)
|
|
157
|
+
if delegates:
|
|
158
|
+
delegate = random.choice(delegates)
|
|
159
|
+
if delegate in self.hby.kevers:
|
|
160
|
+
return self.hby.kevers[delegate]
|
|
161
|
+
else:
|
|
162
|
+
raise kering.ConfigurationError(f"Unable to find kever for {aid}")
|
|
163
|
+
elif aid in self.hby.kevers:
|
|
164
|
+
return self.hby.kevers[aid]
|
|
165
|
+
else:
|
|
166
|
+
raise kering.ConfigurationError(f"Unable to find kever for {aid}")
|
|
167
|
+
|
|
168
|
+
def encode(self, path, payload, target=None, said=None):
|
|
169
|
+
hab = self.hab(self._hab.pre) # Signer is always hardcoded
|
|
170
|
+
|
|
171
|
+
payload = dict(i=hab.pre, **payload)
|
|
172
|
+
|
|
173
|
+
encryption_target = (
|
|
174
|
+
target if target is not None else self.encryption_target
|
|
175
|
+
) # Must extract the encryption
|
|
176
|
+
|
|
177
|
+
# target from the message context from DESSR or get is from self.encryption_target
|
|
178
|
+
if encryption_target is None:
|
|
179
|
+
raise ConfigurationError("Unable to determine encryption target")
|
|
180
|
+
|
|
181
|
+
rkever = self.kever(encryption_target)
|
|
182
|
+
if rkever is None:
|
|
183
|
+
raise ConfigurationError(
|
|
184
|
+
f"Unable to find kever for encryption target {encryption_target}"
|
|
185
|
+
)
|
|
186
|
+
|
|
187
|
+
# convert signing public key to encryption public key
|
|
188
|
+
pubkey = pysodium.crypto_sign_pk_to_box_pk(rkever.verfers[0].raw)
|
|
189
|
+
raw = pysodium.crypto_box_seal(cbor.dumps(payload), pubkey)
|
|
190
|
+
diger = coring.Diger(ser=raw, code=MtrDex.Blake3_256)
|
|
191
|
+
|
|
192
|
+
kwargs = dict()
|
|
193
|
+
if said is not None:
|
|
194
|
+
kwargs["dig"] = said
|
|
195
|
+
|
|
196
|
+
exn, _ = exchanging.exchange(
|
|
197
|
+
route=path, # The return_route of original message
|
|
198
|
+
diger=diger,
|
|
199
|
+
sender=hab.pre,
|
|
200
|
+
recipient=rkever.prefixer.qb64, # Must sign receiver
|
|
201
|
+
date=helping.nowIso8601(),
|
|
202
|
+
**kwargs,
|
|
203
|
+
)
|
|
204
|
+
|
|
205
|
+
ims = hab.endorse(serder=exn, pipelined=False)
|
|
206
|
+
|
|
207
|
+
size = len(raw)
|
|
208
|
+
chunks = math.ceil(size / CHUNK_SIZE)
|
|
209
|
+
ims.extend(
|
|
210
|
+
core.Counter(
|
|
211
|
+
code=CtrDex_1_0.ESSRPayloadGroup, count=chunks, gvrsn=kering.Vrsn_1_0
|
|
212
|
+
).qb64b
|
|
213
|
+
)
|
|
214
|
+
for idx in range(chunks):
|
|
215
|
+
start = idx * CHUNK_SIZE
|
|
216
|
+
end = start + CHUNK_SIZE
|
|
217
|
+
texter = coring.Matter(raw=raw[start:end], code=MtrDex.Bytes_L0)
|
|
218
|
+
ims.extend(texter.qb64b)
|
|
219
|
+
|
|
220
|
+
hab.psr.parseOne(ims=bytes(ims))
|
|
221
|
+
|
|
222
|
+
hab.db.essrs.rem(keys=(exn.said,))
|
|
223
|
+
hab.db.epath.rem(keys=(exn.said,))
|
|
224
|
+
self.rt.encs.add(keys=(hab.kever.serder.said,), val=exn.said)
|
|
225
|
+
|
|
226
|
+
return ims
|
|
227
|
+
|
|
228
|
+
def rotate_signer(self, aid):
|
|
229
|
+
delegates = self.delegates(aid)
|
|
230
|
+
if not delegates:
|
|
231
|
+
raise kering.ConfigurationError(f"No delegates assigned for {aid}")
|
|
232
|
+
|
|
233
|
+
if not (delegate := self.rt.cur.get(keys=(aid,))):
|
|
234
|
+
if (
|
|
235
|
+
delegates
|
|
236
|
+
): # if we have defined delegates, assign the first one as our current signer
|
|
237
|
+
delegate = delegates[0]
|
|
238
|
+
if delegate in self.hby.habs:
|
|
239
|
+
self.rt.cur.pin(keys=(aid,), val=delegate)
|
|
240
|
+
else:
|
|
241
|
+
try:
|
|
242
|
+
idx = delegates.index(delegate)
|
|
243
|
+
except ValueError:
|
|
244
|
+
delegate = delegates[0]
|
|
245
|
+
if delegate in self.hby.habs:
|
|
246
|
+
self.rt.cur.pin(keys=(aid,), val=delegate)
|
|
247
|
+
else:
|
|
248
|
+
idx = (idx + 1) % len(delegates)
|
|
249
|
+
delegate = delegates[idx]
|
|
250
|
+
if delegate in self.hby.habs:
|
|
251
|
+
self.rt.cur.pin(keys=(aid,), val=delegate)
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
def scan_for_delegates(hby, rt, delegator):
|
|
255
|
+
cloner = hby.db.clonePreIter(pre=delegator, fn=0) # create iterator at 0
|
|
256
|
+
rt.dlgs.rem(keys=(delegator,))
|
|
257
|
+
for msg in cloner:
|
|
258
|
+
srdr = serdering.SerderKERI(raw=msg)
|
|
259
|
+
process_delegator_event_seals(hby, rt, srdr)
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def process_delegator_event_seals(hby, rt, srdr):
|
|
263
|
+
delegator = srdr.pre
|
|
264
|
+
for anchor in srdr.seals:
|
|
265
|
+
if (
|
|
266
|
+
"i" not in anchor and "s" not in anchor and "d" not in anchor
|
|
267
|
+
): # Event seal anchor
|
|
268
|
+
continue
|
|
269
|
+
|
|
270
|
+
delegate = anchor["i"]
|
|
271
|
+
if (
|
|
272
|
+
anchor["s"] != "0" or delegate != anchor["d"]
|
|
273
|
+
): # Ensure this is an inception anchor
|
|
274
|
+
continue
|
|
275
|
+
|
|
276
|
+
delegate_kever = hby.kevers[delegate]
|
|
277
|
+
|
|
278
|
+
# Check for accidental registration of non-delegate or for a delegate that was neutered.
|
|
279
|
+
if delegate_kever.delpre != delegator or not delegate_kever.ndigers:
|
|
280
|
+
continue
|
|
281
|
+
|
|
282
|
+
rt.dlgs.add(keys=(delegator,), val=delegate)
|
|
283
|
+
|
|
284
|
+
logger.info(f"Signer {delegate} added for delegator {delegator}")
|
kept/core/exceptions.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
|
2
|
+
"""
|
|
3
|
+
KERI-ESSR
|
|
4
|
+
kept.essr.core.exceptions package
|
|
5
|
+
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class ESSRStatusError(Exception):
|
|
10
|
+
"""Raised when the ESSR server responds with an error status."""
|
|
11
|
+
|
|
12
|
+
def __init__(self, status_code: int, message: str):
|
|
13
|
+
self.status_code = status_code
|
|
14
|
+
self.message = message
|
|
File without changes
|