diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java index 976ff1d..92ddf65 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/JsonHandlerRegistry.java @@ -6,8 +6,7 @@ import server.logic.ws_protocol.JSON.entyties.Auth.Net_CreateAuthSession_Request import server.logic.ws_protocol.JSON.entyties.Auth.Net_RefreshSession_Request; import server.logic.ws_protocol.JSON.entyties.Auth.Net_CloseActiveSession_Request; import server.logic.ws_protocol.JSON.entyties.Auth.Net_ListSessions_Request; -import server.logic.ws_protocol.JSON.entyties.blockchain.Net_AddBlock_new_Request; -import server.logic.ws_protocol.JSON.entyties.blockchain.Net_AddBlock_new_Response; +import server.logic.ws_protocol.JSON.entyties.blockchain.Net_AddBlock_Request; import server.logic.ws_protocol.JSON.entyties.tempToTest.Net_AddUser_Request; import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; import server.logic.ws_protocol.JSON.handlers.auth.Net_AuthChallenge_Handler; @@ -49,7 +48,7 @@ public final class JsonHandlerRegistry { "CreateAuthSession", Net_CreateAuthSession_Request.class, "CloseActiveSession", Net_CloseActiveSession_Request.class, "ListSessions", Net_ListSessions_Request.class, - "AddBlock", Net_AddBlock_new_Request.class + "AddBlock", Net_AddBlock_Request.class ); private JsonHandlerRegistry() { diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/Auth/Net_RefreshSession_Request.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/Auth/Net_RefreshSession_Request.java index fa34d88..543f871 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/Auth/Net_RefreshSession_Request.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/Auth/Net_RefreshSession_Request.java @@ -42,11 +42,7 @@ public class Net_RefreshSession_Request extends Net_Request { this.sessionPwd = sessionPwd; } - public String getClientInfo() { - return clientInfo; - } + public String getClientInfo() { return clientInfo; } - public void setClientInfo(String clientInfo) { - this.clientInfo = clientInfo; - } + public void setClientInfo(String clientInfo) { this.clientInfo = clientInfo; } } \ No newline at end of file diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_new_Request.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_Request.java similarity index 94% rename from shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_new_Request.java rename to shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_Request.java index 8a0bb26..a8a056e 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_new_Request.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_Request.java @@ -2,7 +2,7 @@ package server.logic.ws_protocol.JSON.entyties.blockchain; import server.logic.ws_protocol.JSON.entyties.Net_Request; -public final class Net_AddBlock_new_Request extends Net_Request { +public final class Net_AddBlock_Request extends Net_Request { private String login; // обязателен private long blockchainId; // обязателен diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_new_Response.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_Response.java similarity index 95% rename from shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_new_Response.java rename to shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_Response.java index f4e30ac..b27119d 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_new_Response.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/entyties/blockchain/Net_AddBlock_Response.java @@ -2,7 +2,7 @@ package server.logic.ws_protocol.JSON.entyties.blockchain; import server.logic.ws_protocol.JSON.entyties.Net_Response; -public final class Net_AddBlock_new_Response extends Net_Response { +public final class Net_AddBlock_Response extends Net_Response { private String reasonCode; // null если ok diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/BlockchainStateService_new.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/BlockchainStateService_new.java index efaeaf3..1954142 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/BlockchainStateService_new.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/BlockchainStateService_new.java @@ -1,5 +1,6 @@ package server.logic.ws_protocol.JSON.handlers.blockchain; +import server.logic.ws_protocol.WireCodes; import shine.db.SqliteDbController; import shine.db.dao.BlockchainStateDAO; import shine.db.dao.BlocksDAO; @@ -10,6 +11,8 @@ import shine.db.entities.SolanaUserEntry; import java.sql.Connection; import java.sql.SQLException; +import java.sql.Types; +import java.util.Base64; /** * BlockchainStateService_new — атомарное добавление блока: @@ -23,6 +26,25 @@ import java.sql.SQLException; */ public final class BlockchainStateService_new { + /** Результат атомарного addBlock */ + public static final class AddBlockResult { + public final int lineIndex; // 0..7 (пока ставим 0) + public final int httpStatus; // WireCodes.Status.* + public final String reasonCode; // null если ok + public final BlockchainStateEntry stateAfter; // состояние после (может быть null) + + public AddBlockResult(int lineIndex, int httpStatus, String reasonCode, BlockchainStateEntry stateAfter) { + this.lineIndex = lineIndex; + this.httpStatus = httpStatus; + this.reasonCode = reasonCode; + this.stateAfter = stateAfter; + } + + public boolean isOk() { + return httpStatus == WireCodes.Status.OK; + } + } + private static volatile BlockchainStateService_new instance; private final SqliteDbController db = SqliteDbController.getInstance(); @@ -42,25 +64,32 @@ public final class BlockchainStateService_new { } /** - * Атомарно добавляет блок (в рамках одной транзакции). - * - * @param login логин (для поиска loginId) - * @param blockchainId id блокчейна - * @param globalNumber глобальный номер - * @param prevGlobalHash предыдущий глобальный хэш - * @param blockBytesB64 блок (в Base64) — если у тебя уже byte[], сделай перегрузку + * Атомарно добавляет блок (в рамках одной транзакции) и возвращает результат, + * чтобы хэндлер мог заполнить ответ клиенту. */ - public void addBlockAtomically( + public AddBlockResult addBlockAtomically( String login, long blockchainId, int globalNumber, String prevGlobalHash, String blockBytesB64 - ) throws Exception { + ) { - // ⚠️ Тут я не трогаю твою бизнес-логику парсинга blockBytesB64. - // Просто предполагаю, что у тебя есть метод декодирования. - byte[] blockBytes = decodeBase64(blockBytesB64); + // Пока не парсим lineIndex из блока — ставим 0, чтобы протокол работал. + // Позже сделаем реальный разбор (и это же место будет правильным для вычисления хэшей). + final int lineIndex = 0; + + byte[] blockBytes; + try { + blockBytes = decodeBase64(blockBytesB64); + } catch (Exception e) { + return new AddBlockResult( + lineIndex, + WireCodes.Status.BAD_REQUEST, + "bad_block_base64", + null + ); + } try (Connection c = db.getConnection()) { boolean oldAutoCommit = c.getAutoCommit(); @@ -69,51 +98,72 @@ public final class BlockchainStateService_new { // 1) получаем loginId по login SolanaUserEntry u = solanaUsersDAO.getByLogin(c, login); if (u == null) { - throw new IllegalStateException("Не найден пользователь в solana_users по login=" + login); + c.rollback(); + return new AddBlockResult( + lineIndex, + WireCodes.Status.NOT_FOUND, + "user_not_found", + null + ); } long loginId = u.getLoginId(); // 2) вставляем блок в blocks - insertBlockRow(c, loginId, blockchainId, globalNumber, prevGlobalHash, blockBytes); + insertBlockRow(c, loginId, blockchainId, globalNumber, prevGlobalHash, blockBytes, lineIndex); - // 3) обновляем агрегатное состояние (если у тебя там отдельная логика — подключи сюда) - // Ниже — базовый пример, ты можешь заменить на свои расчёты lineHash/lineNumber и т.д. + // 3) обновляем агрегатное состояние blockchain_state BlockchainStateEntry st = stateDAO.getByBlockchainId(c, blockchainId); if (st == null) { - throw new IllegalStateException("Не найден blockchain_state для blockchainId=" + blockchainId); + c.rollback(); + return new AddBlockResult( + lineIndex, + WireCodes.Status.NOT_FOUND, + "blockchain_state_not_found", + null + ); } + // MVP: обновляем “последний глобальный номер”. + // Хэш тут сейчас оставлен как заглушка — лучше поставить фактический хэш нового блока. st.setLastGlobalNumber(globalNumber); - st.setLastGlobalHash(nn(prevGlobalHash)); // или новый hash, если ты его вычисляешь + st.setLastGlobalHash(nn(prevGlobalHash)); // TODO: заменить на hash нового блока st.setUpdatedAtMs(System.currentTimeMillis()); + // (линии пока не трогаем — позже внесём логику lineNumber/lineHash) stateDAO.upsert(c, st); c.commit(); + return new AddBlockResult(lineIndex, WireCodes.Status.OK, null, st); + } catch (Exception e) { - c.rollback(); - throw e; + try { c.rollback(); } catch (SQLException ignore) {} + return new AddBlockResult( + lineIndex, + WireCodes.Status.INTERNAL_ERROR, + "internal_error", + null + ); } finally { - c.setAutoCommit(oldAutoCommit); + try { c.setAutoCommit(oldAutoCommit); } catch (SQLException ignore) {} } + } catch (Exception e) { + return new AddBlockResult( + lineIndex, + WireCodes.Status.INTERNAL_ERROR, + "db_error", + null + ); } } - /** - * Вставка/обновление строки блока в таблицу blocks. - * - * Раньше у тебя тут был SQL, который пытался использовать колонку user_login — - * из-за этого и падало "table blocks has no column named user_login". - * - * Теперь всё делаем через BlocksDAO, где имена колонок гарантированно совпадают со схемой. - */ private void insertBlockRow( Connection c, long loginId, long blockchainId, int globalNumber, String prevGlobalHash, - byte[] blockBytes + byte[] blockBytes, + int lineIndex ) throws SQLException { BlockEntry e = new BlockEntry(); @@ -123,9 +173,8 @@ public final class BlockchainStateService_new { e.setBlockGlobalNumber(globalNumber); e.setBlockGlobalPreHashe(nn(prevGlobalHash)); - // ⚠️ Эти поля (линии/типы/маршрутизация) заполни так, как у тебя реально устроен блок. - // Я ставлю дефолты, чтобы код компилился и логика была ясна. - e.setBlockLineIndex(0); + // Заглушки под линии — позже заменим на реальную логику из blockBytes. + e.setBlockLineIndex(lineIndex); e.setBlockLineNumber(0); e.setBlockLinePreHashe(""); @@ -138,7 +187,6 @@ public final class BlockchainStateService_new { e.setToBlockGlobalNumber(0); e.setToBlockHashe(""); - // upsert — безопаснее, чем insert, если возможны повторы при ретраях blocksDAO.upsert(c, e); } @@ -150,6 +198,6 @@ public final class BlockchainStateService_new { private static byte[] decodeBase64(String s) { if (s == null || s.isBlank()) return null; - return java.util.Base64.getDecoder().decode(s); + return Base64.getDecoder().decode(s); } } \ No newline at end of file diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/Net_AddBlock_new_Handler.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/Net_AddBlock_new_Handler.java index db394c8..af2f879 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/Net_AddBlock_new_Handler.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/blockchain/Net_AddBlock_new_Handler.java @@ -3,8 +3,8 @@ package server.logic.ws_protocol.JSON.handlers.blockchain; import server.logic.ws_protocol.JSON.ConnectionContext; import server.logic.ws_protocol.JSON.entyties.Net_Request; import server.logic.ws_protocol.JSON.entyties.Net_Response; -import server.logic.ws_protocol.JSON.entyties.blockchain.Net_AddBlock_new_Request; -import server.logic.ws_protocol.JSON.entyties.blockchain.Net_AddBlock_new_Response; +import server.logic.ws_protocol.JSON.entyties.blockchain.Net_AddBlock_Request; +import server.logic.ws_protocol.JSON.entyties.blockchain.Net_AddBlock_Response; import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; import server.logic.ws_protocol.WireCodes; @@ -12,7 +12,7 @@ public final class Net_AddBlock_new_Handler implements JsonMessageHandler { @Override public Net_Response handle(Net_Request baseReq, ConnectionContext ctx) throws Exception { - Net_AddBlock_new_Request req = (Net_AddBlock_new_Request) baseReq; + Net_AddBlock_Request req = (Net_AddBlock_Request) baseReq; var r = BlockchainStateService_new.getInstance().addBlockAtomically( req.getLogin(), @@ -22,7 +22,7 @@ public final class Net_AddBlock_new_Handler implements JsonMessageHandler { req.getBlockBytesB64() ); - Net_AddBlock_new_Response resp = new Net_AddBlock_new_Response(); + Net_AddBlock_Response resp = new Net_AddBlock_Response(); resp.setOp(req.getOp()); resp.setRequestId(req.getRequestId()); resp.setLineIndex(r.lineIndex); diff --git a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/WireCodes.java b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/WireCodes.java index 782f736..f447ca2 100644 --- a/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/WireCodes.java +++ b/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/WireCodes.java @@ -28,6 +28,7 @@ public final class WireCodes { public static final int ALREADY_EXISTS = 409; // пришёл блок < N+1 public static final int NON_SEQUENTIAL = 412; // пришёл блок > N+1 + public static final int NOT_FOUND = 422; // Нет такого полбзователя - типо добавляем блок к которому нет пользователя - хотя на деле такой статус наверное никогда не вернётся, тк это раньше проверяется private Status() {}