Дорабатываю добавление блоков. Промежуточный исправления (не работают)
This commit is contained in:
AidarKC 2025-12-24 14:22:50 +03:00
parent 5ecaf67bcb
commit 80ea016687
4 changed files with 57 additions and 62 deletions

View File

@ -4,15 +4,11 @@ import server.logic.ws_protocol.JSON.entyties.Net_Request;
public final class Net_AddBlock_Request extends Net_Request { public final class Net_AddBlock_Request extends Net_Request {
private String login; // обязателен
private String blockchainName; // обязателен private String blockchainName; // обязателен
private int globalNumber; // обязателен private int globalNumber; // обязателен
private String prevGlobalHash; // HEX(64) или "" для нулевого private String prevGlobalHash; // HEX(64) или "" для нулевого
private String blockBytesB64; // байты FULL-блока (raw+sig+hash) в Base64 private String blockBytesB64; // байты FULL-блока (raw+sig+hash) в Base64
public String getLogin() { return login; }
public void setLogin(String login) { this.login = login; }
public String getBlockchainName() { return blockchainName; } public String getBlockchainName() { return blockchainName; }
public void setBlockchainName(String blockchainName) { this.blockchainName = blockchainName; } public void setBlockchainName(String blockchainName) { this.blockchainName = blockchainName; }

View File

@ -2,6 +2,7 @@ package server.logic.ws_protocol.JSON.handlers.blockchain;
import blockchain.BchBlockEntry; import blockchain.BchBlockEntry;
import blockchain.BchCryptoVerifier; import blockchain.BchCryptoVerifier;
import blockchain.body.BodyRecordParser;
import server.logic.ws_protocol.WireCodes; import server.logic.ws_protocol.WireCodes;
import shine.db.SqliteDbController; import shine.db.SqliteDbController;
import shine.db.dao.BlockchainStateDAO; import shine.db.dao.BlockchainStateDAO;
@ -68,7 +69,6 @@ public final class BlockchainStateService {
} }
public AddBlockResult addBlockAtomically( public AddBlockResult addBlockAtomically(
String login,
String blockchainName, String blockchainName,
int globalNumber, int globalNumber,
String prevGlobalHashHex, String prevGlobalHashHex,
@ -84,18 +84,8 @@ public final class BlockchainStateService {
if (loginFromBlockchainName == null || loginFromBlockchainName.isBlank()) if (loginFromBlockchainName == null || loginFromBlockchainName.isBlank())
return new AddBlockResult(WireCodes.Status.BAD_REQUEST, "bad_blockchain_name", 0, ""); return new AddBlockResult(WireCodes.Status.BAD_REQUEST, "bad_blockchain_name", 0, "");
// todo действительно давай прото брать логин из имени блокчена и не передавать его отдельно в запросе! // todo действительно давай прото брать логин из имени блокчена и не передавать его отдельно в запросе!
if (login == null || login.isBlank()) { String login = loginFromBlockchainName;
// раз уж у нас есть loginFromName можно принимать login пустым,
// но ты явно передаёшь login, поэтому пока так:
return new AddBlockResult(WireCodes.Status.BAD_REQUEST, "empty_login", 0, "");
}
// (опционально) сверка
if (!loginFromBlockchainName.equals(login)) {
return new AddBlockResult(WireCodes.Status.BAD_REQUEST, "login_not_match_blockchain_name", 0, "");
}
byte[] blockBytes; byte[] blockBytes;
try { try {
@ -105,12 +95,13 @@ public final class BlockchainStateService {
} }
// todo ну и ещё тут нужно проверить что не только сам формат блока верный, но и запись в этом блоке верная - тоесть что её можно распарсить! // todo ну и ещё тут нужно проверить что не только сам формат блока верный, но и запись в этом блоке верная - тоесть что её можно распарсить!
final BchBlockEntry block; final BchBlockEntry block;
try { try {
block = new BchBlockEntry(blockBytes); block = new BchBlockEntry(blockBytes);
// проверяем, что body распарсится и валидируется
BodyRecordParser.parse(block.bodyBytes).check();
} catch (Exception e) { } catch (Exception e) {
return new AddBlockResult(WireCodes.Status.BAD_REQUEST, "bad_block_format", 0, ""); return new AddBlockResult(WireCodes.Status.BAD_REQUEST, "bad_block_format", 0, "");
} }
@ -141,10 +132,21 @@ public final class BlockchainStateService {
BlockchainStateEntry st = stateDAO.getByBlockchainName(c, blockchainName); BlockchainStateEntry st = stateDAO.getByBlockchainName(c, blockchainName);
//todo тут надо учесть тот случай что если это 0 блок тоесть начало блокчейна то логично что ещё нет самого файла блокчейна и по этому нет и BlockchainStateEntry //todo тут надо учесть тот случай что если это 0 блок тоесть начало блокчейна то логично что ещё нет самого файла блокчейна и по этому нет и BlockchainStateEntry
boolean isGenesis = (globalNumber == 0);
if (st == null) { if (st == null) {
if (!isGenesis) {
c.rollback(); c.rollback();
return new AddBlockResult(WireCodes.Status.NOT_FOUND, "blockchain_state_not_found", 0, ""); return new AddBlockResult(WireCodes.Status.NOT_FOUND, "blockchain_state_not_found", 0, "");
} }
st = new BlockchainStateEntry();
st.setBlockchainName(blockchainName);
st.setLogin(login);
st.setLastGlobalNumber(-1);
st.setLastGlobalHash("");
st.setLastLineNumber(0, -1);
st.setLastLineHash(0, "");
}
// 3) проверяем последовательность глобального номера // 3) проверяем последовательность глобального номера
int expected = st.getLastGlobalNumber() + 1; int expected = st.getLastGlobalNumber() + 1;
@ -175,8 +177,8 @@ public final class BlockchainStateService {
prevLineHash32, prevLineHash32,
block.getRawBytes(), block.getRawBytes(),
block.getSignature64(), block.getSignature64(),
block.getHash32(), loginKey32,
loginKey32 block.getHash32()
); );
if (!ok) { if (!ok) {

View File

@ -8,6 +8,8 @@ import server.logic.ws_protocol.JSON.entyties.blockchain.Net_AddBlock_Response;
import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler; import server.logic.ws_protocol.JSON.handlers.JsonMessageHandler;
import server.logic.ws_protocol.WireCodes; import server.logic.ws_protocol.WireCodes;
import java.util.concurrent.locks.ReentrantLock;
public final class Net_AddBlock_Handler implements JsonMessageHandler { public final class Net_AddBlock_Handler implements JsonMessageHandler {
@Override @Override
@ -15,18 +17,19 @@ public final class Net_AddBlock_Handler implements JsonMessageHandler {
Net_AddBlock_Request req = (Net_AddBlock_Request) baseReq; Net_AddBlock_Request req = (Net_AddBlock_Request) baseReq;
// todo если пришёл запрос на добавление то надо блочить работу с этим блокчейном по req.getBlockchainName(),
// с помощью класса BlockchainLocks и разлочивать работу только в конце завершения работы этого хэндлера, что бы не случилось паралельной работы двух потоков с одним и тем же блокчейном!
ReentrantLock lock = BlockchainLocks.lockFor(req.getBlockchainName());
lock.lock();
try {
var r = BlockchainStateService.getInstance().addBlockAtomically( var r = BlockchainStateService.getInstance().addBlockAtomically(
req.getLogin(),
req.getBlockchainName(), req.getBlockchainName(),
req.getGlobalNumber(), req.getGlobalNumber(),
req.getPrevGlobalHash(), req.getPrevGlobalHash(),
req.getBlockBytesB64() req.getBlockBytesB64()
); );
// todo если пришёл запрос на добавление то надо блочить работу с этим блокчейном по req.getBlockchainName(),
// с помощью класса BlockchainLocks и разлочивать работу только в конце завершения работы этого хэндлера, что бы не случилось паралельной работы двух потоков с одним и тем же блокчейном!
Net_AddBlock_Response resp = new Net_AddBlock_Response(); Net_AddBlock_Response resp = new Net_AddBlock_Response();
resp.setOp(req.getOp()); resp.setOp(req.getOp());
resp.setRequestId(req.getRequestId()); resp.setRequestId(req.getRequestId());
@ -46,5 +49,9 @@ public final class Net_AddBlock_Handler implements JsonMessageHandler {
} }
return resp; return resp;
} finally {
lock.unlock();
}
} }
} }

View File

@ -19,7 +19,7 @@ import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage; import java.util.concurrent.CompletionStage;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
public class Test_AddBlock_new_NoAuth { public class Test_AddBlock_NoAuth {
private static final ObjectMapper JSON = new ObjectMapper(); private static final ObjectMapper JSON = new ObjectMapper();
@ -36,7 +36,6 @@ public class Test_AddBlock_new_NoAuth {
private int step = 0; private int step = 0;
private String lastGlobalHashHex = ZERO64; private String lastGlobalHashHex = ZERO64;
private String lastLineHashHex = ZERO64;
@Override @Override
public void onOpen(WebSocket ws) { public void onOpen(WebSocket ws) {
@ -54,7 +53,6 @@ public class Test_AddBlock_new_NoAuth {
String json = buildAddBlockJson( String json = buildAddBlockJson(
"test-add-header", "test-add-header",
TestConfig.TEST_LOGIN,
TestConfig.TEST_BCH_NAME, TestConfig.TEST_BCH_NAME,
0, 0,
ZERO64, ZERO64,
@ -82,22 +80,17 @@ public class Test_AddBlock_new_NoAuth {
} }
String serverLastGlobalHash = extractPayloadString(msg, "serverLastGlobalHash"); String serverLastGlobalHash = extractPayloadString(msg, "serverLastGlobalHash");
String serverLastLineHash = extractPayloadString(msg, "serverLastLineHash");
if (serverLastGlobalHash == null || serverLastGlobalHash.isBlank()) { if (serverLastGlobalHash == null || serverLastGlobalHash.isBlank()) {
System.out.println("❌ No serverLastGlobalHash in response"); System.out.println("❌ No serverLastGlobalHash in response");
ws.sendClose(WebSocket.NORMAL_CLOSURE, "bad-response"); ws.sendClose(WebSocket.NORMAL_CLOSURE, "bad-response");
return CompletableFuture.completedFuture(null); return CompletableFuture.completedFuture(null);
} }
if (serverLastLineHash == null || serverLastLineHash.isBlank()) {
serverLastLineHash = serverLastGlobalHash;
}
lastGlobalHashHex = serverLastGlobalHash; lastGlobalHashHex = serverLastGlobalHash;
lastLineHashHex = serverLastLineHash;
byte[] prevGlobal32 = hexToBytes32(lastGlobalHashHex); byte[] prevGlobal32 = hexToBytes32(lastGlobalHashHex);
byte[] prevLine32 = hexToBytes32(lastLineHashHex); byte[] prevLine32 = prevGlobal32;
// 2) TEXT block: global=1, line=0, lineNumber=1 // 2) TEXT block: global=1, line=0, lineNumber=1
byte[] textFull = buildTextBlockFullBytes( byte[] textFull = buildTextBlockFullBytes(
@ -111,7 +104,6 @@ public class Test_AddBlock_new_NoAuth {
String json2 = buildAddBlockJson( String json2 = buildAddBlockJson(
"test-add-text", "test-add-text",
TestConfig.TEST_LOGIN,
TestConfig.TEST_BCH_NAME, TestConfig.TEST_BCH_NAME,
1, 1,
lastGlobalHashHex, lastGlobalHashHex,
@ -238,7 +230,6 @@ public class Test_AddBlock_new_NoAuth {
// ================================================================================= // =================================================================================
private static String buildAddBlockJson(String requestId, private static String buildAddBlockJson(String requestId,
String login,
String blockchainName, String blockchainName,
int globalNumber, int globalNumber,
String prevGlobalHashHex, String prevGlobalHashHex,
@ -248,14 +239,13 @@ public class Test_AddBlock_new_NoAuth {
"op": "AddBlock", "op": "AddBlock",
"requestId": "%s", "requestId": "%s",
"payload": { "payload": {
"login": "%s",
"blockchainName": "%s", "blockchainName": "%s",
"globalNumber": %d, "globalNumber": %d,
"prevGlobalHash": "%s", "prevGlobalHash": "%s",
"blockBytesB64": "%s" "blockBytesB64": "%s"
} }
} }
""".formatted(requestId, login, blockchainName, globalNumber, prevGlobalHashHex, blockBytesB64); """.formatted(requestId, blockchainName, globalNumber, prevGlobalHashHex, blockBytesB64);
} }
// ================================================================================= // =================================================================================