Define variable stream parts with a signed RS batch envelope

This commit is contained in:
evgeny committed 2026-10-13 20:03:08 +02:00
1 parent 3477a8844c
commit 7c8470f44a
3 files changed
+100 -37

No files matched your search

+23 -11
View File
@@ -1,7 +1,8 @@
/* Формирование и проверка подписанных FEC-блоков без сокетов и внешних callbacks.
/* Одна Ed25519-подпись пачки до RS, части переменного размера без отдельных подписей.
* Контексты одного uasync-потока; descriptor и ключ источника уже проверены членством группы.
* encode возвращает заимствованные блоки до следующего encode/destroy; ошибочные результаты не публикуют.
* verify не меняет выходной view при отказе. Ключ непосредственного ретранслятора здесь не используется. */
* parse проверяет только формат части; подпись источника проверяется после RS в batch_verify.
* Заимствованные части действуют до следующего encode/destroy; ошибочный результат не публикуют. */
#ifndef STREAM_BLOCK_H
#define STREAM_BLOCK_H
@@ -13,17 +14,23 @@ extern "C" {
struct stream_encoder;
struct stream_block_view {
struct stream_batch_info {
uint64_t seq;
uint32_t data_length;
uint16_t timestamp_ms;
uint8_t subblock;
uint16_t block_size; /* Фактический размер RS-кодограммы одной пачки. */
uint8_t flags;
const uint8_t *rs; /* Заимствованный диапазон descriptor.block_size байт. */
};
struct stream_block_view {
struct stream_batch_info batch;
uint8_t subblock;
const uint8_t *rs; /* Заимствованный диапазон batch.block_size байт. */
};
int stream_descriptor_validate(const struct stream_descriptor *descriptor);
size_t stream_block_size(const struct stream_descriptor *descriptor);
size_t stream_block_capacity(const struct stream_descriptor *descriptor);
/* Максимальная длина содержимого без подписанных метаданных/подписи. */
size_t stream_input_size(const struct stream_descriptor *descriptor);
/* out заранее NULL; ключ копируется и очищается при destroy. */
@@ -34,13 +41,18 @@ void stream_encoder_destroy(struct stream_encoder *encoder);
const uint8_t *stream_encoder_public_key(const struct stream_encoder *encoder);
/* blocks — массив descriptor.n указателей; input не перекрывается с рабочими буферами encoder.
* 0 < length <= stream_input_size; остаток пачки дополняется нулями. seq != UINT64_MAX.
* При ошибке blocks не изменяется; собственные рабочие буферы могут измениться. */
* 0 < length <= stream_input_size; подпись входит в RS, дополнение не превышает n-r-1 байт.
* block_length получает общий фактический размер частей. seq != UINT64_MAX.
* При ошибке blocks/block_length не изменяются; собственная рабочая память может измениться. */
int stream_encoder_encode(struct stream_encoder *encoder, uint64_t seq, uint16_t timestamp_ms, uint8_t flags,
const uint8_t *input, size_t length, const uint8_t **blocks);
const uint8_t *input, size_t length, const uint8_t **blocks, size_t *block_length);
int stream_block_verify(const struct stream_descriptor *descriptor, const uint8_t public_key[SC_PUBKEY_SIZE],
const uint8_t *wire, size_t length, struct stream_block_view *view);
/* Формат, дескриптор и канонический размер; криптографической проверки части нет. view не меняется при отказе. */
int stream_block_parse(const struct stream_descriptor *descriptor, const uint8_t *wire, size_t length, struct stream_block_view *view);
/* После RS сверить подписанные поля с ожидаемой пачкой, нулевой хвост и одну подпись источника.
* decoded_length — полный восстановленный размер с padding; содержимое начинается с STREAM_BATCH_HEADER. */
int stream_batch_verify(const struct stream_descriptor *descriptor, const uint8_t public_key[SC_PUBKEY_SIZE],
const struct stream_batch_info *expected, const uint8_t *decoded, size_t decoded_length);
#ifdef __cplusplus
}
+9 -4
View File
@@ -1,4 +1,4 @@
/* Неизменяемый блок источника: все числа big-endian, подпись охватывает тело до signature.
/* Части RS имеют непроверенный внешний заголовок; подписанная пачка находится внутри RS.
* Данные ETCP-выдачи (handle/сессия/путь) добавляются снаружи и в подпись не входят.
* seq/subblock берутся из заголовка RS; второго независимого номера блока нет. */
#ifndef STREAM_PROTO_H
@@ -10,7 +10,7 @@
#include "../../lib/reed_solomon.h"
#include "../transport_layer/secure_channel.h"
#define STREAM_BLOCK_DOMAIN "stream_block"
#define STREAM_BLOCK_DOMAIN "stream_part1"
#define STREAM_BLOCK_DOMAIN_SIZE 12
#define STREAM_BLOCK_GROUP_OFF 12
#define STREAM_BLOCK_SOURCE_OFF 20
@@ -24,7 +24,11 @@
#define STREAM_BLOCK_RS_OFF 47
#define STREAM_BLOCK_SEQ_OFF STREAM_BLOCK_RS_OFF
#define STREAM_BLOCK_SUB_OFF (STREAM_BLOCK_RS_OFF + 8)
#define STREAM_BLOCK_OVERHEAD (STREAM_BLOCK_RS_OFF + SC_SIGN_SIZE)
#define STREAM_BLOCK_OVERHEAD STREAM_BLOCK_RS_OFF
#define STREAM_BATCH_DOMAIN "stream_batch"
#define STREAM_BATCH_SEQ_OFF STREAM_BLOCK_RS_OFF
#define STREAM_BATCH_HEADER (STREAM_BATCH_SEQ_OFF + 8)
#define STREAM_BATCH_OVERHEAD (STREAM_BATCH_HEADER + SC_SIGN_SIZE)
#define STREAM_BLOCK_DEFAULT_SIZE 1300
#define STREAM_RS_DEFAULT_SIZE (STREAM_BLOCK_DEFAULT_SIZE - STREAM_BLOCK_OVERHEAD)
#define STREAM_BLOCK_MAX_SIZE (RS_MAX_BLOCK_SIZE + STREAM_BLOCK_OVERHEAD)
@@ -38,7 +42,7 @@ struct stream_descriptor {
uint64_t group_id;
uint64_t source_node_id;
uint64_t source_epoch;
uint16_t block_size; /* Полный размер RS-кодограммы, без stream-метаданных/подписи. */
uint16_t block_size; /* Максимальный размер RS-кодограммы; фактический размер задан в каждой пачке. */
uint8_t n;
uint8_t r;
};
@@ -49,6 +53,7 @@ enum stream_result {
STREAM_WAIT = 2,
STREAM_GAP = 3,
STREAM_EXPIRED = 4,
STREAM_REJECTED = 5, /* Пачка восстановлена, но подпись/подписанные метаданные не прошли проверку. */
STREAM_ERR_ARGUMENT = -1,
STREAM_ERR_MEMORY = -2,
STREAM_ERR_FORMAT = -3,