fix(mpc-system): GetSessionStatus API 返回 threshold_t 和 threshold_n

问题:
- Account 服务的 GetSessionStatus HTTP API 没有返回 threshold 字段
- 导致 service-party-app 获取到的 threshold 始终是 0
- TSS keygen 无法使用正确的阈值参数

修复:
- Account gRPC client 添加 ThresholdT 和 ThresholdN 字段映射
- Account HTTP handler 返回 threshold_t 和 threshold_n
- service-party-app 优先使用后端返回的 threshold 值
- checkAndTriggerKeygen 使用后端 threshold 更新 activeKeygenSession

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
hailin 2025-12-29 12:43:59 -08:00
parent fb1b27e36f
commit 674bc9e5cd
4 changed files with 23 additions and 6 deletions

View File

@ -314,6 +314,8 @@ func (h *CoManagedHTTPHandler) GetSessionStatus(c *gin.Context) {
"session_id": sessionID,
"status": resp.Status,
"session_type": resp.SessionType,
"threshold_t": resp.ThresholdT,
"threshold_n": resp.ThresholdN,
"completed_parties": resp.CompletedParties,
"total_parties": resp.TotalParties,
}

View File

@ -225,6 +225,8 @@ func (c *SessionCoordinatorClient) GetSessionStatus(
Status: resp.Status,
CompletedParties: resp.CompletedParties,
TotalParties: resp.TotalParties,
ThresholdT: resp.ThresholdT,
ThresholdN: resp.ThresholdN,
SessionType: resp.SessionType,
PublicKey: resp.PublicKey,
Signature: resp.Signature,
@ -293,6 +295,8 @@ type SessionStatusResponse struct {
Status string
CompletedParties int32
TotalParties int32
ThresholdT int32 // Minimum parties needed to sign (e.g., 2 in 2-of-3)
ThresholdN int32 // Total number of parties required (e.g., 3 in 2-of-3)
SessionType string // "keygen" or "sign"
PublicKey []byte
Signature []byte

View File

@ -166,10 +166,13 @@ async function checkAndTriggerKeygen(sessionId: string) {
continue;
}
const expectedN = status.total_parties || activeKeygenSession.threshold.n;
// 优先使用后端返回的 threshold 值
const thresholdN = status.threshold_n || status.total_parties || activeKeygenSession.threshold.n;
const thresholdT = status.threshold_t || activeKeygenSession.threshold.t;
const expectedN = thresholdN;
const currentParticipants = status.participants?.length || 0;
debugLog.debug('main', `Session ${sessionId} status: ${status.status}, participants: ${currentParticipants}/${expectedN}`);
debugLog.debug('main', `Session ${sessionId} status: ${status.status}, participants: ${currentParticipants}/${expectedN}, threshold: ${thresholdT}-of-${thresholdN}`);
// 检查是否满足启动条件
const hasAllParticipants = currentParticipants >= expectedN;
@ -207,13 +210,16 @@ async function checkAndTriggerKeygen(sessionId: string) {
})))}`);
}
// 更新 activeKeygenSession 的 threshold使用后端返回的正确值
activeKeygenSession.threshold = { t: thresholdT, n: thresholdN };
const selectedParties = activeKeygenSession.participants.map(p => p.partyId);
await handleSessionStart({
eventType: 'session_started',
sessionId: sessionId,
thresholdN: activeKeygenSession.threshold.n,
thresholdT: activeKeygenSession.threshold.t,
thresholdN: thresholdN,
thresholdT: thresholdT,
selectedParties: selectedParties,
});
@ -869,8 +875,11 @@ function setupIpcHandlers() {
ipcMain.handle('grpc:getSessionStatus', async (_event, { sessionId }) => {
try {
const result = await accountClient?.getSessionStatus(sessionId);
// 从 activeKeygenSession 获取更完整的信息
const threshold = activeKeygenSession?.threshold || { t: 0, n: result?.total_parties || 0 };
// 优先使用后端返回的 threshold否则从 activeKeygenSession 获取
const threshold = {
t: result?.threshold_t || activeKeygenSession?.threshold?.t || 0,
n: result?.threshold_n || result?.total_parties || activeKeygenSession?.threshold?.n || 0,
};
const participants = result?.participants?.map((p, idx) => ({
partyId: p.party_id,
partyIndex: p.party_index,

View File

@ -73,6 +73,8 @@ export interface ParticipantStatusInfo {
export interface GetSessionStatusResponse {
session_id: string;
status: string;
threshold_t: number; // Minimum parties needed to sign (e.g., 2 in 2-of-3)
threshold_n: number; // Total number of parties required (e.g., 3 in 2-of-3)
completed_parties: number;
total_parties: number;
session_type: string;