refactor: перевели хэши на BLOB и добавили поля block_hash / block_signature / edited_by_block_global_number

и главное добавили тип блока изменение сообщение и сслку на последнее изменение в табл блокс
This commit is contained in:
AidarKC
2026-01-07 19:58:50 +03:00
parent 8bcaa192c5
commit 06c77b1c1f
13 changed files with 306 additions and 284 deletions
@@ -27,6 +27,6 @@ public interface BodyHasTarget {
/** globalNumber цели (nullable). */
Integer toBlockGlobalNumber();
/** hash цели в HEX(64) (nullable). */
String toBlockHashe();
/** hash целевого блока (обычно 32 байта). Может быть null, если ссылки нет. */
byte[] toBlockHasheBytes();
}
@@ -49,9 +49,6 @@ import java.util.Objects;
*
* ВАЖНО: поля toBlockchainName/toBlockGlobalNumber/toBlockHash32 — это
* "последний известный блок" того человека (снимок/якорь состояния).
* По сути можно было бы обойтись без них, но они полезны:
* - фиксируют, какой блок и какой хэш ты считаешь последним известным у друга/контакта;
* - помогают синхронизации/проверкам (например, если потом сравнивать, насколько данные устарели).
*
* ЛИНИЯ:
* - строго lineIndex=3 (выделяем отдельную линию под связи).
@@ -182,7 +179,7 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget {
private static boolean isValidSubType(short st) {
return st == SUB_FRIEND || st == SUB_CONTACT || st == SUB_FOLLOW
|| st == SUB_UNFRIEND || st == SUB_UNCONTACT || st == SUB_UNFOLLOW;
|| st == SUB_UNFRIEND || st == SUB_UNCONTACT || st == SUB_UNFOLLOW;
}
/** true если это событие установки связи (10/20/30). */
@@ -348,5 +345,5 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget {
@Override public Integer toBlockGlobalNumber() { return toBlockGlobalNumber; }
@Override public String toBlockHashe() { return toBlockHashHex(); }
@Override public byte[] toBlockHasheBytes() { return toBlockHash32; }
}
@@ -15,9 +15,8 @@ import java.util.Objects;
* [2] type=2
* [2] ver=1
*
* [2] subType (uint16) — подтип реакции (раньше это был reactionCode int32)
* [2] subType (uint16) — подтип реакции
* 1 = LIKE (лайк)
* (в будущем: 2=DISLIKE, 3=LAUGH, 4=WOW ... если захочешь)
*
* [1] toBlockchainNameLen (uint8)
* [N] toBlockchainName UTF-8
@@ -26,10 +25,6 @@ import java.util.Objects;
*
* ЛИНИЯ:
* - строго lineIndex=2
*
* ВАЖНО (MVP):
* - Здесь мы НЕ проверяем, существует ли цель реакции.
* - Мы проверяем только корректность формата и целостность полей.
*/
public final class ReactionBody implements BodyRecord, BodyHasTarget {
@@ -191,7 +186,7 @@ public final class ReactionBody implements BodyRecord, BodyHasTarget {
}
/* ===================================================================== */
/* ====================== BodyToFields контракт ========================= */
/* ====================== BodyHasTarget контракт ========================= */
/* ===================================================================== */
/** В самом формате ReactionBody login цели не хранится => null. */
@@ -201,5 +196,5 @@ public final class ReactionBody implements BodyRecord, BodyHasTarget {
@Override public Integer toBlockGlobalNumber() { return toBlockGlobalNumber; }
@Override public String toBlockHashe() { return toBlockHashHex(); }
@Override public byte[] toBlockHasheBytes() { return toBlockHash32; }
}
@@ -33,13 +33,6 @@ import java.util.Objects;
*
* ЛИНИЯ:
* - строго lineIndex=1
*
* Правила строгого парсинга (чтобы формат не “плыл”):
* - subType обязан быть 1/2/3
* - textLen обязан быть >0 и <=65535
* - text обязан быть валидным UTF-8 и не blank
* - для subType=NEW запрещены поля ссылки и запрещены любые “лишние байты” в хвосте
* - для subType=REPLY/REPOST хвост обязан быть ровно по формату и без мусора в конце
*/
public final class TextBody implements BodyRecord, BodyHasTarget {
@@ -160,10 +153,6 @@ public final class TextBody implements BodyRecord, BodyHasTarget {
/* ====================== Конструкторы “для тестов” ====================== */
/* ===================================================================== */
/**
* Удобный конструктор для тестов/сборки простого сообщения:
* new TextBody(text) == new TextBody(SUB_NEW, text)
*/
public TextBody(String message) {
this(SUB_NEW, message);
}
@@ -244,7 +233,6 @@ public final class TextBody implements BodyRecord, BodyHasTarget {
if (toBlockHash32 == null || toBlockHash32.length != 32)
throw new IllegalArgumentException("toBlockHash32 invalid");
} else {
// SUB_NEW
if (toBlockchainName != null) throw new IllegalArgumentException("toBlockchainName must be null for SUB_NEW");
if (toBlockHash32 != null) throw new IllegalArgumentException("toBlockHash32 must be null for SUB_NEW");
}
@@ -279,7 +267,6 @@ public final class TextBody implements BodyRecord, BodyHasTarget {
cap += 1 + nameBytes.length + 4 + 32;
} else {
// SUB_NEW — ссылка запрещена
if (toBlockchainName != null || toBlockHash32 != null) {
throw new IllegalArgumentException("SUB_NEW must not contain reply/repost fields");
}
@@ -363,7 +350,7 @@ public final class TextBody implements BodyRecord, BodyHasTarget {
}
/* ===================================================================== */
/* ====================== BodyToFields контракт ========================= */
/* ====================== BodyHasTarget контракт ========================= */
/* ===================================================================== */
/** В формате TextBody login цели не хранится => null. */
@@ -380,7 +367,7 @@ public final class TextBody implements BodyRecord, BodyHasTarget {
}
@Override
public String toBlockHashe() {
return (subType == SUB_REPLY || subType == SUB_REPOST) ? toBlockHashHex() : null;
public byte[] toBlockHasheBytes() {
return (subType == SUB_REPLY || subType == SUB_REPOST) ? toBlockHash32 : null;
}
}