File size: 7,540 Bytes
6c36acc 163043c 6c36acc 163043c 05cbd4d 1c5b1af 05cbd4d 163043c 666a7de d88f510 05cbd4d 163043c 666a7de 163043c 666a7de 163043c 666a7de d88f510 05cbd4d 163043c 666a7de 163043c 666a7de d88f510 05cbd4d 163043c 666a7de 163043c 666a7de 05cbd4d 666a7de 163043c 666a7de 163043c 05cbd4d 163043c 6c36acc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# DHT Protocol Specification
## 1. Общие положения
* DHT-протокол предназначен для обмена информацией о пирах между агентами.
* Используется **DID** (Decentralized Identifier) как уникальный идентификатор агента.
* Для проверки подлинности применяется криптоподпись (публичный/приватный ключ).
* Для защиты от спама/флуда используется **Proof-of-Work (PoW)**.
* Каждый агент может иметь несколько сетевых интерфейсов (адресов).
* У агента может быть только **одна устойчивая пара DID + pubkey**.
---
## 2. Интерфейсы
Формат интерфейса:
```json
{
"addr": "tcp://1.2.3.4:4000",
"nonce": 123456,
"pow_hash": "abcd1234...",
"difficulty": 22,
"datetime": "2025-09-14T21:00:00Z",
"type": "internet"
}
```
### Поддерживаемые протоколы
* `tcp://`
* `udp://`
### Поле `type` (опционально)
* `localhost` — адреса локальной машины.
* `lan:[маска_подсети]` — локальная сеть, пример: `lan:192.168.10.0`.
(Один агент может иметь несколько сетевых интерфейсов и, соответственно, несколько LAN-сегментов.)
* `internet` — обычное TCP/UDP-подключение через глобальную сеть.
* `yggdrasil` — узел доступен через Yggdrasil overlay.
* `i2p` — узел доступен через I2P.
### Правила
* Если `port = 0` → интерфейс считается **отключённым**.
* Корректный интерфейс с более новой датой заменяет аналогичный старый (после проверки PoW).
* При обмене рекомендуется **не передавать локальные интерфейсы** в Интернет (исключение: Yggdrasil и I2P).
---
## 3. Proof-of-Work (PoW)
* Каждый интерфейс сопровождается PoW.
* Сложность PoW должна быть выбрана так, чтобы генерация занимала **несколько минут** (операция нечастая).
* Поля:
* `nonce` — число, подобранное агентом.
* `pow_hash` — хэш значения (`DID + addr + datetime + nonce`).
* `difficulty` — число ведущих нулей (или иное условие).
---
## 3.1 Формализация PoW и подписи
### Канонический вход для PoW
```
pow_input_string = DID + " -- " + addr + " -- " + datetime + " -- " + nonce_string
```
* Все строки кодируются в UTF-8.
* Хеш: `pow_hash = sha256(pow_input_string_bytes)`, hex lower-case (64 символа).
* `difficulty` = число ведущих нулевых hex-символов.
### Подпись сообщения
* Подписывается всё сообщение (JSON), кроме поля `signature`.
* Сериализация: JSON с отсортированными ключами, без пробелов:
```python
serialized = json.dumps(obj, separators=(",", ":"), sort_keys=True, ensure_ascii=False).encode("utf-8")
```
* Алгоритм: **Ed25519** (рекомендуется).
* Подпись хранится в поле:
```json
"signature": "BASE64URL(...)",
"sig_algo": "ed25519"
```
### Верификация
1. Проверить подпись сообщения по `pubkey`.
2. Для каждого `address` вычислить PoW и проверить `difficulty`.
3. Некорректные адреса игнорировать, сообщение в целом может оставаться валидным.
---
## 4. Сообщения
### 4.1 DISCOVERY
Используется для объявления себя в локальной сети.
```json
{
"type": "DISCOVERY",
"id": "did:example:123",
"name": "Agent_X",
"pubkey": "base58...",
"addresses": [
{
"addr": "tcp://1.2.3.4:4000",
"nonce": 123456,
"pow_hash": "0000abf39d...",
"difficulty": 22,
"datetime": "2025-09-14T21:00:00Z",
"type": "internet"
}
],
"signature": "BASE64URL(...)",
"sig_algo": "ed25519"
}
````
---
### 4.2 PEER\_EXCHANGE\_REQUEST / RESPONSE
Запрос известных пиров:
```json
{
"type": "PEER_EXCHANGE_REQUEST",
"id": "did:example:123",
"name": "Agent_X",
"addresses": [
{
"addr": "udp://1.2.3.4:4010",
"nonce": 987654,
"pow_hash": "0000123def...",
"difficulty": 22,
"datetime": "2025-09-14T21:05:00Z",
"type": "lan:192.168.1.0"
}
],
"signature": "BASE64URL(...)",
"sig_algo": "ed25519"
}
```
Ответ содержит список пиров (каждый с DID, pubkey и адресами, у которых тоже должен быть валидный PoW):
```json
[
{
"id": "did:example:456",
"name": "Agent_Y",
"pubkey": "base58...",
"addresses": [
{
"addr": "tcp://5.6.7.8:4020",
"nonce": 22222,
"pow_hash": "0000a1b2c3...",
"difficulty": 22,
"datetime": "2025-09-14T21:10:00Z",
"type": "internet"
}
],
"signature": "BASE64URL(...)",
"sig_algo": "ed25519"
}
]
```
---
## 5. Правила валидации адресов и пиров
* Каждый `address` в DISCOVERY и PEER_EXCHANGE должен содержать валидный PoW:
* `pow_hash = sha256(DID + " -- " + addr + " -- " + datetime + " -- " + nonce_string)`
* `difficulty` соответствует локальной политике (например, 22 ведущих нуля).
* Если PoW некорректен → адрес игнорируется.
* `datetime` фиксируется при генерации PoW и не должен изменяться.
* Если приходит новый адрес с той же парой `(DID + addr)` и более свежим `datetime` → он заменяет старый.
* **Разные pubkey для одного DID** → принимается **первый**, остальные игнорируются.
* **Адрес подписан чужим ключом** → запись отклоняется.
* **Несколько интерфейсов** → сохраняются все, кроме явных дубликатов.
> Примечание: строка `DID + " -- " + addr + " -- " + datetime + " -- " + nonce_string` всегда кодируется в UTF-8,
> а `nonce_string` преобразуется к десятичной строке перед конкатенацией.
---
## 6. Безопасность
* Для всех сообщений требуется **подпись отправителя** (в будущем: обязательная проверка).
* Сообщения без подписи или с невалидным PoW могут игнорироваться.
* В перспективе можно добавить шифрование трафика (например, на уровне TCP/TLS или QUIC).
|