fix(sign): fetch partyIndex from Account Service instead of local storage
- Query keygen session status to get correct party_index for signing - Keep original design: don't save partyIndex locally during keygen - Add parties to createSignSession response - Make partyIndex optional in database type definitions - Transfer.tsx: use signParties from createSignSession response 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
454e596d40
commit
b79289bc29
|
|
@ -574,17 +574,18 @@ func (h *CoManagedHTTPHandler) CreateSignSession(c *gin.Context) {
|
|||
zap.Int("num_parties", len(resp.SelectedParties)))
|
||||
|
||||
c.JSON(http.StatusCreated, gin.H{
|
||||
"session_id": resp.SessionID,
|
||||
"keygen_session_id": req.KeygenSessionID,
|
||||
"wallet_name": req.WalletName,
|
||||
"invite_code": inviteCode,
|
||||
"join_token": wildcardToken,
|
||||
"threshold_t": req.ThresholdT,
|
||||
"selected_parties": resp.SelectedParties,
|
||||
"status": "waiting_for_participants",
|
||||
"current_participants": 0,
|
||||
"session_id": resp.SessionID,
|
||||
"keygen_session_id": req.KeygenSessionID,
|
||||
"wallet_name": req.WalletName,
|
||||
"invite_code": inviteCode,
|
||||
"join_token": wildcardToken,
|
||||
"threshold_t": req.ThresholdT,
|
||||
"parties": req.Parties, // 返回完整的 parties (包含 party_id 和 party_index)
|
||||
"selected_parties": resp.SelectedParties,
|
||||
"status": "waiting_for_participants",
|
||||
"current_participants": 0,
|
||||
"required_participants": len(req.Parties),
|
||||
"expires_at": resp.ExpiresAt,
|
||||
"expires_at": resp.ExpiresAt,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -564,10 +564,10 @@ async function handleKeygenComplete(result: KeygenResult) {
|
|||
try {
|
||||
// 1. 保存 share 到本地数据库
|
||||
const publicKeyHex = result.publicKey.toString('hex');
|
||||
// 转换 participants 格式:保存 partyId, partyIndex, name
|
||||
// 转换 participants 格式:从 { partyId, partyIndex, name } 到 { partyId, name }
|
||||
// 注意:partyIndex 不保存到本地,签名时需要从 Account Service 获取
|
||||
const participantsForSave = activeKeygenSession.participants.map(p => ({
|
||||
partyId: p.partyId,
|
||||
partyIndex: p.partyIndex,
|
||||
name: p.name,
|
||||
}));
|
||||
const saved = database.saveShare({
|
||||
|
|
@ -1219,11 +1219,16 @@ function setupIpcHandlers() {
|
|||
return { success: false, error: 'Share not found or incorrect password' };
|
||||
}
|
||||
|
||||
// 解析 participants_json 获取参与方列表
|
||||
const participants = JSON.parse(share.participants_json || '[]');
|
||||
const parties = participants.map((p: { partyId: string; partyIndex?: number }, index: number) => ({
|
||||
party_id: p.partyId,
|
||||
party_index: p.partyIndex ?? index, // 优先使用保存的 partyIndex,否则使用数组索引
|
||||
// 从 Account Service 查询 keygen session 获取正确的 participants(包含 party_index)
|
||||
const sessionStatus = await accountClient?.getSessionStatus(share.session_id);
|
||||
if (!sessionStatus?.participants || sessionStatus.participants.length === 0) {
|
||||
return { success: false, error: 'Failed to get participants from keygen session' };
|
||||
}
|
||||
|
||||
// 使用后端返回的 participants(包含正确的 party_index)
|
||||
const parties = sessionStatus.participants.map(p => ({
|
||||
party_id: p.party_id,
|
||||
party_index: p.party_index,
|
||||
}));
|
||||
|
||||
const result = await accountClient?.createSignSession({
|
||||
|
|
@ -1241,6 +1246,7 @@ function setupIpcHandlers() {
|
|||
inviteCode: result?.invite_code,
|
||||
expiresAt: result?.expires_at,
|
||||
joinToken: result?.join_token,
|
||||
parties: result?.parties, // 包含正确的 party_id 和 party_index
|
||||
};
|
||||
} catch (error) {
|
||||
return { success: false, error: (error as Error).message };
|
||||
|
|
|
|||
|
|
@ -339,7 +339,7 @@ export class DatabaseManager {
|
|||
thresholdN: number;
|
||||
publicKeyHex: string;
|
||||
rawShare: string;
|
||||
participants: Array<{ partyId: string; name: string }>;
|
||||
participants: Array<{ partyId: string; partyIndex?: number; name: string }>;
|
||||
}, password: string): ShareRecord {
|
||||
if (!this.db) throw new Error('Database not initialized');
|
||||
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@ export default function Transfer() {
|
|||
// 签名会话
|
||||
const [inviteCode, setInviteCode] = useState('');
|
||||
const [signSessionId, setSignSessionId] = useState('');
|
||||
const [signParties, setSignParties] = useState<Array<{ party_id: string; party_index: number }>>([]);
|
||||
|
||||
// 错误信息
|
||||
const [error, setError] = useState('');
|
||||
|
|
@ -215,6 +216,7 @@ export default function Transfer() {
|
|||
|
||||
setInviteCode(result.inviteCode || '');
|
||||
setSignSessionId(result.sessionId || '');
|
||||
setSignParties(result.parties || []);
|
||||
setTxHash(messageHash);
|
||||
|
||||
// 显示邀请码,等待用户通知其他参与方
|
||||
|
|
@ -231,11 +233,17 @@ export default function Transfer() {
|
|||
if (!txParams || !share || !txHash || !signSessionId) return;
|
||||
|
||||
try {
|
||||
// 构建 participants 列表
|
||||
const participants = (share.participants || []).map((p, index) => ({
|
||||
partyId: p.partyId,
|
||||
partyIndex: p.partyIndex ?? index, // 优先使用保存的 partyIndex
|
||||
}));
|
||||
// 使用创建签名会话时返回的 parties(包含正确的 party_index)
|
||||
// 如果没有,则 fallback 到本地 share 的 participants
|
||||
const participants = signParties.length > 0
|
||||
? signParties.map(p => ({
|
||||
partyId: p.party_id,
|
||||
partyIndex: p.party_index,
|
||||
}))
|
||||
: (share.participants || []).map((p, index) => ({
|
||||
partyId: p.partyId,
|
||||
partyIndex: p.partyIndex ?? index,
|
||||
}));
|
||||
|
||||
// 执行 TSS 签名
|
||||
if (window.electronAPI) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue