From c7d55ea1f95e504bd4cf8a6b95b4fa5873e50f49 Mon Sep 17 00:00:00 2001 From: coopops Date: Mon, 15 Jun 2026 10:54:43 +0000 Subject: [PATCH] =?UTF-8?q?[794-5][@ant]=20fix(api,shared):=20C6=20?= =?UTF-8?q?=E2=80=94=20=D0=BA=D0=B0=D0=BD=D0=BE=D0=BD=D0=B8=D0=B7=D0=B0?= =?UTF-8?q?=D1=86=D0=B8=D1=8F=20=D0=BF=D1=83=D0=B1=D0=BB=D0=B8=D1=87=D0=BD?= =?UTF-8?q?=D0=BE=D0=B3=D0=BE=20=D0=BA=D0=BB=D1=8E=D1=87=D0=B0=20=D0=BF?= =?UTF-8?q?=D0=B5=D1=80=D0=B5=D0=B4=20=D1=81=D1=80=D0=B0=D0=B2=D0=BD=D0=B5?= =?UTF-8?q?=D0=BD=D0=B8=D0=B5=D0=BC=20=E2=80=94=20=D1=81=D0=BD=D1=8F=D1=82?= =?UTF-8?q?=D1=8C=20=D0=BB=D0=BE=D0=B6=D0=BD=D1=8B=D0=B9=20=C2=AB=D0=BA?= =?UTF-8?q?=D0=BB=D1=8E=D1=87=20=D0=BD=D0=B5=20=D0=B0=D0=BA=D1=82=D0=B8?= =?UTF-8?q?=D0=B2=D0=B5=D0=BD=C2=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Один ключ встречается как legacy EOS... (бэкфилл из снапшота) и как PUB_K1_... (подписи нового SDK) — разные строки, строгое сравнение в checkActiveKey давало active:false. Добавлен canonicalPublicKey (PublicKey.from().toString()) в shared; C6 сравнивает обе стороны в канонической форме. Инцидент: документ Авдеев-Муравьев. --- apps/api/src/repo.ts | 7 ++++++- packages/shared/src/crypto/pubkey.ts | 20 ++++++++++++++++++++ packages/shared/src/index.ts | 1 + 3 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 packages/shared/src/crypto/pubkey.ts diff --git a/apps/api/src/repo.ts b/apps/api/src/repo.ts index 4a158f3..1ac80c0 100644 --- a/apps/api/src/repo.ts +++ b/apps/api/src/repo.ts @@ -1,4 +1,5 @@ import type { Kysely } from 'kysely'; +import { canonicalPublicKey } from '@verifier/shared'; import type { Database, KeyWeight } from './db/schema.js'; import { SYNC_KEY } from './config.js'; import { classify, type HealthView } from './services/health-status.js'; @@ -53,7 +54,11 @@ export async function checkActiveKey( } const keys = last.keys as unknown as KeyWeight[]; - const active = !last.is_deleted && keys.some((k) => k.public_key === publicKey); + // Ключ из документа (`PUB_K1_...`, новый SDK) и ключ в индексе (`EOS...` из бэкфилла + // снапшота / `PUB_K1_...` из native-deltas) — один и тот же ключ в разных кодировках. + // Сравниваем по канонической форме, иначе C6 ложно отдаёт «не активен». + const target = canonicalPublicKey(publicKey); + const active = !last.is_deleted && keys.some((k) => canonicalPublicKey(k.public_key) === target); return { active, last_known_block: last.block_num, diff --git a/packages/shared/src/crypto/pubkey.ts b/packages/shared/src/crypto/pubkey.ts new file mode 100644 index 0000000..b7d39b9 --- /dev/null +++ b/packages/shared/src/crypto/pubkey.ts @@ -0,0 +1,20 @@ +import { PublicKey } from '@wharfkit/antelope'; + +/** + * Канонизация публичного ключа к единому строковому виду (`PUB__...`). + * + * Один и тот же secp256k1-ключ встречается в ДВУХ кодировках: legacy `EOS...` + * (снапшот цепи / бэкфилл прав, старый SDK) и современный `PUB_K1_...` (подписи нового + * SDK, native-deltas парсера). Это разные строки с разной контрольной суммой — сравнивать + * их как есть нельзя, иначе C6 ложно отдаёт «ключ не активен на момент подписи», хотя ключ + * тот же. Приводим оба операнда к `.toString()` (новый формат) перед сравнением. + * + * На невалидной строке возвращаем вход как есть (сравнение тогда просто не совпадёт). + */ +export function canonicalPublicKey(key: string): string { + try { + return PublicKey.from(key).toString(); + } catch { + return key; + } +} diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index ab10048..217c3b2 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -1,4 +1,5 @@ export * from './types/index.js'; export * from './canonicalize/index.js'; export * from './crypto/sha256.js'; +export * from './crypto/pubkey.js'; export * from './checks/index.js';