From f5698771e4c07b89dbc2878d49b89329feec60b52764cda07b40b456d6b48686 Mon Sep 17 00:00:00 2001 From: AidarKC Date: Sun, 27 Sep 2026 16:35:27 +0300 Subject: [PATCH] =?UTF-8?q?=D0=98=D1=81=D0=BF=D1=80=D0=B0=D0=B2=D0=B8?= =?UTF-8?q?=D1=82=D1=8C=20=D0=BF=D0=BE=D0=B2=D1=82=D0=BE=D1=80=20=D1=81?= =?UTF-8?q?=D0=BC=D0=B5=D0=BD=D1=8B=20=D0=BA=D0=BB=D1=8E=D1=87=D0=B5=D0=B9?= =?UTF-8?q?=20=D0=BF=D0=BE=D1=81=D0=BB=D0=B5=20=D0=BF=D1=83=D0=B1=D0=BB?= =?UTF-8?q?=D0=B8=D0=BA=D0=B0=D1=86=D0=B8=D0=B8=20candidate-=D1=86=D0=B5?= =?UTF-8?q?=D0=BF=D0=BE=D1=87=D0=BA=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Net_KeyRotationFinishChain_Handler.java | 6 ++++++ shine-UI/js/services/key-rotation-service.js | 10 ++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/keyRotation/Net_KeyRotationFinishChain_Handler.java b/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/keyRotation/Net_KeyRotationFinishChain_Handler.java index c4c5779d..e76f87e4 100644 --- a/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/keyRotation/Net_KeyRotationFinishChain_Handler.java +++ b/SHiNE-server/shine-server-net-protocol/src/main/java/server/logic/ws_protocol/JSON/handlers/keyRotation/Net_KeyRotationFinishChain_Handler.java @@ -19,6 +19,8 @@ import shine.db.entities.BlockEntry; import shine.db.entities.KeyRotationCandidateBlockEntry; import shine.db.entities.KeyRotationSessionEntry; import shine.db.entities.KeyRotationStatus; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.sql.Connection; import java.util.Arrays; @@ -31,6 +33,8 @@ import java.util.concurrent.locks.ReentrantLock; * затем переводит ротацию COPYING_CHAIN -> CHAIN_READY. */ public final class Net_KeyRotationFinishChain_Handler implements JsonMessageHandler { + private static final Logger log = LoggerFactory.getLogger(Net_KeyRotationFinishChain_Handler.class); + private final KeyRotationSessionsDAO rotations = KeyRotationSessionsDAO.getInstance(); private final KeyRotationCandidateBlocksDAO candidates = KeyRotationCandidateBlocksDAO.getInstance(); private final BlocksDAO blocks = BlocksDAO.getInstance(); @@ -103,6 +107,8 @@ public final class Net_KeyRotationFinishChain_Handler implements JsonMessageHand rotations.clearError(initial.getId()); return KeyRotationApiSupport.response(req.getOp(), req.getRequestId(), ready); } catch (Exception transitionFailure) { + log.warn("KeyRotationFinishChain transition failed: login={}, sessionId={}", + login, initial.getId(), transitionFailure); // Идемпотентность для параллельного FinishChain из другой сессии. try { KeyRotationSessionEntry now = rotations.getActiveByLogin(login); diff --git a/shine-UI/js/services/key-rotation-service.js b/shine-UI/js/services/key-rotation-service.js index 71e088fe..4d19f5ab 100644 --- a/shine-UI/js/services/key-rotation-service.js +++ b/shine-UI/js/services/key-rotation-service.js @@ -79,6 +79,11 @@ export class KeyRotationClient { const cutoff=Number(rotation.forkFromBlock); const source=String(rotation.sourceBlockchainName||''); if(!source || !Number.isInteger(cutoff) || cutoff<0) throw new Error('Некорректное состояние ротации'); if(String(newBundle?.blockchainPair?.publicKeyB64||'') !== String(rotation.newBlockchainKey||'')) throw new Error('Новый пароль выводит другой blockchain key'); + const total=cutoff+2; + if(Number(rotation.progressCurrent)||0 >= total) { + onProgress({ phase:'copy', current:total, total }); + return; + } const owner32=base64ToBytes(newBundle.blockchainPair.publicKeyB64); const privateKey=newBundle.blockchainPair.privateKey; let start=Math.max(0, Math.min(cutoff+1, Number(rotation.progressCurrent)||0)); @@ -106,10 +111,11 @@ export class KeyRotationClient { reasonCode:rotation.reasonCode, comment:rotation.comment, }); - const techFrame=makeFrame({ prevHash:rotation.forkFromHash, blockNumber:cutoff+1, type:0, subType:TECH_FORK_SUBTYPE, version:1, body:forkBody }); + const techTimestampMs=Number(rotation.createdAtMs)||Number(parentTipTimestampMs)+1000; + const techFrame=makeFrame({ prevHash:rotation.forkFromHash, blockNumber:cutoff+1, type:0, subType:TECH_FORK_SUBTYPE, version:1, body:forkBody, timestampMs:techTimestampMs }); const techRaw=await createAns104DataItem({ owner32, privateKey, data:techFrame, tags:[{name:'App',value:'test5590'}] }); await this.addCandidate({ blockNumber:cutoff+1, prevBlockHash:rotation.forkFromHash, blockBytesB64:bytesToBase64(techRaw) }); - onProgress({ phase:'copy', current:cutoff+2, total:cutoff+2 }); + onProgress({ phase:'copy', current:total, total }); } async #sourcePrevHash(source, blockNumber) {