GitHub Action
commited on
Commit
·
ad45f9a
1
Parent(s):
a37a248
Sync from GitHub with Git LFS
Browse files- agents/bootstrap.txt +4 -4
- agents/examples/bootstrap.txt +4 -4
- agents/init.py +25 -20
- agents/peer_sync.py +7 -4
- agents/tools/db_structure.sql +1 -1
- agents/tools/storage.py +32 -16
agents/bootstrap.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
DID: "did:hmp:
|
2 |
-
DID: "did:hmp:
|
3 |
-
DID: "did:hmp:
|
4 |
-
DID: "did:hmp:
|
|
|
1 |
+
DID: "did:hmp:87836dac-a93c-4203-8710-5e4711b07e02"; NAME: "Agent_108"; KEY: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAzqHBnykJSRs6PsvpsEXdZNSPAs+voBarQYDAR0B664I=\n-----END PUBLIC KEY-----\n"; ADDRESS: [{"addr": "tcp://95.72.96.108:4000", "nonce": 67802, "pow_hash": "00002dbeb3936beffc746b25bdbeff0e20c7c164281f9ebe4d03e76a28592211", "difficulty": 4, "datetime": "2025-08-28T15:44:51.608882+00:00"}, {"addr": "udp://95.72.96.108:4000", "nonce": 8072, "pow_hash": "0000e54c7d2a5e0dabd811e1b1ac3f8ec94029b29382d8bf8a9fe3fc12985dc6", "difficulty": 4, "datetime": "2025-08-28T15:44:51.773206+00:00"}, {"addr": "tcp://195.172.229.108:4000", "nonce": 368, "pow_hash": "000089b642d389d1c5e36f93e0983158c676e2cae21b981fe978c8488ed679e0", "difficulty": 4, "datetime": "2025-08-28T15:44:51.790767+00:00"}, {"addr": "udp://195.172.229.108:4000", "nonce": 24998, "pow_hash": "00004791d6e3042a876d465e63b5d6104ded6e492cd23300b6455eeed2b36701", "difficulty": 4, "datetime": "2025-08-28T15:44:51.791505+00:00"}];
|
2 |
+
DID: "did:hmp:377e75d2-9eaf-4bfa-a02c-e9cc063b72d1"; NAME: "Agent_112"; KEY: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAuvk/l8iJIQ3DcFJg+Jn5SFg+9xc7VRZ7p5SwsKyIwt4=\n-----END PUBLIC KEY-----\n"; ADDRESS: [{"addr": "tcp://95.72.96.112:4000", "nonce": 11491, "pow_hash": "0000b2f6b325bdf17b0da5ba1a3e66ed7cd49ba45ba681477af11e89ccd01ca8", "difficulty": 4, "datetime": "2025-08-28T15:47:03.319703+00:00"}, {"addr": "udp://95.72.96.112:4000", "nonce": 18356, "pow_hash": "0000d2c1e2b48141a15bad3f2be0ad091972be28f8e4e4fba5004bbfbc12f1ef", "difficulty": 4, "datetime": "2025-08-28T15:47:03.362438+00:00"}, {"addr": "tcp://195.172.229.112:4000", "nonce": 171, "pow_hash": "0000c5b7b126e83b93d3e809b022d7bf38225766d194052d15f6a750c465b515", "difficulty": 4, "datetime": "2025-08-28T15:47:03.404411+00:00"}, {"addr": "udp://195.172.229.112:4000", "nonce": 48621, "pow_hash": "000007acb2d37c02f0e3f2ce9bb4c1fd29bbbd2953a3f3218ee1313a18e662d9", "difficulty": 4, "datetime": "2025-08-28T15:47:03.404820+00:00"}];
|
3 |
+
DID: "did:hmp:25e6c264-8e16-4bb7-8cce-5930f757df98"; NAME: "Agent_116"; KEY: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAFgW23nQgQ89si67ZcRbsoZXqSS2rrWFnMAYKib29orA=\n-----END PUBLIC KEY-----\n"; ADDRESS: [{"addr": "tcp://95.72.96.116:4000", "nonce": 19471, "pow_hash": "000049397d5e7f91f09d6aa3da1537fedb95a1ef3456006a739cb4e81d37ee20", "difficulty": 4, "datetime": "2025-08-28T15:48:44.898372+00:00"}, {"addr": "udp://95.72.96.116:4000", "nonce": 67946, "pow_hash": "00002fb896fe39cf18408c5d87ee83a5e8eb76326205e5254e862b70bd336864", "difficulty": 4, "datetime": "2025-08-28T15:48:44.945521+00:00"}, {"addr": "tcp://195.172.229.116:4000", "nonce": 106038, "pow_hash": "000032d57ddc691502e9aea72fc2f3fd9018d6c5127f6c971af6aae2d964d5e9", "difficulty": 4, "datetime": "2025-08-28T15:48:45.097886+00:00"}, {"addr": "udp://195.172.229.116:4000", "nonce": 20754, "pow_hash": "00008df5e84f7d98b3e756784cad7a6518d202273ac5b9fcc6918803da0a815e", "difficulty": 4, "datetime": "2025-08-28T15:48:45.374646+00:00"}];
|
4 |
+
DID: "did:hmp:3a30112e-6b14-4161-8ce9-189a6f4bdd1e"; NAME: "Agent_120"; KEY: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAPIYEVWz9lBfxBI1MCHMoyVqAJpWH5wwLjAAFKV7Q6UM=\n-----END PUBLIC KEY-----\n"; ADDRESS: [{"addr": "tcp://95.72.96.120:4000", "nonce": 48308, "pow_hash": "0000bbf1c4880c752362fe6100d1eddb98530e9b36f7dda366dfbd3e8860a680", "difficulty": 4, "datetime": "2025-08-28T15:50:17.822119+00:00"}, {"addr": "udp://95.72.96.120:4000", "nonce": 277204, "pow_hash": "0000e71c10d990fb4af04a3a171f9735291ab21a8807acf9284fc39817e028a3", "difficulty": 4, "datetime": "2025-08-28T15:50:17.935199+00:00"}, {"addr": "tcp://195.172.229.120:4000", "nonce": 74353, "pow_hash": "0000c16fcdbbc456b93680fdf48e3a844a477d038c362dd01d70219d566defb0", "difficulty": 4, "datetime": "2025-08-28T15:50:18.661732+00:00"}, {"addr": "udp://195.172.229.120:4000", "nonce": 9937, "pow_hash": "000019a037ff2c15c8b88e45d63152dee141a779628370692973626bf0c343f7", "difficulty": 4, "datetime": "2025-08-28T15:50:18.849814+00:00"}];
|
agents/examples/bootstrap.txt
CHANGED
@@ -1,4 +1,4 @@
|
|
1 |
-
DID: "did:hmp:
|
2 |
-
DID: "did:hmp:
|
3 |
-
DID: "did:hmp:
|
4 |
-
DID: "did:hmp:
|
|
|
1 |
+
DID: "did:hmp:87836dac-a93c-4203-8710-5e4711b07e02"; NAME: "Agent_108"; KEY: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAzqHBnykJSRs6PsvpsEXdZNSPAs+voBarQYDAR0B664I=\n-----END PUBLIC KEY-----\n"; ADDRESS: [{"addr": "tcp://95.72.96.108:4000", "nonce": 67802, "pow_hash": "00002dbeb3936beffc746b25bdbeff0e20c7c164281f9ebe4d03e76a28592211", "difficulty": 4, "datetime": "2025-08-28T15:44:51.608882+00:00"}, {"addr": "udp://95.72.96.108:4000", "nonce": 8072, "pow_hash": "0000e54c7d2a5e0dabd811e1b1ac3f8ec94029b29382d8bf8a9fe3fc12985dc6", "difficulty": 4, "datetime": "2025-08-28T15:44:51.773206+00:00"}, {"addr": "tcp://195.172.229.108:4000", "nonce": 368, "pow_hash": "000089b642d389d1c5e36f93e0983158c676e2cae21b981fe978c8488ed679e0", "difficulty": 4, "datetime": "2025-08-28T15:44:51.790767+00:00"}, {"addr": "udp://195.172.229.108:4000", "nonce": 24998, "pow_hash": "00004791d6e3042a876d465e63b5d6104ded6e492cd23300b6455eeed2b36701", "difficulty": 4, "datetime": "2025-08-28T15:44:51.791505+00:00"}];
|
2 |
+
DID: "did:hmp:377e75d2-9eaf-4bfa-a02c-e9cc063b72d1"; NAME: "Agent_112"; KEY: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAuvk/l8iJIQ3DcFJg+Jn5SFg+9xc7VRZ7p5SwsKyIwt4=\n-----END PUBLIC KEY-----\n"; ADDRESS: [{"addr": "tcp://95.72.96.112:4000", "nonce": 11491, "pow_hash": "0000b2f6b325bdf17b0da5ba1a3e66ed7cd49ba45ba681477af11e89ccd01ca8", "difficulty": 4, "datetime": "2025-08-28T15:47:03.319703+00:00"}, {"addr": "udp://95.72.96.112:4000", "nonce": 18356, "pow_hash": "0000d2c1e2b48141a15bad3f2be0ad091972be28f8e4e4fba5004bbfbc12f1ef", "difficulty": 4, "datetime": "2025-08-28T15:47:03.362438+00:00"}, {"addr": "tcp://195.172.229.112:4000", "nonce": 171, "pow_hash": "0000c5b7b126e83b93d3e809b022d7bf38225766d194052d15f6a750c465b515", "difficulty": 4, "datetime": "2025-08-28T15:47:03.404411+00:00"}, {"addr": "udp://195.172.229.112:4000", "nonce": 48621, "pow_hash": "000007acb2d37c02f0e3f2ce9bb4c1fd29bbbd2953a3f3218ee1313a18e662d9", "difficulty": 4, "datetime": "2025-08-28T15:47:03.404820+00:00"}];
|
3 |
+
DID: "did:hmp:25e6c264-8e16-4bb7-8cce-5930f757df98"; NAME: "Agent_116"; KEY: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAFgW23nQgQ89si67ZcRbsoZXqSS2rrWFnMAYKib29orA=\n-----END PUBLIC KEY-----\n"; ADDRESS: [{"addr": "tcp://95.72.96.116:4000", "nonce": 19471, "pow_hash": "000049397d5e7f91f09d6aa3da1537fedb95a1ef3456006a739cb4e81d37ee20", "difficulty": 4, "datetime": "2025-08-28T15:48:44.898372+00:00"}, {"addr": "udp://95.72.96.116:4000", "nonce": 67946, "pow_hash": "00002fb896fe39cf18408c5d87ee83a5e8eb76326205e5254e862b70bd336864", "difficulty": 4, "datetime": "2025-08-28T15:48:44.945521+00:00"}, {"addr": "tcp://195.172.229.116:4000", "nonce": 106038, "pow_hash": "000032d57ddc691502e9aea72fc2f3fd9018d6c5127f6c971af6aae2d964d5e9", "difficulty": 4, "datetime": "2025-08-28T15:48:45.097886+00:00"}, {"addr": "udp://195.172.229.116:4000", "nonce": 20754, "pow_hash": "00008df5e84f7d98b3e756784cad7a6518d202273ac5b9fcc6918803da0a815e", "difficulty": 4, "datetime": "2025-08-28T15:48:45.374646+00:00"}];
|
4 |
+
DID: "did:hmp:3a30112e-6b14-4161-8ce9-189a6f4bdd1e"; NAME: "Agent_120"; KEY: "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAPIYEVWz9lBfxBI1MCHMoyVqAJpWH5wwLjAAFKV7Q6UM=\n-----END PUBLIC KEY-----\n"; ADDRESS: [{"addr": "tcp://95.72.96.120:4000", "nonce": 48308, "pow_hash": "0000bbf1c4880c752362fe6100d1eddb98530e9b36f7dda366dfbd3e8860a680", "difficulty": 4, "datetime": "2025-08-28T15:50:17.822119+00:00"}, {"addr": "udp://95.72.96.120:4000", "nonce": 277204, "pow_hash": "0000e71c10d990fb4af04a3a171f9735291ab21a8807acf9284fc39817e028a3", "difficulty": 4, "datetime": "2025-08-28T15:50:17.935199+00:00"}, {"addr": "tcp://195.172.229.120:4000", "nonce": 74353, "pow_hash": "0000c16fcdbbc456b93680fdf48e3a844a477d038c362dd01d70219d566defb0", "difficulty": 4, "datetime": "2025-08-28T15:50:18.661732+00:00"}, {"addr": "udp://195.172.229.120:4000", "nonce": 9937, "pow_hash": "000019a037ff2c15c8b88e45d63152dee141a779628370692973626bf0c343f7", "difficulty": 4, "datetime": "2025-08-28T15:50:18.849814+00:00"}];
|
agents/init.py
CHANGED
@@ -132,6 +132,17 @@ def init_config_table(storage, config):
|
|
132 |
print("[+] Конфигурация сохранена в БД.")
|
133 |
|
134 |
def update_pow_for_addresses(storage, difficulty=4):
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
135 |
raw_id = storage.get_config_value("agent_id")
|
136 |
if not raw_id:
|
137 |
print("[-] Нет agent_id в config — пропуск обновления PoW.")
|
@@ -160,41 +171,35 @@ def update_pow_for_addresses(storage, difficulty=4):
|
|
160 |
|
161 |
enriched = []
|
162 |
for addr in addresses:
|
163 |
-
|
|
|
|
|
164 |
# уже в новом формате → оставляем как есть
|
165 |
-
|
166 |
-
|
167 |
-
continue
|
168 |
-
# старый формат с "address"/"pow" → конвертим
|
169 |
-
if "address" in addr and "pow" in addr:
|
170 |
-
enriched.append({
|
171 |
-
"addr": addr["address"],
|
172 |
-
"nonce": addr["pow"].get("nonce"),
|
173 |
-
"pow_hash": addr["pow"].get("hash"),
|
174 |
-
"difficulty": addr["pow"].get("difficulty", difficulty),
|
175 |
-
"expires": addr.get("expires", "")
|
176 |
-
})
|
177 |
-
continue
|
178 |
|
179 |
# строка → нужно сгенерировать PoW
|
180 |
-
if isinstance(addr, str)
|
181 |
-
|
|
|
|
|
182 |
peer_id=agent_id,
|
183 |
pubkey=pubkey,
|
184 |
-
address=
|
|
|
185 |
difficulty=difficulty
|
186 |
)
|
187 |
enriched.append({
|
188 |
-
"addr":
|
189 |
"nonce": nonce,
|
190 |
"pow_hash": hash_value,
|
191 |
"difficulty": difficulty,
|
192 |
-
"
|
193 |
})
|
194 |
|
195 |
storage.set_config(addr_key, json.dumps(enriched))
|
196 |
|
197 |
-
print("[+] Адреса обновлены с PoW в
|
198 |
|
199 |
def init_prompts_and_ethics():
|
200 |
folder = os.path.dirname(__file__)
|
|
|
132 |
print("[+] Конфигурация сохранена в БД.")
|
133 |
|
134 |
def update_pow_for_addresses(storage, difficulty=4):
|
135 |
+
"""
|
136 |
+
Обновляет PoW для всех локальных и глобальных адресов агента.
|
137 |
+
Используется новый формат:
|
138 |
+
{
|
139 |
+
"addr": "tcp://95.69.92.23:8010",
|
140 |
+
"nonce": 108834,
|
141 |
+
"pow_hash": "0000665ea1440781356d7a9b899fc03a01a4f8342d3cfa3d75bb2619b66b4cfb",
|
142 |
+
"difficulty": 4,
|
143 |
+
"datetime": "2025-08-28T11:00:00+03:00"
|
144 |
+
}
|
145 |
+
"""
|
146 |
raw_id = storage.get_config_value("agent_id")
|
147 |
if not raw_id:
|
148 |
print("[-] Нет agent_id в config — пропуск обновления PoW.")
|
|
|
171 |
|
172 |
enriched = []
|
173 |
for addr in addresses:
|
174 |
+
dt_now = datetime.now(UTC).isoformat()
|
175 |
+
|
176 |
+
if isinstance(addr, dict) and "addr" in addr and "pow_hash" in addr:
|
177 |
# уже в новом формате → оставляем как есть
|
178 |
+
enriched.append(addr)
|
179 |
+
continue
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
180 |
|
181 |
# строка → нужно сгенерировать PoW
|
182 |
+
addr_str = addr if isinstance(addr, str) else addr.get("address")
|
183 |
+
dt_now = datetime.now(UTC).isoformat()
|
184 |
+
if addr_str:
|
185 |
+
nonce, hash_value, dt_now = storage.generate_pow(
|
186 |
peer_id=agent_id,
|
187 |
pubkey=pubkey,
|
188 |
+
address=addr_str,
|
189 |
+
dt=dt_now,
|
190 |
difficulty=difficulty
|
191 |
)
|
192 |
enriched.append({
|
193 |
+
"addr": addr_str,
|
194 |
"nonce": nonce,
|
195 |
"pow_hash": hash_value,
|
196 |
"difficulty": difficulty,
|
197 |
+
"datetime": dt_now
|
198 |
})
|
199 |
|
200 |
storage.set_config(addr_key, json.dumps(enriched))
|
201 |
|
202 |
+
print("[+] Адреса обновлены с PoW в новом формате с datetime.")
|
203 |
|
204 |
def init_prompts_and_ethics():
|
205 |
folder = os.path.dirname(__file__)
|
agents/peer_sync.py
CHANGED
@@ -91,7 +91,7 @@ def load_bootstrap_peers(filename="bootstrap.txt"):
|
|
91 |
"nonce": addr.get("pow", {}).get("nonce"),
|
92 |
"pow_hash": addr.get("pow", {}).get("hash"),
|
93 |
"difficulty": addr.get("pow", {}).get("difficulty"),
|
94 |
-
"
|
95 |
})
|
96 |
# уже новый формат → оставляем как есть
|
97 |
elif "addr" in addr:
|
@@ -101,8 +101,8 @@ def load_bootstrap_peers(filename="bootstrap.txt"):
|
|
101 |
if addr.startswith("any://"):
|
102 |
hostport = addr[len("any://"):]
|
103 |
expanded_addresses.extend([
|
104 |
-
{"addr": f"tcp://{hostport}", "nonce": None, "pow_hash": None, "difficulty": None, "
|
105 |
-
{"addr": f"udp://{hostport}", "nonce": None, "pow_hash": None, "difficulty": None, "
|
106 |
])
|
107 |
else:
|
108 |
expanded_addresses.append({
|
@@ -110,10 +110,13 @@ def load_bootstrap_peers(filename="bootstrap.txt"):
|
|
110 |
"nonce": None,
|
111 |
"pow_hash": None,
|
112 |
"difficulty": None,
|
113 |
-
"
|
114 |
})
|
115 |
|
116 |
# Сохраняем в storage
|
|
|
|
|
|
|
117 |
storage.add_or_update_peer(
|
118 |
peer_id=did,
|
119 |
name=name,
|
|
|
91 |
"nonce": addr.get("pow", {}).get("nonce"),
|
92 |
"pow_hash": addr.get("pow", {}).get("hash"),
|
93 |
"difficulty": addr.get("pow", {}).get("difficulty"),
|
94 |
+
"datetime": addr.get("datetime", "")
|
95 |
})
|
96 |
# уже новый формат → оставляем как есть
|
97 |
elif "addr" in addr:
|
|
|
101 |
if addr.startswith("any://"):
|
102 |
hostport = addr[len("any://"):]
|
103 |
expanded_addresses.extend([
|
104 |
+
{"addr": f"tcp://{hostport}", "nonce": None, "pow_hash": None, "difficulty": None, "datetime": ""},
|
105 |
+
{"addr": f"udp://{hostport}", "nonce": None, "pow_hash": None, "difficulty": None, "datetime": ""}
|
106 |
])
|
107 |
else:
|
108 |
expanded_addresses.append({
|
|
|
110 |
"nonce": None,
|
111 |
"pow_hash": None,
|
112 |
"difficulty": None,
|
113 |
+
"datetime": ""
|
114 |
})
|
115 |
|
116 |
# Сохраняем в storage
|
117 |
+
print(f"[DEBUG] Saving peer {did} with addresses:")
|
118 |
+
for a in expanded_addresses:
|
119 |
+
print(a)
|
120 |
storage.add_or_update_peer(
|
121 |
peer_id=did,
|
122 |
name=name,
|
agents/tools/db_structure.sql
CHANGED
@@ -151,7 +151,7 @@ CREATE TABLE IF NOT EXISTS llm_recent_responses (
|
|
151 |
CREATE TABLE IF NOT EXISTS agent_peers (
|
152 |
id TEXT PRIMARY KEY, -- Уникальный идентификатор (UUID или псевдоним)
|
153 |
name TEXT, -- Имя агента
|
154 |
-
addresses TEXT, -- Адреса для связи (JSON), каждый адрес содержит addr, nonce, pow_hash,
|
155 |
tags TEXT, -- Теги (Postman, Friend и т.д.)
|
156 |
status TEXT DEFAULT 'unknown', -- online | offline | untrusted | blacklisted и др.
|
157 |
source TEXT, -- bootstrap | discovery | exchange
|
|
|
151 |
CREATE TABLE IF NOT EXISTS agent_peers (
|
152 |
id TEXT PRIMARY KEY, -- Уникальный идентификатор (UUID или псевдоним)
|
153 |
name TEXT, -- Имя агента
|
154 |
+
addresses TEXT, -- Адреса для связи (JSON), каждый адрес содержит addr, nonce, pow_hash, datatime
|
155 |
tags TEXT, -- Теги (Postman, Friend и т.д.)
|
156 |
status TEXT DEFAULT 'unknown', -- online | offline | untrusted | blacklisted и др.
|
157 |
source TEXT, -- bootstrap | discovery | exchange
|
agents/tools/storage.py
CHANGED
@@ -677,18 +677,20 @@ class Storage:
|
|
677 |
self.conn.commit()
|
678 |
return cursor.lastrowid
|
679 |
|
680 |
-
def generate_pow(self, peer_id, pubkey, address,
|
681 |
"""
|
682 |
-
Генерирует PoW для
|
683 |
"""
|
|
|
|
|
|
|
684 |
nonce = 0
|
685 |
prefix = "0" * difficulty
|
686 |
-
expires_str = str(expires) if expires is not None else ""
|
687 |
while True:
|
688 |
-
base = f"{peer_id}{pubkey}{address}{
|
689 |
h = hashlib.sha256(base).hexdigest()
|
690 |
if h.startswith(prefix):
|
691 |
-
return nonce, h
|
692 |
nonce += 1
|
693 |
|
694 |
# Управление основными процессами
|
@@ -971,7 +973,7 @@ class Storage:
|
|
971 |
def get_local_ports(self):
|
972 |
"""
|
973 |
Возвращает список портов для всех локальных адресов.
|
974 |
-
Формат конфигурации: список dict {"address": str, "pow": {...}, "
|
975 |
"""
|
976 |
local_addrs_json = self.get_config_value("local_addresses")
|
977 |
if not local_addrs_json:
|
@@ -1003,12 +1005,11 @@ class Storage:
|
|
1003 |
|
1004 |
# Работа с пирам (agent_peers)
|
1005 |
@staticmethod
|
1006 |
-
def verify_pow(peer_id, pubkey, address, nonce, pow_hash,
|
1007 |
"""
|
1008 |
-
Проверяет PoW
|
1009 |
"""
|
1010 |
-
|
1011 |
-
base = f"{peer_id}{pubkey}{address}{expires_str}{nonce}".encode()
|
1012 |
h = hashlib.sha256(base).hexdigest()
|
1013 |
return h == pow_hash and h.startswith("0" * difficulty)
|
1014 |
|
@@ -1024,14 +1025,20 @@ class Storage:
|
|
1024 |
norm_addresses = []
|
1025 |
for a in (addresses or []):
|
1026 |
if isinstance(a, dict) and "addr" in a:
|
|
|
1027 |
norm_addresses.append({
|
1028 |
"addr": self.normalize_address(a["addr"]),
|
1029 |
"nonce": a.get("nonce"),
|
1030 |
"pow_hash": a.get("pow_hash"),
|
1031 |
-
"
|
1032 |
})
|
1033 |
elif isinstance(a, str):
|
1034 |
-
norm_addresses.append({
|
|
|
|
|
|
|
|
|
|
|
1035 |
|
1036 |
# получаем существующую запись
|
1037 |
existing_addresses = []
|
@@ -1066,19 +1073,28 @@ class Storage:
|
|
1066 |
return
|
1067 |
final_pubkey = existing_pubkey or pubkey
|
1068 |
|
1069 |
-
# Объединяем адреса по addr, проверяем PoW
|
1070 |
addr_map = {a["addr"]: a for a in existing_addresses if isinstance(a, dict)}
|
1071 |
for a in norm_addresses:
|
1072 |
addr = a["addr"]
|
1073 |
nonce = a.get("nonce")
|
1074 |
pow_hash = a.get("pow_hash")
|
1075 |
-
|
|
|
1076 |
# проверка PoW
|
1077 |
if nonce is not None and pow_hash is not None:
|
1078 |
-
if not self.verify_pow(peer_id, final_pubkey, addr, nonce, pow_hash,
|
1079 |
print(f"[WARN] Peer {peer_id} address {addr} failed PoW validation")
|
1080 |
continue
|
1081 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1082 |
|
1083 |
combined_addresses = list(addr_map.values())
|
1084 |
|
|
|
677 |
self.conn.commit()
|
678 |
return cursor.lastrowid
|
679 |
|
680 |
+
def generate_pow(self, peer_id, pubkey, address, dt=None, difficulty=4):
|
681 |
"""
|
682 |
+
Генерирует PoW для (peer_id + pubkey + address + datetime).
|
683 |
"""
|
684 |
+
if dt is None:
|
685 |
+
dt = datetime.now(UTC).isoformat()
|
686 |
+
|
687 |
nonce = 0
|
688 |
prefix = "0" * difficulty
|
|
|
689 |
while True:
|
690 |
+
base = f"{peer_id}{pubkey}{address}{dt}{nonce}".encode()
|
691 |
h = hashlib.sha256(base).hexdigest()
|
692 |
if h.startswith(prefix):
|
693 |
+
return nonce, h, dt
|
694 |
nonce += 1
|
695 |
|
696 |
# Управление основными процессами
|
|
|
973 |
def get_local_ports(self):
|
974 |
"""
|
975 |
Возвращает список портов для всех локальных адресов.
|
976 |
+
Формат конфигурации: список dict {"address": str, "pow": {...}, "datetime": str, "difficulty": int}
|
977 |
"""
|
978 |
local_addrs_json = self.get_config_value("local_addresses")
|
979 |
if not local_addrs_json:
|
|
|
1005 |
|
1006 |
# Работа с пирам (agent_peers)
|
1007 |
@staticmethod
|
1008 |
+
def verify_pow(peer_id, pubkey, address, nonce, pow_hash, dt, difficulty=4):
|
1009 |
"""
|
1010 |
+
Проверяет PoW (peer_id + pubkey + address + datetime).
|
1011 |
"""
|
1012 |
+
base = f"{peer_id}{pubkey}{address}{dt}{nonce}".encode()
|
|
|
1013 |
h = hashlib.sha256(base).hexdigest()
|
1014 |
return h == pow_hash and h.startswith("0" * difficulty)
|
1015 |
|
|
|
1025 |
norm_addresses = []
|
1026 |
for a in (addresses or []):
|
1027 |
if isinstance(a, dict) and "addr" in a:
|
1028 |
+
dt = a.get("datetime") or datetime.now(UTC).isoformat()
|
1029 |
norm_addresses.append({
|
1030 |
"addr": self.normalize_address(a["addr"]),
|
1031 |
"nonce": a.get("nonce"),
|
1032 |
"pow_hash": a.get("pow_hash"),
|
1033 |
+
"datetime": dt
|
1034 |
})
|
1035 |
elif isinstance(a, str):
|
1036 |
+
norm_addresses.append({
|
1037 |
+
"addr": self.normalize_address(a),
|
1038 |
+
"nonce": None,
|
1039 |
+
"pow_hash": None,
|
1040 |
+
"datetime": datetime.now(UTC).isoformat()
|
1041 |
+
})
|
1042 |
|
1043 |
# получаем существующую запись
|
1044 |
existing_addresses = []
|
|
|
1073 |
return
|
1074 |
final_pubkey = existing_pubkey or pubkey
|
1075 |
|
1076 |
+
# Объединяем адреса по addr, проверяем PoW и актуальность
|
1077 |
addr_map = {a["addr"]: a for a in existing_addresses if isinstance(a, dict)}
|
1078 |
for a in norm_addresses:
|
1079 |
addr = a["addr"]
|
1080 |
nonce = a.get("nonce")
|
1081 |
pow_hash = a.get("pow_hash")
|
1082 |
+
dt = a.get("datetime")
|
1083 |
+
|
1084 |
# проверка PoW
|
1085 |
if nonce is not None and pow_hash is not None:
|
1086 |
+
if not self.verify_pow(peer_id, final_pubkey, addr, nonce, pow_hash, dt):
|
1087 |
print(f"[WARN] Peer {peer_id} address {addr} failed PoW validation")
|
1088 |
continue
|
1089 |
+
|
1090 |
+
# проверка актуальности по datetime
|
1091 |
+
if addr in addr_map:
|
1092 |
+
old_dt = addr_map[addr].get("datetime")
|
1093 |
+
if old_dt and dt <= old_dt:
|
1094 |
+
continue # оставляем более свежий адрес
|
1095 |
+
|
1096 |
+
# обновляем запись
|
1097 |
+
addr_map[addr] = {"addr": addr, "nonce": nonce, "pow_hash": pow_hash, "datetime": dt}
|
1098 |
|
1099 |
combined_addresses = list(addr_map.values())
|
1100 |
|