fix(mpc-service): 修复 MPC 会话流程,先创建会话再加入
问题:mpc-service 尝试用 identity-service 生成的 SHA256 哈希作为 joinToken 加入会话,但 session-coordinator 期望的是由它自己 CreateSession 接口生成的 JWT token。 修复: - coordinator-client.ts: 添加 createSession() 方法 - participate-keygen.handler.ts: 先创建会话获取 JWT,再加入 - participate-signing.handler.ts: 同上 - rotate-share.handler.ts: 同上(使用 keygen 类型) 流程变更: 1. CreateSession -> 获取 sessionId + JWT joinToken 2. JoinSession 使用 JWT token 加入会话 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
467206fd61
commit
e51edc2ce4
|
|
@ -163,11 +163,31 @@ export class ParticipateInKeygenHandler {
|
|||
|
||||
private async joinSession(command: ParticipateInKeygenCommand): Promise<SessionInfo> {
|
||||
try {
|
||||
return await this.coordinatorClient.joinSession({
|
||||
sessionId: command.sessionId,
|
||||
partyId: command.partyId,
|
||||
joinToken: command.joinToken,
|
||||
// First, create the session via coordinator to get a valid JWT token
|
||||
// The session-coordinator expects us to create a session first
|
||||
this.logger.log('Creating MPC session via coordinator...');
|
||||
const createResponse = await this.coordinatorClient.createSession({
|
||||
sessionType: 'keygen',
|
||||
thresholdN: 3, // Default 2-of-3 MPC
|
||||
thresholdT: 2,
|
||||
createdBy: command.partyId,
|
||||
expiresIn: 600, // 10 minutes
|
||||
});
|
||||
this.logger.log(`Session created: ${createResponse.sessionId}, now joining...`);
|
||||
|
||||
// Now join using the valid JWT token from the coordinator
|
||||
const sessionInfo = await this.coordinatorClient.joinSession({
|
||||
sessionId: createResponse.sessionId,
|
||||
partyId: command.partyId,
|
||||
joinToken: createResponse.joinToken, // Use the JWT from createSession
|
||||
});
|
||||
|
||||
// Return session info with the original session ID for consistency
|
||||
return {
|
||||
...sessionInfo,
|
||||
sessionId: createResponse.sessionId,
|
||||
joinToken: createResponse.joinToken,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new ApplicationError(
|
||||
`Failed to join session: ${error.message}`,
|
||||
|
|
|
|||
|
|
@ -167,11 +167,33 @@ export class ParticipateInSigningHandler {
|
|||
|
||||
private async joinSession(command: ParticipateInSigningCommand): Promise<SessionInfo> {
|
||||
try {
|
||||
return await this.coordinatorClient.joinSession({
|
||||
sessionId: command.sessionId,
|
||||
partyId: command.partyId,
|
||||
joinToken: command.joinToken,
|
||||
// First, create the session via coordinator to get a valid JWT token
|
||||
this.logger.log('Creating MPC signing session via coordinator...');
|
||||
const createResponse = await this.coordinatorClient.createSession({
|
||||
sessionType: 'sign',
|
||||
thresholdN: 3, // Default 2-of-3 MPC
|
||||
thresholdT: 2,
|
||||
createdBy: command.partyId,
|
||||
messageHash: command.messageHash,
|
||||
expiresIn: 300, // 5 minutes for signing
|
||||
});
|
||||
this.logger.log(`Signing session created: ${createResponse.sessionId}, now joining...`);
|
||||
|
||||
// Now join using the valid JWT token from the coordinator
|
||||
const sessionInfo = await this.coordinatorClient.joinSession({
|
||||
sessionId: createResponse.sessionId,
|
||||
partyId: command.partyId,
|
||||
joinToken: createResponse.joinToken,
|
||||
});
|
||||
|
||||
// Return session info with correct IDs and public key from command
|
||||
return {
|
||||
...sessionInfo,
|
||||
sessionId: createResponse.sessionId,
|
||||
joinToken: createResponse.joinToken,
|
||||
publicKey: command.publicKey, // Preserve public key from command
|
||||
messageHash: command.messageHash,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new ApplicationError(
|
||||
`Failed to join signing session: ${error.message}`,
|
||||
|
|
|
|||
|
|
@ -174,11 +174,31 @@ export class RotateShareHandler {
|
|||
|
||||
private async joinSession(command: RotateShareCommand): Promise<SessionInfo> {
|
||||
try {
|
||||
return await this.coordinatorClient.joinSession({
|
||||
sessionId: command.sessionId,
|
||||
partyId: command.partyId,
|
||||
joinToken: command.joinToken,
|
||||
// First, create the session via coordinator to get a valid JWT token
|
||||
// Key refresh uses 'keygen' session type (coordinator doesn't have 'refresh' type)
|
||||
this.logger.log('Creating MPC refresh session via coordinator...');
|
||||
const createResponse = await this.coordinatorClient.createSession({
|
||||
sessionType: 'keygen', // Use keygen type for key refresh
|
||||
thresholdN: 3,
|
||||
thresholdT: 2,
|
||||
createdBy: command.partyId,
|
||||
expiresIn: 600, // 10 minutes
|
||||
});
|
||||
this.logger.log(`Refresh session created: ${createResponse.sessionId}, now joining...`);
|
||||
|
||||
// Now join using the valid JWT token from the coordinator
|
||||
const sessionInfo = await this.coordinatorClient.joinSession({
|
||||
sessionId: createResponse.sessionId,
|
||||
partyId: command.partyId,
|
||||
joinToken: createResponse.joinToken,
|
||||
});
|
||||
|
||||
return {
|
||||
...sessionInfo,
|
||||
sessionId: createResponse.sessionId,
|
||||
joinToken: createResponse.joinToken,
|
||||
publicKey: command.publicKey,
|
||||
};
|
||||
} catch (error) {
|
||||
throw new ApplicationError(
|
||||
`Failed to join rotation session: ${error.message}`,
|
||||
|
|
|
|||
|
|
@ -2,12 +2,32 @@
|
|||
* MPC Coordinator Client
|
||||
*
|
||||
* Client for communicating with the external MPC Session Coordinator.
|
||||
*
|
||||
* Flow:
|
||||
* 1. CreateSession - Creates a new MPC session and returns a JWT joinToken
|
||||
* 2. JoinSession - Parties join using the JWT token
|
||||
*/
|
||||
|
||||
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
|
||||
import { ConfigService } from '@nestjs/config';
|
||||
import axios, { AxiosInstance, AxiosError } from 'axios';
|
||||
|
||||
export interface CreateSessionRequest {
|
||||
sessionType: 'keygen' | 'sign';
|
||||
thresholdN: number;
|
||||
thresholdT: number;
|
||||
createdBy: string;
|
||||
messageHash?: string;
|
||||
expiresIn?: number; // seconds
|
||||
}
|
||||
|
||||
export interface CreateSessionResponse {
|
||||
sessionId: string;
|
||||
joinToken: string; // JWT token for joining
|
||||
status: string;
|
||||
expiresAt?: number;
|
||||
}
|
||||
|
||||
export interface JoinSessionRequest {
|
||||
sessionId: string;
|
||||
partyId: string;
|
||||
|
|
@ -22,6 +42,7 @@ export interface SessionInfo {
|
|||
participants: Array<{ partyId: string; partyIndex: number }>;
|
||||
publicKey?: string;
|
||||
messageHash?: string;
|
||||
joinToken?: string; // JWT token for this session
|
||||
}
|
||||
|
||||
export interface ReportCompletionRequest {
|
||||
|
|
@ -89,7 +110,42 @@ export class MPCCoordinatorClient implements OnModuleInit {
|
|||
}
|
||||
|
||||
/**
|
||||
* Join an MPC session
|
||||
* Create an MPC session
|
||||
*
|
||||
* This must be called first to get a valid JWT joinToken
|
||||
*/
|
||||
async createSession(request: CreateSessionRequest): Promise<CreateSessionResponse> {
|
||||
this.logger.log(`Creating session: type=${request.sessionType}, ${request.thresholdT}-of-${request.thresholdN}`);
|
||||
|
||||
try {
|
||||
const response = await this.client.post('/api/v1/sessions', {
|
||||
sessionType: request.sessionType,
|
||||
thresholdN: request.thresholdN,
|
||||
thresholdT: request.thresholdT,
|
||||
createdBy: request.createdBy,
|
||||
messageHash: request.messageHash,
|
||||
expiresIn: request.expiresIn || 600, // Default 10 minutes
|
||||
});
|
||||
|
||||
this.logger.log(`Session created: ${response.data.sessionId}`);
|
||||
|
||||
return {
|
||||
sessionId: response.data.sessionId,
|
||||
joinToken: response.data.joinToken,
|
||||
status: response.data.status,
|
||||
expiresAt: response.data.expiresAt,
|
||||
};
|
||||
} catch (error) {
|
||||
const message = this.getErrorMessage(error);
|
||||
this.logger.error(`Failed to create session: ${message}`);
|
||||
throw new Error(`Failed to create MPC session: ${message}`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Join an MPC session using a JWT token
|
||||
*
|
||||
* The joinToken must be obtained from createSession()
|
||||
*/
|
||||
async joinSession(request: JoinSessionRequest): Promise<SessionInfo> {
|
||||
this.logger.log(`Joining session: ${request.sessionId}`);
|
||||
|
|
@ -114,6 +170,7 @@ export class MPCCoordinatorClient implements OnModuleInit {
|
|||
})) || [],
|
||||
publicKey: undefined,
|
||||
messageHash: undefined,
|
||||
joinToken: request.joinToken,
|
||||
};
|
||||
} catch (error) {
|
||||
const message = this.getErrorMessage(error);
|
||||
|
|
|
|||
Loading…
Reference in New Issue