Переписал код кучи классов перешёл на новый надеюсь теперь подходящий формат блоков

и тесты переделал.

Но пока остались баги и тесты не проходят (в частности пользователи не создаются - ошибка в бд)
This commit is contained in:
AidarKC
2026-01-13 16:18:38 +03:00
parent b7025dde59
commit e9e05c1192
23 changed files with 1516 additions and 2379 deletions
@@ -1,5 +1,5 @@
// =======================
// BlockchainStateDAO.java (НОВАЯ ВЕРСИЯ)
// shine/db/dao/BlockchainStateDAO.java (ИЗМЕНЁННАЯ: убраны line0..7, last_block_*)
// =======================
package shine.db.dao;
@@ -40,17 +40,9 @@ public final class BlockchainStateDAO {
blockchain_key,
size_limit,
file_size_bytes,
last_global_number,
last_global_hash,
updated_at_ms,
line0_last_number, line0_last_hash,
line1_last_number, line1_last_hash,
line2_last_number, line2_last_hash,
line3_last_number, line3_last_hash,
line4_last_number, line4_last_hash,
line5_last_number, line5_last_hash,
line6_last_number, line6_last_hash,
line7_last_number, line7_last_hash
last_block_number,
last_block_hash,
updated_at_ms
FROM blockchain_state
WHERE blockchain_name = ?
""";
@@ -73,10 +65,6 @@ public final class BlockchainStateDAO {
/** UPSERT с внешним соединением. Соединение НЕ закрывает. */
public void upsert(Connection c, BlockchainStateEntry e) throws SQLException {
// Колонок ровно 24:
// 8 основных + (8 линий * 2 поля) = 24
String sql = """
INSERT INTO blockchain_state (
blockchain_name,
@@ -84,53 +72,19 @@ public final class BlockchainStateDAO {
blockchain_key,
size_limit,
file_size_bytes,
last_global_number,
last_global_hash,
updated_at_ms,
line0_last_number, line0_last_hash,
line1_last_number, line1_last_hash,
line2_last_number, line2_last_hash,
line3_last_number, line3_last_hash,
line4_last_number, line4_last_hash,
line5_last_number, line5_last_hash,
line6_last_number, line6_last_hash,
line7_last_number, line7_last_hash
) VALUES (
?,?,?,?,?,?,?,?,
?,?,
?,?,
?,?,
?,?,
?,?,
?,?,
?,?,
?,?
)
last_block_number,
last_block_hash,
updated_at_ms
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
ON CONFLICT(blockchain_name)
DO UPDATE SET
login = excluded.login,
blockchain_key = excluded.blockchain_key,
size_limit = excluded.size_limit,
file_size_bytes = excluded.file_size_bytes,
last_global_number = excluded.last_global_number,
last_global_hash = excluded.last_global_hash,
updated_at_ms = excluded.updated_at_ms,
line0_last_number = excluded.line0_last_number,
line0_last_hash = excluded.line0_last_hash,
line1_last_number = excluded.line1_last_number,
line1_last_hash = excluded.line1_last_hash,
line2_last_number = excluded.line2_last_number,
line2_last_hash = excluded.line2_last_hash,
line3_last_number = excluded.line3_last_number,
line3_last_hash = excluded.line3_last_hash,
line4_last_number = excluded.line4_last_number,
line4_last_hash = excluded.line4_last_hash,
line5_last_number = excluded.line5_last_number,
line5_last_hash = excluded.line5_last_hash,
line6_last_number = excluded.line6_last_number,
line6_last_hash = excluded.line6_last_hash,
line7_last_number = excluded.line7_last_number,
line7_last_hash = excluded.line7_last_hash
login = excluded.login,
blockchain_key = excluded.blockchain_key,
size_limit = excluded.size_limit,
file_size_bytes = excluded.file_size_bytes,
last_block_number= excluded.last_block_number,
last_block_hash = excluded.last_block_hash,
updated_at_ms = excluded.updated_at_ms
""";
try (PreparedStatement ps = c.prepareStatement(sql)) {
@@ -143,14 +97,10 @@ public final class BlockchainStateDAO {
ps.setLong(i++, e.getSizeLimit());
ps.setLong(i++, e.getFileSizeBytes());
ps.setInt(i++, e.getLastGlobalNumber());
setBytesNullable(ps, i++, e.getLastGlobalHash());
ps.setLong(i++, e.getUpdatedAtMs());
ps.setInt(i++, e.getLastBlockNumber());
setBytesNullable(ps, i++, e.getLastBlockHash());
for (int line = 0; line < 8; line++) {
ps.setInt(i++, e.getLastLineNumber(line));
setBytesNullable(ps, i++, e.getLastLineHash(line));
}
ps.setLong(i++, e.getUpdatedAtMs());
ps.executeUpdate();
}
@@ -175,24 +125,10 @@ public final class BlockchainStateDAO {
ps.setLong(2, nowMs);
ps.setString(3, blockchainName);
ps.setLong(4, deltaBytes);
int updated = ps.executeUpdate();
return updated > 0;
return ps.executeUpdate() > 0;
}
}
/** Удобная проверка для HEADER: запись должна быть и last_global_number должен быть -1. */
public BlockchainStateEntry requireExistingAtGenesis(Connection c, String blockchainName) throws SQLException {
BlockchainStateEntry st = getByBlockchainName(c, blockchainName);
if (st == null) {
throw new IllegalStateException("Blockchain state not found for blockchainName=" + blockchainName);
}
if (st.getLastGlobalNumber() != -1) {
throw new IllegalStateException("Blockchain state is not at genesis (-1). blockchainName=" + blockchainName +
" last_global_number=" + st.getLastGlobalNumber());
}
return st;
}
private BlockchainStateEntry mapRow(ResultSet rs) throws SQLException {
BlockchainStateEntry e = new BlockchainStateEntry();
@@ -203,16 +139,11 @@ public final class BlockchainStateDAO {
e.setSizeLimit(rs.getLong("size_limit"));
e.setFileSizeBytes(rs.getLong("file_size_bytes"));
e.setLastGlobalNumber(rs.getInt("last_global_number"));
e.setLastGlobalHash(rs.getBytes("last_global_hash")); // может быть null
e.setLastBlockNumber(rs.getInt("last_block_number"));
e.setLastBlockHash(rs.getBytes("last_block_hash")); // nullable
e.setUpdatedAtMs(rs.getLong("updated_at_ms"));
for (int line = 0; line < 8; line++) {
e.setLastLineNumber(line, rs.getInt("line" + line + "_last_number"));
e.setLastLineHash(line, rs.getBytes("line" + line + "_last_hash")); // может быть null
}
return e;
}
@@ -1,3 +1,6 @@
// =======================
// shine/db/dao/BlocksDAO.java (ИЗМЕНЁННЫЙ под новый blocks формат + линейная проверка)
// =======================
package shine.db.dao;
import shine.db.SqliteDbController;
@@ -6,14 +9,14 @@ import shine.db.entities.BlockEntry;
import java.sql.*;
/**
* DAO для таблицы blocks.
* DAO для таблицы blocks (новый формат).
*
* Правило:
* - методы с Connection НЕ закрывают соединение
* - методы без Connection сами открывают и закрывают соединение
*
* Важно:
* - PRIMARY KEY удалён (временно), поэтому "upsert" сделан через UPDATE->INSERT.
* Ключ:
* - (bch_name, block_number) — уникальная пара в рамках общей БД сервера.
*/
public final class BlocksDAO {
@@ -39,26 +42,62 @@ public final class BlocksDAO {
INSERT INTO blocks (
login,
bch_name,
block_global_number,
block_global_pre_hashe,
block_line_index,
block_line_number,
block_line_pre_hashe,
block_number,
msg_type,
msg_sub_type,
block_byte,
block_bytes,
to_login,
to_bch_name,
to_block_global_number,
to_block_hashe,
to_block_number,
to_block_hash,
block_hash,
block_signature,
edited_by_block_global_number
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
edited_by_block_number,
prev_line_number,
prev_line_hash,
this_line_number
) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
""";
try (PreparedStatement ps = c.prepareStatement(sql)) {
bindAll(ps, e);
int i = 1;
ps.setString(i++, e.getLogin());
ps.setString(i++, e.getBchName());
ps.setInt(i++, e.getBlockNumber());
ps.setInt(i++, e.getMsgType());
ps.setInt(i++, e.getMsgSubType());
ps.setBytes(i++, e.getBlockBytes());
if (e.getToLogin() != null) ps.setString(i++, e.getToLogin());
else ps.setNull(i++, Types.VARCHAR);
if (e.getToBchName() != null) ps.setString(i++, e.getToBchName());
else ps.setNull(i++, Types.VARCHAR);
if (e.getToBlockNumber() != null) ps.setInt(i++, e.getToBlockNumber());
else ps.setNull(i++, Types.INTEGER);
if (e.getToBlockHash() != null) ps.setBytes(i++, e.getToBlockHash());
else ps.setNull(i++, Types.BLOB);
ps.setBytes(i++, e.getBlockHash());
ps.setBytes(i++, e.getBlockSignature());
if (e.getEditedByBlockNumber() != null) ps.setInt(i++, e.getEditedByBlockNumber());
else ps.setNull(i++, Types.INTEGER);
if (e.getPrevLineNumber() != null) ps.setInt(i++, e.getPrevLineNumber());
else ps.setNull(i++, Types.INTEGER);
if (e.getPrevLineHash() != null) ps.setBytes(i++, e.getPrevLineHash());
else ps.setNull(i++, Types.BLOB);
if (e.getThisLineNumber() != null) ps.setInt(i++, e.getThisLineNumber());
else ps.setNull(i++, Types.INTEGER);
ps.executeUpdate();
}
}
@@ -70,63 +109,62 @@ public final class BlocksDAO {
}
}
// -------------------- UPSERT (UPDATE -> INSERT) --------------------
public void upsert(Connection c, BlockEntry e) throws SQLException {
int updated = update(c, e);
if (updated == 0) insert(c, e);
}
public void upsert(BlockEntry e) throws SQLException {
try (Connection c = db.getConnection()) {
upsert(c, e);
}
}
// -------------------- SELECT --------------------
public BlockEntry getByPk(Connection c,
String login,
String bchName,
int blockGlobalNumber,
int blockLineIndex,
int blockLineNumber) throws SQLException {
// -------------------- SELECT: HASH BY NUMBER --------------------
/** Получить block_hash по (bch_name, block_number). Нужен для линейной проверки. */
public byte[] getHashByNumber(Connection c, String bchName, int blockNumber) throws SQLException {
String sql = """
SELECT
login,
bch_name,
block_global_number,
block_global_pre_hashe,
block_line_index,
block_line_number,
block_line_pre_hashe,
msg_type,
msg_sub_type,
block_byte,
to_login,
to_bch_name,
to_block_global_number,
to_block_hashe,
block_hash,
block_signature,
edited_by_block_global_number
SELECT block_hash
FROM blocks
WHERE
login = ?
AND bch_name = ?
AND block_global_number = ?
AND block_line_index = ?
AND block_line_number = ?
WHERE bch_name = ? AND block_number = ?
LIMIT 1
""";
try (PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, login);
ps.setString(2, bchName);
ps.setInt(3, blockGlobalNumber);
ps.setInt(4, blockLineIndex);
ps.setInt(5, blockLineNumber);
ps.setString(1, bchName);
ps.setInt(2, blockNumber);
try (ResultSet rs = ps.executeQuery()) {
if (!rs.next()) return null;
return rs.getBytes("block_hash");
}
}
}
public byte[] getHashByNumber(String bchName, int blockNumber) throws SQLException {
try (Connection c = db.getConnection()) {
return getHashByNumber(c, bchName, blockNumber);
}
}
// -------------------- SELECT: FULL ENTRY --------------------
public BlockEntry getByNumber(Connection c, String bchName, int blockNumber) throws SQLException {
String sql = """
SELECT
login,
bch_name,
block_number,
msg_type,
msg_sub_type,
block_bytes,
to_login,
to_bch_name,
to_block_number,
to_block_hash,
block_hash,
block_signature,
edited_by_block_number,
prev_line_number,
prev_line_hash,
this_line_number
FROM blocks
WHERE bch_name = ? AND block_number = ?
LIMIT 1
""";
try (PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, bchName);
ps.setInt(2, blockNumber);
try (ResultSet rs = ps.executeQuery()) {
if (!rs.next()) return null;
@@ -135,205 +173,57 @@ public final class BlocksDAO {
}
}
public BlockEntry getByPk(String login,
String bchName,
int blockGlobalNumber,
int blockLineIndex,
int blockLineNumber) throws SQLException {
public BlockEntry getByNumber(String bchName, int blockNumber) throws SQLException {
try (Connection c = db.getConnection()) {
return getByPk(c, login, bchName, blockGlobalNumber, blockLineIndex, blockLineNumber);
}
}
// -------------------- UPDATE --------------------
public int update(Connection c, BlockEntry e) throws SQLException {
String sql = """
UPDATE blocks
SET
block_global_pre_hashe = ?,
block_line_pre_hashe = ?,
msg_type = ?,
msg_sub_type = ?,
block_byte = ?,
to_login = ?,
to_bch_name = ?,
to_block_global_number = ?,
to_block_hashe = ?,
block_hash = ?,
block_signature = ?,
edited_by_block_global_number = ?
WHERE
login = ?
AND bch_name = ?
AND block_global_number = ?
AND block_line_index = ?
AND block_line_number = ?
""";
try (PreparedStatement ps = c.prepareStatement(sql)) {
int i = 1;
ps.setBytes(i++, bb(e.getBlockGlobalPreHashe()));
ps.setBytes(i++, bb(e.getBlockLinePreHashe()));
ps.setInt(i++, e.getMsgType());
ps.setInt(i++, e.getMsgSubType());
byte[] bytes = e.getBlockByte();
if (bytes != null) ps.setBytes(i++, bytes);
else ps.setNull(i++, Types.BLOB);
if (e.getToLogin() != null) ps.setString(i++, e.getToLogin());
else ps.setNull(i++, Types.VARCHAR);
if (e.getToBchName() != null) ps.setString(i++, e.getToBchName());
else ps.setNull(i++, Types.VARCHAR);
if (e.getToBlockGlobalNumber() != null) ps.setInt(i++, e.getToBlockGlobalNumber());
else ps.setNull(i++, Types.INTEGER);
if (e.getToBlockHashe() != null) ps.setBytes(i++, e.getToBlockHashe());
else ps.setNull(i++, Types.BLOB);
ps.setBytes(i++, bb(e.getBlockHash()));
ps.setBytes(i++, bb(e.getBlockSignature()));
if (e.getEditedByBlockGlobalNumber() != null) ps.setInt(i++, e.getEditedByBlockGlobalNumber());
else ps.setNull(i++, Types.INTEGER);
ps.setString(i++, e.getLogin());
ps.setString(i++, e.getBchName());
ps.setInt(i++, e.getBlockGlobalNumber());
ps.setInt(i++, e.getBlockLineIndex());
ps.setInt(i++, e.getBlockLineNumber());
return ps.executeUpdate();
}
}
public int update(BlockEntry e) throws SQLException {
try (Connection c = db.getConnection()) {
return update(c, e);
}
}
// -------------------- DELETE --------------------
public int deleteByPk(Connection c,
String login,
String bchName,
int blockGlobalNumber,
int blockLineIndex,
int blockLineNumber) throws SQLException {
String sql = """
DELETE FROM blocks
WHERE
login = ?
AND bch_name = ?
AND block_global_number = ?
AND block_line_index = ?
AND block_line_number = ?
""";
try (PreparedStatement ps = c.prepareStatement(sql)) {
ps.setString(1, login);
ps.setString(2, bchName);
ps.setInt(3, blockGlobalNumber);
ps.setInt(4, blockLineIndex);
ps.setInt(5, blockLineNumber);
return ps.executeUpdate();
}
}
public int deleteByPk(String login,
String bchName,
int blockGlobalNumber,
int blockLineIndex,
int blockLineNumber) throws SQLException {
try (Connection c = db.getConnection()) {
return deleteByPk(c, login, bchName, blockGlobalNumber, blockLineIndex, blockLineNumber);
return getByNumber(c, bchName, blockNumber);
}
}
// -------------------- INTERNAL --------------------
private static void bindAll(PreparedStatement ps, BlockEntry e) throws SQLException {
int i = 1;
ps.setString(i++, e.getLogin());
ps.setString(i++, e.getBchName());
ps.setInt(i++, e.getBlockGlobalNumber());
ps.setBytes(i++, bb(e.getBlockGlobalPreHashe()));
ps.setInt(i++, e.getBlockLineIndex());
ps.setInt(i++, e.getBlockLineNumber());
ps.setBytes(i++, bb(e.getBlockLinePreHashe()));
ps.setInt(i++, e.getMsgType());
ps.setInt(i++, e.getMsgSubType());
byte[] bytes = e.getBlockByte();
if (bytes != null) ps.setBytes(i++, bytes);
else ps.setNull(i++, Types.BLOB);
if (e.getToLogin() != null) ps.setString(i++, e.getToLogin());
else ps.setNull(i++, Types.VARCHAR);
if (e.getToBchName() != null) ps.setString(i++, e.getToBchName());
else ps.setNull(i++, Types.VARCHAR);
if (e.getToBlockGlobalNumber() != null) ps.setInt(i++, e.getToBlockGlobalNumber());
else ps.setNull(i++, Types.INTEGER);
if (e.getToBlockHashe() != null) ps.setBytes(i++, e.getToBlockHashe());
else ps.setNull(i++, Types.BLOB);
ps.setBytes(i++, bb(e.getBlockHash()));
ps.setBytes(i++, bb(e.getBlockSignature()));
if (e.getEditedByBlockGlobalNumber() != null) ps.setInt(i++, e.getEditedByBlockGlobalNumber());
else ps.setNull(i++, Types.INTEGER);
}
private BlockEntry mapRow(ResultSet rs) throws SQLException {
BlockEntry e = new BlockEntry();
e.setLogin(rs.getString("login"));
e.setBchName(rs.getString("bch_name"));
e.setBlockGlobalNumber(rs.getInt("block_global_number"));
e.setBlockGlobalPreHashe(rs.getBytes("block_global_pre_hashe"));
e.setBlockLineIndex(rs.getInt("block_line_index"));
e.setBlockLineNumber(rs.getInt("block_line_number"));
e.setBlockLinePreHashe(rs.getBytes("block_line_pre_hashe"));
e.setBlockNumber(rs.getInt("block_number"));
e.setMsgType(rs.getInt("msg_type"));
e.setMsgSubType(rs.getInt("msg_sub_type"));
e.setBlockByte(rs.getBytes("block_byte"));
e.setBlockBytes(rs.getBytes("block_bytes"));
e.setToLogin(rs.getString("to_login"));
String toLogin = rs.getString("to_login");
if (rs.wasNull()) toLogin = null;
e.setToLogin(toLogin);
String toBchName = rs.getString("to_bch_name");
if (rs.wasNull()) toBchName = null;
e.setToBchName(toBchName);
Integer toBlockGlobalNumber = (Integer) rs.getObject("to_block_global_number");
e.setToBlockGlobalNumber(toBlockGlobalNumber);
Integer toBlockNumber = (Integer) rs.getObject("to_block_number");
e.setToBlockNumber(toBlockNumber);
byte[] toBlockHashe = rs.getBytes("to_block_hashe");
if (rs.wasNull()) toBlockHashe = null;
e.setToBlockHashe(toBlockHashe);
byte[] toHash = rs.getBytes("to_block_hash");
if (rs.wasNull()) toHash = null;
e.setToBlockHash(toHash);
e.setBlockHash(rs.getBytes("block_hash"));
e.setBlockSignature(rs.getBytes("block_signature"));
Integer editedBy = (Integer) rs.getObject("edited_by_block_global_number");
e.setEditedByBlockGlobalNumber(editedBy);
Integer editedBy = (Integer) rs.getObject("edited_by_block_number");
e.setEditedByBlockNumber(editedBy);
Integer prevLn = (Integer) rs.getObject("prev_line_number");
e.setPrevLineNumber(prevLn);
byte[] prevLh = rs.getBytes("prev_line_hash");
if (rs.wasNull()) prevLh = null;
e.setPrevLineHash(prevLh);
Integer thisLn = (Integer) rs.getObject("this_line_number");
e.setThisLineNumber(thisLn);
return e;
}
private static byte[] bb(byte[] b) { return b == null ? new byte[0] : b; }
}
@@ -9,7 +9,7 @@ import java.sql.*;
/**
* UserCreateDAO — атомарное добавление пользователя:
* - solana_users (login, device_key)
* - blockchain_state (blockchain_name, login, blockchain_key, size_limit, ... last_global_number=-1 ...)
* - blockchain_state (blockchain_name, login, blockchain_key, size_limit, ... last_block_number=-1 ...)
*
* ВАЖНО:
* - только INSERT/UPSERT
@@ -67,14 +67,9 @@ public final class UserCreateDAO {
st.setSizeLimit(sizeLimit);
st.setFileSizeBytes(0L);
// старт: глобальных блоков ещё нет
st.setLastGlobalNumber(-1);
st.setLastGlobalHash(null);
for (int line = 0; line < 8; line++) {
st.setLastLineNumber(line, 0);
st.setLastLineHash(line, null);
}
// старт: блоков ещё нет
st.setLastBlockNumber(-1);
st.setLastBlockHash(null);
st.setUpdatedAtMs(nowMs);
@@ -1,93 +1,62 @@
// =======================
// shine/db/entities/BlockEntry.java (ИЗМЕНЁННАЯ под новый blocks формат)
// =======================
package shine.db.entities;
/**
* Запись блока (таблица blocks).
* Запись блока (таблица blocks) — обновлённая модель под новый формат.
*
* Храним:
* - login, bch_name (как было в проекте, чтобы не ломать общую БД)
* - block_number (глобальный номер в этой цепочке)
* - block_bytes (полный блок: preimage + signature)
* - block_hash (32 байта вычисленный SHA-256(preimage))
* - block_signature (64 байта)
*
* Опционально:
* - prev_line_number / prev_line_hash / this_line_number
*
* Плюс поля индексации (как раньше было удобно):
* - msg_type / msg_sub_type
* - to_* (если есть target)
* - edited_by_block_number (для TEXT_EDIT)
*/
public class BlockEntry {
private String login;
private String bchName;
private int blockGlobalNumber;
private byte[] blockGlobalPreHashe;
private int blockNumber;
private int blockLineIndex;
private int blockLineNumber;
private byte[] blockLinePreHashe;
private int msgType;
private int msgSubType;
private int msgType;
private int msgSubType;
private byte[] blockByte;
private byte[] blockBytes;
private String toLogin;
private String toBchName;
private Integer toBlockGlobalNumber;
private byte[] toBlockHashe;
private Integer toBlockNumber;
private byte[] toBlockHash;
// новое
private byte[] blockHash;
private byte[] blockSignature;
private Integer editedByBlockGlobalNumber;
private Integer editedByBlockNumber;
private Integer prevLineNumber;
private byte[] prevLineHash;
private Integer thisLineNumber;
public BlockEntry() {}
public BlockEntry(String login,
String bchName,
int blockGlobalNumber,
byte[] blockGlobalPreHashe,
int blockLineIndex,
int blockLineNumber,
byte[] blockLinePreHashe,
int msgType,
int msgSubType,
byte[] blockByte,
String toLogin,
String toBchName,
Integer toBlockGlobalNumber,
byte[] toBlockHashe,
byte[] blockHash,
byte[] blockSignature,
Integer editedByBlockGlobalNumber) {
this.login = login;
this.bchName = bchName;
this.blockGlobalNumber = blockGlobalNumber;
this.blockGlobalPreHashe = blockGlobalPreHashe;
this.blockLineIndex = blockLineIndex;
this.blockLineNumber = blockLineNumber;
this.blockLinePreHashe = blockLinePreHashe;
this.msgType = msgType;
this.msgSubType = msgSubType;
this.blockByte = blockByte;
this.toLogin = toLogin;
this.toBchName = toBchName;
this.toBlockGlobalNumber = toBlockGlobalNumber;
this.toBlockHashe = toBlockHashe;
this.blockHash = blockHash;
this.blockSignature = blockSignature;
this.editedByBlockGlobalNumber = editedByBlockGlobalNumber;
}
public String getLogin() { return login; }
public void setLogin(String login) { this.login = login; }
public String getBchName() { return bchName; }
public void setBchName(String bchName) { this.bchName = bchName; }
public int getBlockGlobalNumber() { return blockGlobalNumber; }
public void setBlockGlobalNumber(int blockGlobalNumber) { this.blockGlobalNumber = blockGlobalNumber; }
public byte[] getBlockGlobalPreHashe() { return blockGlobalPreHashe; }
public void setBlockGlobalPreHashe(byte[] blockGlobalPreHashe) { this.blockGlobalPreHashe = blockGlobalPreHashe; }
public int getBlockLineIndex() { return blockLineIndex; }
public void setBlockLineIndex(int blockLineIndex) { this.blockLineIndex = blockLineIndex; }
public int getBlockLineNumber() { return blockLineNumber; }
public void setBlockLineNumber(int blockLineNumber) { this.blockLineNumber = blockLineNumber; }
public byte[] getBlockLinePreHashe() { return blockLinePreHashe; }
public void setBlockLinePreHashe(byte[] blockLinePreHashe) { this.blockLinePreHashe = blockLinePreHashe; }
public int getBlockNumber() { return blockNumber; }
public void setBlockNumber(int blockNumber) { this.blockNumber = blockNumber; }
public int getMsgType() { return msgType; }
public void setMsgType(int msgType) { this.msgType = msgType; }
@@ -95,8 +64,8 @@ public class BlockEntry {
public int getMsgSubType() { return msgSubType; }
public void setMsgSubType(int msgSubType) { this.msgSubType = msgSubType; }
public byte[] getBlockByte() { return blockByte; }
public void setBlockByte(byte[] blockByte) { this.blockByte = blockByte; }
public byte[] getBlockBytes() { return blockBytes; }
public void setBlockBytes(byte[] blockBytes) { this.blockBytes = blockBytes; }
public String getToLogin() { return toLogin; }
public void setToLogin(String toLogin) { this.toLogin = toLogin; }
@@ -104,11 +73,11 @@ public class BlockEntry {
public String getToBchName() { return toBchName; }
public void setToBchName(String toBchName) { this.toBchName = toBchName; }
public Integer getToBlockGlobalNumber() { return toBlockGlobalNumber; }
public void setToBlockGlobalNumber(Integer toBlockGlobalNumber) { this.toBlockGlobalNumber = toBlockGlobalNumber; }
public Integer getToBlockNumber() { return toBlockNumber; }
public void setToBlockNumber(Integer toBlockNumber) { this.toBlockNumber = toBlockNumber; }
public byte[] getToBlockHashe() { return toBlockHashe; }
public void setToBlockHashe(byte[] toBlockHashe) { this.toBlockHashe = toBlockHashe; }
public byte[] getToBlockHash() { return toBlockHash; }
public void setToBlockHash(byte[] toBlockHash) { this.toBlockHash = toBlockHash; }
public byte[] getBlockHash() { return blockHash; }
public void setBlockHash(byte[] blockHash) { this.blockHash = blockHash; }
@@ -116,6 +85,15 @@ public class BlockEntry {
public byte[] getBlockSignature() { return blockSignature; }
public void setBlockSignature(byte[] blockSignature) { this.blockSignature = blockSignature; }
public Integer getEditedByBlockGlobalNumber() { return editedByBlockGlobalNumber; }
public void setEditedByBlockGlobalNumber(Integer editedByBlockGlobalNumber) { this.editedByBlockGlobalNumber = editedByBlockGlobalNumber; }
public Integer getEditedByBlockNumber() { return editedByBlockNumber; }
public void setEditedByBlockNumber(Integer editedByBlockNumber) { this.editedByBlockNumber = editedByBlockNumber; }
public Integer getPrevLineNumber() { return prevLineNumber; }
public void setPrevLineNumber(Integer prevLineNumber) { this.prevLineNumber = prevLineNumber; }
public byte[] getPrevLineHash() { return prevLineHash; }
public void setPrevLineHash(byte[] prevLineHash) { this.prevLineHash = prevLineHash; }
public Integer getThisLineNumber() { return thisLineNumber; }
public void setThisLineNumber(Integer thisLineNumber) { this.thisLineNumber = thisLineNumber; }
}
@@ -1,72 +1,38 @@
// =======================
// BlockchainStateEntry.java (НОВАЯ ВЕРСИЯ)
// shine/db/entities/BlockchainStateEntry.java (ИЗМЕНЁННАЯ: убраны line0..7, переименовано last_block_*)
// =======================
package shine.db.entities;
import java.util.Arrays;
import java.util.Base64;
/**
* Агрегатная сущность текущего состояния блокчейна.
* 1 строка = 1 blockchain_name, плюс состояние линий 0..7.
*
* ВАЖНО:
* - hash-поля теперь храним как byte[] и допускаем NULL:
* * NULL = "ещё не было ни одного блока" (genesis и т.п.)
* * не подменяем на new byte[0], чтобы не терять смысл
* - Убраны все поля линий line0..7 (они больше не нужны).
* - Оставляем:
* last_block_number
* last_block_hash
*
* Остальные поля (login, blockchain_key, лимиты) оставлены как в проекте,
* потому что серверу они реально нужны (ключ подписи/лимит файла).
*/
public final class BlockchainStateEntry {
private String blockchainName;
private String login;
private String blockchainKey;
private String blockchainKey; // Base64(32)
private long sizeLimit;
private long fileSizeBytes;
private int lastGlobalNumber;
private byte[] lastGlobalHash; // nullable
private final int[] lastLineNumbers = new int[8];
private final byte[][] lastLineHashes = new byte[8][]; // nullable elements
private int lastBlockNumber; // было last_global_number
private byte[] lastBlockHash; // было last_global_hash (nullable)
private long updatedAtMs;
public BlockchainStateEntry() {
// hashes остаются null по умолчанию (genesis)
}
public BlockchainStateEntry(String blockchainName,
String login,
String blockchainKey,
long sizeLimit,
long fileSizeBytes,
int lastGlobalNumber,
byte[] lastGlobalHash,
int[] lastLineNumbers,
byte[][] lastLineHashes,
long updatedAtMs) {
this.blockchainName = blockchainName;
this.login = login;
this.blockchainKey = blockchainKey;
this.sizeLimit = sizeLimit;
this.fileSizeBytes = fileSizeBytes;
this.lastGlobalNumber = lastGlobalNumber;
this.lastGlobalHash = lastGlobalHash;
if (lastLineNumbers != null) {
if (lastLineNumbers.length != 8) throw new IllegalArgumentException("lastLineNumbers must be len=8");
System.arraycopy(lastLineNumbers, 0, this.lastLineNumbers, 0, 8);
}
if (lastLineHashes != null) {
if (lastLineHashes.length != 8) throw new IllegalArgumentException("lastLineHashes must be len=8");
System.arraycopy(lastLineHashes, 0, this.lastLineHashes, 0, 8);
}
this.updatedAtMs = updatedAtMs;
}
public BlockchainStateEntry() {}
public String getBlockchainName() { return blockchainName; }
public void setBlockchainName(String blockchainName) { this.blockchainName = blockchainName; }
@@ -95,42 +61,12 @@ public final class BlockchainStateEntry {
public long getFileSizeBytes() { return fileSizeBytes; }
public void setFileSizeBytes(long fileSizeBytes) { this.fileSizeBytes = fileSizeBytes; }
public int getLastGlobalNumber() { return lastGlobalNumber; }
public void setLastGlobalNumber(int lastGlobalNumber) { this.lastGlobalNumber = lastGlobalNumber; }
public int getLastBlockNumber() { return lastBlockNumber; }
public void setLastBlockNumber(int lastBlockNumber) { this.lastBlockNumber = lastBlockNumber; }
public byte[] getLastGlobalHash() { return lastGlobalHash; }
public void setLastGlobalHash(byte[] lastGlobalHash) { this.lastGlobalHash = lastGlobalHash; }
public int getLastLineNumber(int line) {
checkLine(line);
return lastLineNumbers[line];
}
public void setLastLineNumber(int line, int value) {
checkLine(line);
lastLineNumbers[line] = value;
}
public byte[] getLastLineHash(int line) {
checkLine(line);
return lastLineHashes[line];
}
public void setLastLineHash(int line, byte[] value) {
checkLine(line);
lastLineHashes[line] = value;
}
public int[] getLastLineNumbersCopy() {
return Arrays.copyOf(lastLineNumbers, 8);
}
public byte[][] getLastLineHashesCopy() {
return Arrays.copyOf(lastLineHashes, 8);
}
public byte[] getLastBlockHash() { return lastBlockHash; }
public void setLastBlockHash(byte[] lastBlockHash) { this.lastBlockHash = lastBlockHash; }
public long getUpdatedAtMs() { return updatedAtMs; }
public void setUpdatedAtMs(long updatedAtMs) { this.updatedAtMs = updatedAtMs; }
private static void checkLine(int line) {
if (line < 0 || line > 7) throw new IllegalArgumentException("line must be 0..7");
}
}