17 12 25
Заработало блок добавляется в файл и в статус блокчена в БД!! Но ещё надо сделать таблицу с записями :)
This commit is contained in:
parent
2037ebaa8b
commit
e9c11d6b75
@ -187,7 +187,13 @@ public final class BlockchainStateService_new {
|
|||||||
s.setLastGlobalHash(ZERO64);
|
s.setLastGlobalHash(ZERO64);
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
|
if (i == 0) {
|
||||||
|
// линия 0: заглавный блок имеет lineNumber=0
|
||||||
|
s.setLastLineNumber(i, -1);
|
||||||
|
} else {
|
||||||
|
// остальные линии: первый блок будет lineNumber=1
|
||||||
s.setLastLineNumber(i, 0);
|
s.setLastLineNumber(i, 0);
|
||||||
|
}
|
||||||
s.setLastLineHash(i, ZERO64);
|
s.setLastLineHash(i, ZERO64);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -13,7 +13,6 @@ import java.net.http.HttpClient;
|
|||||||
import java.net.http.WebSocket;
|
import java.net.http.WebSocket;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
import java.nio.ByteOrder;
|
import java.nio.ByteOrder;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.Base64;
|
import java.util.Base64;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.concurrent.CompletionStage;
|
import java.util.concurrent.CompletionStage;
|
||||||
@ -24,7 +23,6 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
private static final String WS_URI = "ws://localhost:7070/ws";
|
private static final String WS_URI = "ws://localhost:7070/ws";
|
||||||
private static final ObjectMapper JSON = new ObjectMapper();
|
private static final ObjectMapper JSON = new ObjectMapper();
|
||||||
|
|
||||||
// ======= ДАННЫЕ (взяты по аналогии с твоим тестом) =======
|
|
||||||
private static final String TEST_LOGIN = "anya24";
|
private static final String TEST_LOGIN = "anya24";
|
||||||
private static final long TEST_BCH_ID = 4222L;
|
private static final long TEST_BCH_ID = 4222L;
|
||||||
|
|
||||||
@ -36,8 +34,8 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
LOGIN_PUB_KEY = Ed25519Util.derivePublicKey(LOGIN_PRIV_KEY);
|
LOGIN_PUB_KEY = Ed25519Util.derivePublicKey(LOGIN_PRIV_KEY);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Нулевой хэш (для первого блока)
|
|
||||||
private static final byte[] ZERO32 = new byte[32];
|
private static final byte[] ZERO32 = new byte[32];
|
||||||
|
private static final String ZERO64 = "0".repeat(64);
|
||||||
|
|
||||||
public static void main(String[] args) throws Exception {
|
public static void main(String[] args) throws Exception {
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
CountDownLatch latch = new CountDownLatch(1);
|
||||||
@ -48,26 +46,32 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
|
|
||||||
private int step = 0;
|
private int step = 0;
|
||||||
|
|
||||||
// сервер просил в request: blockchainId + globalNumber + prevGlobalHash + bytes блока
|
// Эти значения обновим ПО ОТВЕТУ сервера на header
|
||||||
// prevLineHash сервер может не просить — но для подписи нам он нужен
|
private String lastGlobalHashHex = ZERO64;
|
||||||
private byte[] lastGlobalHash = ZERO32;
|
private String lastLineHashHex = ZERO64;
|
||||||
private byte[] lastLineHash = ZERO32;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onOpen(WebSocket ws) {
|
public void onOpen(WebSocket ws) {
|
||||||
System.out.println("✅ WS connected: " + WS_URI);
|
System.out.println("✅ WS connected: " + WS_URI);
|
||||||
ws.request(1);
|
ws.request(1);
|
||||||
|
|
||||||
// 1) Header block
|
// 1) HEADER (global=0, line=0, lineNumber=0)
|
||||||
byte[] headerFull = buildHeaderBlockFullBytes(
|
byte[] headerFull = buildHeaderBlockFullBytes(
|
||||||
/*global*/0,
|
/*global*/0,
|
||||||
/*lineIndex*/(short)0,
|
/*lineIndex*/(short)0,
|
||||||
/*lineBlock*/0,
|
/*lineBlock*/0,
|
||||||
lastGlobalHash,
|
/*prevGlobal*/ZERO32,
|
||||||
lastLineHash
|
/*prevLine*/ZERO32
|
||||||
|
);
|
||||||
|
|
||||||
|
String json = buildAddBlockJson(
|
||||||
|
"test-add-header",
|
||||||
|
TEST_BCH_ID,
|
||||||
|
0,
|
||||||
|
ZERO64, // prevGlobalHash для первого блока — нули
|
||||||
|
base64(headerFull)
|
||||||
);
|
);
|
||||||
|
|
||||||
String json = buildAddBlockJson("test-add-header", TEST_BCH_ID, 0, bytesToHex(lastGlobalHash), base64(headerFull));
|
|
||||||
System.out.println("\n📤 SEND #1 (HEADER):\n" + json);
|
System.out.println("\n📤 SEND #1 (HEADER):\n" + json);
|
||||||
ws.sendText(json, true);
|
ws.sendText(json, true);
|
||||||
}
|
}
|
||||||
@ -80,6 +84,7 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
int status = extractStatus(msg);
|
int status = extractStatus(msg);
|
||||||
|
|
||||||
if (step == 0) {
|
if (step == 0) {
|
||||||
if (status != 200) {
|
if (status != 200) {
|
||||||
System.out.println("❌ HEADER rejected, status=" + status);
|
System.out.println("❌ HEADER rejected, status=" + status);
|
||||||
@ -87,32 +92,54 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
return CompletableFuture.completedFuture(null);
|
return CompletableFuture.completedFuture(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Обновляем prev-хэши для следующего блока: берём хэш из нашего же блока (как ожидаемую цепочку)
|
// Берём ИМЕННО ТОТ хэш, который сервер сохранил в state
|
||||||
byte[] headerFull = lastSentBlockFullFromResponseOrLocalFallback(true);
|
String serverLastGlobalHash = extractPayloadString(msg, "serverLastGlobalHash");
|
||||||
// Fallback: просто пересоберём ровно так же (надёжнее: хранить отправленные байты)
|
String serverLastLineHash = extractPayloadString(msg, "serverLastLineHash");
|
||||||
headerFull = buildHeaderBlockFullBytes(0, (short)0, 0, ZERO32, ZERO32);
|
|
||||||
|
|
||||||
BchBlockEntry_new hb = new BchBlockEntry_new(headerFull);
|
if (serverLastGlobalHash == null || serverLastGlobalHash.isBlank()) {
|
||||||
lastGlobalHash = hb.getHash32();
|
System.out.println("❌ No serverLastGlobalHash in response");
|
||||||
lastLineHash = hb.getHash32();
|
ws.sendClose(WebSocket.NORMAL_CLOSURE, "bad-response");
|
||||||
|
return CompletableFuture.completedFuture(null);
|
||||||
|
}
|
||||||
|
if (serverLastLineHash == null || serverLastLineHash.isBlank()) {
|
||||||
|
// fallback: пусть будет как global (если сервер так хранит)
|
||||||
|
serverLastLineHash = serverLastGlobalHash;
|
||||||
|
}
|
||||||
|
|
||||||
// 2) Text block
|
lastGlobalHashHex = serverLastGlobalHash;
|
||||||
|
lastLineHashHex = serverLastLineHash;
|
||||||
|
|
||||||
|
byte[] prevGlobal32 = hexToBytes32(lastGlobalHashHex);
|
||||||
|
byte[] prevLine32 = hexToBytes32(lastLineHashHex);
|
||||||
|
|
||||||
|
// 2) TEXT (global=1, line=0, lineNumber=1)
|
||||||
byte[] textFull = buildTextBlockFullBytes(
|
byte[] textFull = buildTextBlockFullBytes(
|
||||||
/*global*/1,
|
/*global*/1,
|
||||||
/*lineIndex*/(short)0,
|
/*lineIndex*/(short)0,
|
||||||
/*lineBlock*/1,
|
/*lineBlock*/1,
|
||||||
lastGlobalHash,
|
prevGlobal32,
|
||||||
lastLineHash,
|
prevLine32,
|
||||||
"Hello from test client"
|
"Hello from test client"
|
||||||
);
|
);
|
||||||
|
|
||||||
String json2 = buildAddBlockJson("test-add-text", TEST_BCH_ID, 1, bytesToHex(lastGlobalHash), base64(textFull));
|
String json2 = buildAddBlockJson(
|
||||||
|
"test-add-text",
|
||||||
|
TEST_BCH_ID,
|
||||||
|
1,
|
||||||
|
lastGlobalHashHex, // prevGlobalHash = хэш header'а из ответа сервера
|
||||||
|
base64(textFull)
|
||||||
|
);
|
||||||
|
|
||||||
System.out.println("\n📤 SEND #2 (TEXT):\n" + json2);
|
System.out.println("\n📤 SEND #2 (TEXT):\n" + json2);
|
||||||
step = 1;
|
step = 1;
|
||||||
ws.sendText(json2, true);
|
ws.sendText(json2, true);
|
||||||
|
|
||||||
} else if (step == 1) {
|
} else if (step == 1) {
|
||||||
|
if (status != 200) {
|
||||||
|
System.out.println("❌ TEXT rejected, status=" + status);
|
||||||
|
} else {
|
||||||
System.out.println("✅ Done. Closing.");
|
System.out.println("✅ Done. Closing.");
|
||||||
|
}
|
||||||
ws.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
|
ws.sendClose(WebSocket.NORMAL_CLOSURE, "ok");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,7 +180,6 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
byte[] prevGlobalHash32,
|
byte[] prevGlobalHash32,
|
||||||
byte[] prevLineHash32) {
|
byte[] prevLineHash32) {
|
||||||
|
|
||||||
// bodyBytes (включая type+version внутри)
|
|
||||||
HeaderBody body = new HeaderBody(
|
HeaderBody body = new HeaderBody(
|
||||||
TEST_BCH_ID,
|
TEST_BCH_ID,
|
||||||
TEST_LOGIN,
|
TEST_LOGIN,
|
||||||
@ -173,6 +199,7 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
byte[] prevGlobalHash32,
|
byte[] prevGlobalHash32,
|
||||||
byte[] prevLineHash32,
|
byte[] prevLineHash32,
|
||||||
String text) {
|
String text) {
|
||||||
|
|
||||||
TextBody body = new TextBody(text);
|
TextBody body = new TextBody(text);
|
||||||
byte[] bodyBytes = body.toBytes();
|
byte[] bodyBytes = body.toBytes();
|
||||||
|
|
||||||
@ -188,8 +215,6 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
|
|
||||||
long ts = System.currentTimeMillis() / 1000L;
|
long ts = System.currentTimeMillis() / 1000L;
|
||||||
|
|
||||||
// Собираем rawBytes вручную в точности как BchBlockEntry_new RAW:
|
|
||||||
// [4]recordSize [4]recordNumber [8]ts [2]lineIndex [4]lineBlockNumber [body...]
|
|
||||||
int recordSize =
|
int recordSize =
|
||||||
BchBlockEntry_new.RAW_HEADER_SIZE +
|
BchBlockEntry_new.RAW_HEADER_SIZE +
|
||||||
bodyBytes.length +
|
bodyBytes.length +
|
||||||
@ -215,10 +240,9 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
|
|
||||||
byte[] hash32 = BchCryptoVerifier_new.sha256(preimage);
|
byte[] hash32 = BchCryptoVerifier_new.sha256(preimage);
|
||||||
|
|
||||||
// ВАЖНО: если у тебя в протоколе подпись делается НЕ по hash32, а по preimage — замени тут на preimage
|
// если у тебя подпись должна быть по preimage — меняй тут
|
||||||
byte[] signature64 = Ed25519Util.sign(hash32, LOGIN_PRIV_KEY);
|
byte[] signature64 = Ed25519Util.sign(hash32, LOGIN_PRIV_KEY);
|
||||||
|
|
||||||
// FULL block
|
|
||||||
return new BchBlockEntry_new(
|
return new BchBlockEntry_new(
|
||||||
globalNumber,
|
globalNumber,
|
||||||
ts,
|
ts,
|
||||||
@ -239,7 +263,6 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
int globalNumber,
|
int globalNumber,
|
||||||
String prevGlobalHashHex,
|
String prevGlobalHashHex,
|
||||||
String blockBytesB64) {
|
String blockBytesB64) {
|
||||||
// Если у тебя в Net_AddBlock_new_Request другие имена полей — скажешь, подправлю.
|
|
||||||
return """
|
return """
|
||||||
{
|
{
|
||||||
"op": "AddBlock",
|
"op": "AddBlock",
|
||||||
@ -267,18 +290,32 @@ public class Test_AddBlock_new_NoAuth {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static String extractPayloadString(String json, String field) {
|
||||||
|
try {
|
||||||
|
JsonNode root = JSON.readTree(json);
|
||||||
|
JsonNode payload = root.get("payload");
|
||||||
|
if (payload != null && payload.has(field)) {
|
||||||
|
return payload.get(field).asText();
|
||||||
|
}
|
||||||
|
} catch (Exception ignore) {}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
private static String base64(byte[] bytes) {
|
private static String base64(byte[] bytes) {
|
||||||
return Base64.getEncoder().encodeToString(bytes);
|
return Base64.getEncoder().encodeToString(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String bytesToHex(byte[] b) {
|
private static byte[] hexToBytes32(String hex) {
|
||||||
StringBuilder sb = new StringBuilder(b.length * 2);
|
if (hex == null) throw new IllegalArgumentException("hex is null");
|
||||||
for (byte x : b) sb.append(String.format("%02x", x));
|
String s = hex.trim();
|
||||||
return sb.toString();
|
if (s.length() != 64) throw new IllegalArgumentException("hex must be 64 chars, got " + s.length());
|
||||||
|
byte[] out = new byte[32];
|
||||||
|
for (int i = 0; i < 32; i++) {
|
||||||
|
int hi = Character.digit(s.charAt(i * 2), 16);
|
||||||
|
int lo = Character.digit(s.charAt(i * 2 + 1), 16);
|
||||||
|
if (hi < 0 || lo < 0) throw new IllegalArgumentException("bad hex at pos " + (i * 2));
|
||||||
|
out[i] = (byte) ((hi << 4) | lo);
|
||||||
}
|
}
|
||||||
|
return out;
|
||||||
// Заглушка: в этом тесте проще хранить отправленные байты локально.
|
|
||||||
private static byte[] lastSentBlockFullFromResponseOrLocalFallback(boolean header) {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Reference in New Issue
Block a user