Reuse authenticated immutable RS subsets for playback reads
This commit is contained in:
1 parent
2fac28b7e9
commit
4ae8fc7c45
2 files changed
+21
-3
No files matched your search
@@ -27,6 +27,8 @@ struct stream_cached_batch {
|
||||
uint16_t count;
|
||||
uint8_t flags;
|
||||
int rejected;
|
||||
int verified;
|
||||
uint8_t verified_parts[(RS_MAX_BLOCKS + 7) / 8];
|
||||
};
|
||||
|
||||
struct stream_buffer {
|
||||
@@ -419,8 +421,11 @@ int stream_buffer_decode(struct stream_buffer *b, uint64_t seq, uint8_t *output,
|
||||
return STREAM_ERR_ARGUMENT;
|
||||
}
|
||||
const uint8_t *blocks[RS_MAX_BLOCKS] = {0};
|
||||
for (uint32_t slot = batch->first_slot; slot != STREAM_SLOT_NONE; slot = b->slots[slot].next)
|
||||
blocks[b->slots[slot].subblock] = b->data + slot * b->block_bytes + STREAM_BLOCK_RS_OFF;
|
||||
for (uint32_t slot = batch->first_slot; slot != STREAM_SLOT_NONE; slot = b->slots[slot].next) {
|
||||
unsigned sub = b->slots[slot].subblock;
|
||||
if (!batch->verified || (batch->verified_parts[sub / 8] & (1u << (sub % 8))))
|
||||
blocks[sub] = b->data + slot * b->block_bytes + STREAM_BLOCK_RS_OFF;
|
||||
}
|
||||
size_t decoded_size = (size_t)(b->descriptor.n - b->descriptor.r) * (batch->block_size - RS_HEADER_SIZE);
|
||||
if (rs_decode(b->rs, blocks, batch->block_size, b->decode_output, rs_input_capacity(b->rs)) != RS_OK) {
|
||||
DEBUG_ERROR(DEBUG_CATEGORY_STREAM, "buffer decode RS failed seq=%llu present=%u", (unsigned long long)seq, batch->count);
|
||||
@@ -428,7 +433,8 @@ int stream_buffer_decode(struct stream_buffer *b, uint64_t seq, uint8_t *output,
|
||||
}
|
||||
struct stream_batch_info expected = {.seq = batch->seq, .data_length = batch->data_length,
|
||||
.timestamp_ms = batch->timestamp_ms, .block_size = batch->block_size, .flags = batch->flags};
|
||||
int result = stream_batch_verify(&b->descriptor, b->public_key, &expected, b->decode_output, decoded_size);
|
||||
int result = batch->verified ? STREAM_OK
|
||||
: stream_batch_verify(&b->descriptor, b->public_key, &expected, b->decode_output, decoded_size);
|
||||
if (result != STREAM_OK) {
|
||||
if (result != STREAM_ERR_SIGNATURE && result != STREAM_ERR_FORMAT) return result;
|
||||
batch->rejected = 1; b->stats.rejected_batches++;
|
||||
@@ -448,6 +454,16 @@ int stream_buffer_decode(struct stream_buffer *b, uint64_t seq, uint8_t *output,
|
||||
}
|
||||
return STREAM_REJECTED;
|
||||
}
|
||||
if (!batch->verified) {
|
||||
unsigned selected = 0;
|
||||
for (unsigned sub = 0; sub < b->descriptor.n && selected < (unsigned)(b->descriptor.n - b->descriptor.r); sub++) {
|
||||
if (!blocks[sub]) continue;
|
||||
batch->verified_parts[sub / 8] |= (uint8_t)(1u << (sub % 8)); selected++;
|
||||
}
|
||||
batch->verified = 1;
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_STREAM, "buffer authenticated immutable RS set source=%llx seq=%llu parts=%u",
|
||||
(unsigned long long)b->descriptor.source_node_id, (unsigned long long)seq, selected);
|
||||
}
|
||||
memcpy(output, b->decode_output + STREAM_BATCH_HEADER, batch->data_length);
|
||||
*length = batch->data_length;
|
||||
DEBUG_TRACE(DEBUG_CATEGORY_STREAM, "buffer decoded seq=%llu present=%u length=%u", (unsigned long long)seq, batch->count, batch->data_length);
|
||||
|
||||
@@ -59,6 +59,8 @@ int stream_buffer_read(struct stream_buffer *buffer, uint64_t seq, uint8_t subbl
|
||||
int stream_buffer_range(struct stream_buffer *buffer, uint8_t subblock, uint64_t *first, uint64_t *last);
|
||||
|
||||
/* Восстановить пачку и проверить одну подпись; достаточно capacity >= действительной длины.
|
||||
* После успеха фиксируется использованный набор k неизменяемых частей: повторное чтение не проверяет подпись заново
|
||||
* и не доверяет поздним частям, которые не участвовали в подтверждённом восстановлении.
|
||||
* STREAM_REJECTED означает неверную подпись/подписанные метаданные; такая пачка повторно не декодируется.
|
||||
* Выход не меняется при WAIT/GAP/EXPIRED/REJECTED/ошибке; отсутствующие части в кольцо не добавляются. */
|
||||
int stream_buffer_decode(struct stream_buffer *buffer, uint64_t seq, uint8_t *output, size_t capacity, size_t *length);
|
||||
|
||||
Reference in new issue
Block a user