From d9fe1f02b829d46ef6218d8b12e6cfcc7257148f07abe30ee9b475f6edfd6a15 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Thu, 15 Jan 2026 15:09:45 +0300 Subject: [PATCH] 15 01 25 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Исправил что бы в интерфейсе BodyHasTarget не требывалось хранить в блоках BodyHasTarget и в блоках коннекстин не зранилась поле тоЛогин в байты блока. (Все тесты тесты проходят) --- .../java/blockchain/body/BodyHasTarget.java | 21 +++++--- .../java/blockchain/body/ConnectionBody.java | 54 ++++++++----------- .../test/it/cases/IT_03_AddBlock_NoAuth.java | 13 ++--- 3 files changed, 41 insertions(+), 47 deletions(-) diff --git a/shine-server-blockchain/src/main/java/blockchain/body/BodyHasTarget.java b/shine-server-blockchain/src/main/java/blockchain/body/BodyHasTarget.java index ea0b976..12fe537 100644 --- a/shine-server-blockchain/src/main/java/blockchain/body/BodyHasTarget.java +++ b/shine-server-blockchain/src/main/java/blockchain/body/BodyHasTarget.java @@ -1,20 +1,25 @@ package blockchain.body; +import utils.blockchain.BlockchainNameUtil; + /** - * BodyHasTarget — дополнительный интерфейс для body, которые "ссылаются" на цель (to-поля). + * BodyHasTarget — контракт для body, которые "ссылаются" на цель (to-поля). * - * Идея: - * - Не все body имеют "to". - * - Но для индексации и удобства запросов в БД мы хотим единообразно доставать: - * toLogin, toBchName, toBlockGlobalNumber, toBlockHashe + * ВАЖНО (новое правило): + * - toLogin НЕ храним в байтах блока. + * - toLogin всегда вычисляем из toBchName по стандарту: + * toBchName = login + "-NNN" => toLogin = login * - * Важно: - * - Все методы могут возвращать null. + * Все методы могут возвращать null (если target отсутствует). */ public interface BodyHasTarget { /** login цели (nullable). */ - String toLogin(); + default String toLogin() { + String bch = toBchName(); + if (bch == null) return null; + return BlockchainNameUtil.loginFromBlockchainName(bch); + } /** blockchainName цели (nullable). */ String toBchName(); diff --git a/shine-server-blockchain/src/main/java/blockchain/body/ConnectionBody.java b/shine-server-blockchain/src/main/java/blockchain/body/ConnectionBody.java index c2979a1..cc2fb6d 100644 --- a/shine-server-blockchain/src/main/java/blockchain/body/ConnectionBody.java +++ b/shine-server-blockchain/src/main/java/blockchain/body/ConnectionBody.java @@ -1,6 +1,7 @@ package blockchain.body; import blockchain.MsgSubType; +import utils.blockchain.BlockchainNameUtil; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -16,18 +17,18 @@ import java.util.Objects; * CONTACT=20, UNCONTACT=21 * FOLLOW=30, UNFOLLOW=31 * - * bodyBytes (BigEndian), новый формат: + * bodyBytes (BigEndian), новый формат (toLogin НЕ ХРАНИМ): * [4] prevLineNumber * [32] prevLineHash32 * [4] thisLineNumber * - * [1] toLoginLen (uint8) - * [N] toLogin UTF-8 - * * [1] toBlockchainNameLen (uint8) - * [M] toBlockchainName UTF-8 + * [N] toBlockchainName UTF-8 * [4] toBlockGlobalNumber (int32) * [32] toBlockHash32 (raw 32 bytes) + * + * toLogin вычисляется автоматически из toBlockchainName: + * toLogin = BlockchainNameUtil.loginFromBlockchainName(toBlockchainName) */ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasLine { @@ -45,7 +46,6 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL public final int thisLineNumber; // payload - public final String toLogin; public final String toBlockchainName; public final int toBlockGlobalNumber; public final byte[] toBlockHash32; @@ -64,8 +64,8 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL } // минимум: - // line(4+32+4) + toLoginLen[1]+toLogin[1] + toBchLen[1]+toBch[1] + global[4] + hash[32] - if (bodyBytes.length < (4 + 32 + 4) + 1 + 1 + 1 + 1 + 4 + 32) { + // line(4+32+4) + toBchLen[1]+toBch[1] + global[4] + hash[32] + if (bodyBytes.length < (4 + 32 + 4) + 1 + 1 + 4 + 32) { throw new IllegalArgumentException("ConnectionBody too short"); } @@ -78,14 +78,6 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL this.thisLineNumber = bb.getInt(); - int toLoginLen = Byte.toUnsignedInt(bb.get()); - if (toLoginLen <= 0) throw new IllegalArgumentException("toLoginLen is 0"); - if (bb.remaining() < toLoginLen) throw new IllegalArgumentException("toLogin payload too short"); - - byte[] toLoginBytes = new byte[toLoginLen]; - bb.get(toLoginBytes); - this.toLogin = new String(toLoginBytes, StandardCharsets.UTF_8); - int bchLen = Byte.toUnsignedInt(bb.get()); if (bchLen <= 0) throw new IllegalArgumentException("toBlockchainNameLen is 0"); if (bb.remaining() < bchLen + 4 + 32) throw new IllegalArgumentException("Connection payload too short"); @@ -106,20 +98,21 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL byte[] prevLineHash32, int thisLineNumber, short subType, - String toLogin, String toBlockchainName, int toBlockGlobalNumber, byte[] toBlockHash32) { - Objects.requireNonNull(toLogin, "toLogin == null"); Objects.requireNonNull(toBlockchainName, "toBlockchainName == null"); Objects.requireNonNull(toBlockHash32, "toBlockHash32 == null"); if (!isValidSubType(subType)) throw new IllegalArgumentException("Bad connection subType: " + (subType & 0xFFFF)); - if (toLogin.isBlank()) throw new IllegalArgumentException("toLogin is blank"); - if (!toLogin.matches("^[A-Za-z0-9_]+$")) throw new IllegalArgumentException("toLogin must match ^[A-Za-z0-9_]+$"); if (toBlockchainName.isBlank()) throw new IllegalArgumentException("toBlockchainName is blank"); + // Железное правило формата: bchName -> login + "-NNN" + if (BlockchainNameUtil.loginFromBlockchainName(toBlockchainName) == null) { + throw new IllegalArgumentException("toBlockchainName must match login+\"-NNN\": " + toBlockchainName); + } + if (toBlockGlobalNumber < 0) throw new IllegalArgumentException("toBlockGlobalNumber < 0"); if (toBlockHash32.length != 32) throw new IllegalArgumentException("toBlockHash32 != 32"); @@ -130,7 +123,6 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL this.subType = subType; this.version = VER; - this.toLogin = toLogin; this.toBlockchainName = toBlockchainName; this.toBlockGlobalNumber = toBlockGlobalNumber; this.toBlockHash32 = Arrays.copyOf(toBlockHash32, 32); @@ -158,10 +150,13 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL if (prevLineHash32 == null || prevLineHash32.length != 32) throw new IllegalArgumentException("prevLineHash32 invalid"); } - if (toLogin == null || toLogin.isBlank()) throw new IllegalArgumentException("toLogin is blank"); - if (!toLogin.matches("^[A-Za-z0-9_]+$")) throw new IllegalArgumentException("toLogin must match ^[A-Za-z0-9_]+$"); + if (toBlockchainName == null || toBlockchainName.isBlank()) + throw new IllegalArgumentException("toBlockchainName is blank"); + + // гарантируем вычислимый toLogin (иначе target “битый” по стандарту) + if (BlockchainNameUtil.loginFromBlockchainName(toBlockchainName) == null) + throw new IllegalArgumentException("toBlockchainName must match login+\"-NNN\": " + toBlockchainName); - if (toBlockchainName == null || toBlockchainName.isBlank()) throw new IllegalArgumentException("toBlockchainName is blank"); if (toBlockGlobalNumber < 0) throw new IllegalArgumentException("toBlockGlobalNumber < 0"); if (toBlockHash32 == null || toBlockHash32.length != 32) throw new IllegalArgumentException("toBlockHash32 invalid"); @@ -170,10 +165,6 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL @Override public byte[] toBytes() { - byte[] toLoginBytes = toLogin.getBytes(StandardCharsets.UTF_8); - if (toLoginBytes.length == 0 || toLoginBytes.length > 255) - throw new IllegalArgumentException("toLogin utf8 len must be 1..255"); - byte[] bchBytes = toBlockchainName.getBytes(StandardCharsets.UTF_8); if (bchBytes.length == 0 || bchBytes.length > 255) throw new IllegalArgumentException("toBlockchainName utf8 len must be 1..255"); @@ -182,7 +173,6 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL throw new IllegalArgumentException("toBlockHash32 != 32"); int cap = (4 + 32 + 4) - + 1 + toLoginBytes.length + 1 + bchBytes.length + 4 + 32; @@ -192,9 +182,6 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL bb.put(prevLineHash32 == null ? new byte[32] : Arrays.copyOf(prevLineHash32, 32)); bb.putInt(thisLineNumber); - bb.put((byte) toLoginBytes.length); - bb.put(toLoginBytes); - bb.put((byte) bchBytes.length); bb.put(bchBytes); @@ -216,7 +203,8 @@ public final class ConnectionBody implements BodyRecord, BodyHasTarget, BodyHasL @Override public int thisLineNumber() { return thisLineNumber; } /* ====================== BodyHasTarget ===================== */ - @Override public String toLogin() { return toLogin; } + // toLogin() теперь default в интерфейсе и вычисляется из toBchName() + @Override public String toBchName() { return toBlockchainName; } @Override public Integer toBlockGlobalNumber() { return toBlockGlobalNumber; } @Override public byte[] toBlockHasheBytes() { return toBlockHash32; } diff --git a/src/test/java/test/it/cases/IT_03_AddBlock_NoAuth.java b/src/test/java/test/it/cases/IT_03_AddBlock_NoAuth.java index dc4c500..91dd70e 100644 --- a/src/test/java/test/it/cases/IT_03_AddBlock_NoAuth.java +++ b/src/test/java/test/it/cases/IT_03_AddBlock_NoAuth.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.*; * ВАЖНО: * - НЕТ обращения к blockchain.LineIndex (можно удалить LineIndex.java). * - Линии берём через ChainState.nextLineByType(TYPE_...). + * - ConnectionBody: toLogin в байтах НЕ хранится, вычисляется из toBlockchainName. */ public class IT_03_AddBlock_NoAuth { @@ -177,7 +178,7 @@ public class IT_03_AddBlock_NoAuth { var ln = st1.nextLineByType(ChainState.TYPE_CONNECTION); sender1.send(new ConnectionBody(ln.prevLineNumber, ln.prevLineHash32, ln.thisLineNumber, MsgSubType.CONNECTION_FOLLOW, - u2, bch2, 0, new byte[32] + bch2, 0, new byte[32] ), t); } @@ -186,7 +187,7 @@ public class IT_03_AddBlock_NoAuth { var ln = st1.nextLineByType(ChainState.TYPE_CONNECTION); sender1.send(new ConnectionBody(ln.prevLineNumber, ln.prevLineHash32, ln.thisLineNumber, MsgSubType.CONNECTION_FOLLOW, - u3, bch3, 0, new byte[32] + bch3, 0, new byte[32] ), t); } @@ -195,7 +196,7 @@ public class IT_03_AddBlock_NoAuth { var ln = st2.nextLineByType(ChainState.TYPE_CONNECTION); sender2.send(new ConnectionBody(ln.prevLineNumber, ln.prevLineHash32, ln.thisLineNumber, MsgSubType.CONNECTION_FOLLOW, - u1, bch1, 0, new byte[32] + bch1, 0, new byte[32] ), t); } @@ -204,7 +205,7 @@ public class IT_03_AddBlock_NoAuth { var ln = st2.nextLineByType(ChainState.TYPE_CONNECTION); sender2.send(new ConnectionBody(ln.prevLineNumber, ln.prevLineHash32, ln.thisLineNumber, MsgSubType.CONNECTION_FRIEND, - u1, bch1, 0, new byte[32] + bch1, 0, new byte[32] ), t); } @@ -219,7 +220,7 @@ public class IT_03_AddBlock_NoAuth { var ln = st1.nextLineByType(ChainState.TYPE_CONNECTION); sender1.send(new ConnectionBody(ln.prevLineNumber, ln.prevLineHash32, ln.thisLineNumber, MsgSubType.CONNECTION_FRIEND, - u2, bch2, 0, new byte[32] + bch2, 0, new byte[32] ), t); } @@ -227,7 +228,7 @@ public class IT_03_AddBlock_NoAuth { var ln = st2.nextLineByType(ChainState.TYPE_CONNECTION); sender2.send(new ConnectionBody(ln.prevLineNumber, ln.prevLineHash32, ln.thisLineNumber, MsgSubType.CONNECTION_UNFRIEND, - u1, bch1, 0, new byte[32] + bch1, 0, new byte[32] ), t); }