# Octava Transparent Stratum: журнал rejected shares

**Версия формата:** `1`. **Первая версия:** `0.1.0~dev21`.

Журнал предназначен для проверки rejected shares реальными майнерами. Он
пассивно разбирает копию уже переданных сообщений Stratum V1 и не меняет,
не задерживает и не блокирует mining traffic. Stratum V2 и любой непрозрачный
поток продолжают передаваться byte-identical, но share verdict для них в этом
журнале недоступен.

## Где находится журнал

DEB/systemd пишет JSON Lines в journal службы:

```bash
sudo journalctl -u octava-transparent-stratum -o cat
```

Docker пишет те же JSON Lines в stdout контейнера:

```bash
sudo docker logs octava-transparent-stratum
```

Срок хранения задаётся journald или Docker logging driver. Прокси не создаёт
отдельную неограниченную копию журнала на диске.

## Событие rejected share

На каждый отрицательный ответ пула создаётся одна строка:

```json
{"schema":1,"event":"stratum_share_rejected","at":"2026-10-09T12:00:00.123456789Z","algorithm":"sha256d","session_id":42,"session_started_at":"2026-10-09T11:55:00Z","session_duration_ms":300123,"source":"198.51.100.8","worker_key":"worker:0123456789abcdef","worker_confirmed":true,"endpoint_host":"gate1ssl.octava.online","endpoint_port":3050,"request_id_hash":"sha256:0123456789abcdef","job_id_hash":"sha256:fedcba9876543210","difficulty":262144,"response_latency_ms":18,"reason":"stale","provider_code":"20","submitted":101,"accepted":98,"rejected":3,"pending":0,"telemetry_dropped_chunks":0}
```

Пример сокращён для чтения: реальные SHA-256 значения имеют полную длину.

| Поле | Значение |
|---|---|
| `schema` | Версия формата, сейчас `1` |
| `event` | `stratum_share_rejected` |
| `at` | Время получения ответа пула, UTC |
| `algorithm` | `sha256d` или `scrypt` |
| `session_id` | Номер relay-сессии внутри текущего процесса |
| `session_started_at`, `session_duration_ms` | Начало и возраст сессии |
| `source` | IPv4 источника miner |
| `worker_key` | SHA-256 correlation key; исходное имя worker не пишется |
| `worker_confirmed` | Worker был подтверждён положительным `mining.authorize` |
| `endpoint_host`, `endpoint_port` | Endpoint, давший отрицательный ответ |
| `request_id_hash`, `job_id_hash` | SHA-256 непрозрачных ID без исходных значений |
| `difficulty` | Difficulty, назначенная job на момент submit; `0` означает, что parser её не установил |
| `response_latency_ms` | Время от наблюдаемого submit до ответа пула |
| `reason` | Нормализованный класс причины |
| `provider_code` | Числовой или короткий строковый код пула без raw message |
| `submitted`, `accepted`, `rejected`, `pending` | Накопительные счётчики этой сессии на момент reject |
| `telemetry_dropped_chunks` | Общий счётчик пропущенных telemetry chunks данного listener |

Нормализованные причины:

- `stale`;
- `unknown_job`;
- `low_difficulty`;
- `duplicate`;
- `unauthorized`;
- `rejected` — другой или неизвестный ответ пула.

## Итог сессии

При закрытии V1-сессии, в которой наблюдался хотя бы один submit, записывается:

```json
{"schema":1,"event":"stratum_session_share_summary","at":"2026-10-09T12:05:00Z","algorithm":"sha256d","session_id":42,"session_started_at":"2026-10-09T11:55:00Z","session_duration_ms":600000,"source":"198.51.100.8","worker_key":"worker:0123456789abcdef","worker_confirmed":true,"endpoint_host":"gate1ssl.octava.online","endpoint_port":3050,"submitted":200,"accepted":196,"rejected":4,"pending":0,"close_reason":"peer_closed","telemetry_dropped_chunks":0}
```

`close_reason` принимает `peer_closed`, `context_cancelled` или `io_error`.
По summary рассчитывается точный процент для наблюдавшихся ответов:
`rejected / (accepted + rejected) × 100%`. `pending > 0` означает, что сессия
закрылась до получения части ответов.

## Быстрая выборка

Показать rejects DEB-установки за последний час:

```bash
sudo journalctl -u octava-transparent-stratum --since '1 hour ago' -o cat \
  | jq -Rc 'fromjson? | select(.event == "stratum_share_rejected")'
```

Показать только session summary:

```bash
sudo journalctl -u octava-transparent-stratum --since today -o cat \
  | jq -Rc 'fromjson? | select(.event == "stratum_session_share_summary")'
```

Сгруппировать причины:

```bash
sudo journalctl -u octava-transparent-stratum --since today -o cat \
  | jq -Rsc '[split("\n")[] | fromjson? | select(.event == "stratum_share_rejected")] | group_by(.reason) | map({reason: .[0].reason, count: length})'
```

Для Docker замените источник строк:

```bash
sudo docker logs --since 1h octava-transparent-stratum 2>&1 \
  | jq -Rc 'fromjson? | select(.event == "stratum_share_rejected")'
```

## Какие выводы доступны

Из журнала можно определить:

- reject ratio каждой завершённой V1-сессии;
- алгоритм, worker correlation key и endpoint с rejects;
- распределение `stale`, `unknown_job`, `low_difficulty`, `duplicate` и
  `unauthorized`;
- задержку ответа пула и возраст сессии;
- повтор rejects для одного job hash без раскрытия job ID;
- связь rejects с reconnect, endpoint migration и причиной закрытия сессии;
- неполноту наблюдения по `pending` и `telemetry_dropped_chunks`.

Журнал намеренно не содержит Web-пароль, pool password, исходное имя worker,
raw request/job ID, nonce, share payload или полный текст ошибки пула. Он не
доказывает локальную PoW-корректность и не создаёт verdict для непрозрачного V2.
