From dbeef9f415203e886afa014ba6e8b476ac6063ac Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 26 Jan 2026 18:11:17 -0800 Subject: [PATCH] =?UTF-8?q?fix(android):=20=E4=BF=AE=E6=AD=A32-of-3?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E5=99=A8=E5=A4=87=E4=BB=BD=E5=8F=82=E4=B8=8E?= =?UTF-8?q?=E6=96=B9=E9=80=89=E6=8B=A9=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题描述: 之前的实现在勾选"包含服务器备份"时,会选择全部3个参与方 (2个用户设备 + 1个服务器),导致后端报错: "need exactly 2 parties for threshold 2, got 3" 根本原因: buildSigningParticipantList() 方法在 includeServerParties=true 时, 返回了所有参与方,没有排除丢失的设备。 修复内容: 1. buildSigningParticipantList() 新增 currentPartyId 参数 2. includeServerBackup=true 时的新逻辑: - 只选择当前设备 (currentPartyId) - 加上服务器方 (co-managed-party-*) - 排除另一个丢失的用户设备 - 总共正好 2 个参与方,满足 threshold t=2 3. 增强调试日志: - [PARTICIPANT-LIST] Device lost mode - Selected X parties for signing 测试场景: - 不勾选:2个用户设备参与(默认行为) - 勾选:1个当前设备 + 1个服务器 = 2方(设备丢失场景) 修改文件: - TssRepository.kt (lines 3719-3744, 3796-3804) Co-Authored-By: Claude Sonnet 4.5 --- .../tssparty/data/repository/TssRepository.kt | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/data/repository/TssRepository.kt b/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/data/repository/TssRepository.kt index a6802a9d..670e92f0 100644 --- a/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/data/repository/TssRepository.kt +++ b/backend/mpc-system/services/service-party-android/app/src/main/java/com/durian/tssparty/data/repository/TssRepository.kt @@ -3720,24 +3720,34 @@ data class ParticipantStatusInfo( * 构建签名参与方列表(辅助方法) * * @param participants 所有参与方(从 getSessionStatus 获取) + * @param currentPartyId 当前设备的 party ID * @param includeServerParties 是否包含服务器备份方(默认 false,保持现有行为) * @return 参与方列表 (partyId, partyIndex) * * 新增原因:将参与方过滤逻辑提取为可复用方法,支持选择性包含服务器 * 默认行为:false - 过滤掉 co-managed-party-*(与现有逻辑一致) - * 新行为:true - 保留所有参与方,包括服务器(仅限 2-of-3 用户主动选择) + * 新行为:true - 只包含当前设备 + 服务器(用于丢失设备场景,总共2方) */ private fun buildSigningParticipantList( participants: List, + currentPartyId: String, includeServerParties: Boolean = false ): List> { val filtered = if (includeServerParties) { - // 包含所有参与方(含服务器)- 用于 2-of-3 设备丢失恢复 - android.util.Log.d("TssRepository", "[PARTICIPANT-LIST] Including ALL parties (with server backup)") - participants + // 设备丢失场景:只选择当前设备 + 服务器(共2方,满足 t=2) + // 排除丢失的另一个用户设备 + android.util.Log.d("TssRepository", "[PARTICIPANT-LIST] Device lost mode: current device + server backup only") + participants.filter { + it.partyId == currentPartyId || it.partyId.startsWith("co-managed-party-") + }.also { + android.util.Log.d("TssRepository", "[PARTICIPANT-LIST] Selected ${it.size} parties for signing (current + server)") + it.forEach { p -> + android.util.Log.d("TssRepository", "[PARTICIPANT-LIST] - ${p.partyId.take(20)} (index=${p.partyIndex})") + } + } } else { - // 过滤掉服务器方 - 现有默认行为 - android.util.Log.d("TssRepository", "[PARTICIPANT-LIST] Excluding co-managed-party-* (default behavior)") + // 过滤掉服务器方 - 现有默认行为(2个用户设备) + android.util.Log.d("TssRepository", "[PARTICIPANT-LIST] Normal mode: excluding co-managed-party-* (default behavior)") participants.filter { !it.partyId.startsWith("co-managed-party-") } } return filtered.map { Pair(it.partyId, it.partyIndex) } @@ -3795,8 +3805,11 @@ data class ParticipantStatusInfo( // Step 2: Build participant list using helper method // 关键修改:使用辅助方法,根据 includeServerBackup 参数决定是否包含服务器 + // includeServerBackup=true 时:只选择当前设备 + 服务器(共2方,用于设备丢失场景) + // includeServerBackup=false 时:选择2个用户设备(现有默认行为) val signingParties = buildSigningParticipantList( keygenStatus.participants, + signingPartyIdForEvents, // 传入当前设备的 party ID includeServerBackup )