fix(android): 修正2-of-3服务器备份参与方选择逻辑

问题描述:
之前的实现在勾选"包含服务器备份"时,会选择全部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 <noreply@anthropic.com>
This commit is contained in:
hailin 2026-01-26 18:11:17 -08:00
parent 0eea1815ae
commit dbeef9f415
1 changed files with 19 additions and 6 deletions

View File

@ -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<ParticipantStatusInfo>,
currentPartyId: String,
includeServerParties: Boolean = false
): List<Pair<String, Int>> {
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
)