SHA256
13 01 25
Переписал код кучи классов перешёл на новый надеюсь теперь подходящий формат блоков и тесты переделал. Но пока остались баги и тесты не проходят (в частности пользователи не создаются - ошибка в бд)
This commit is contained in:
@@ -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");
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user