feat(tss): add real-time round progress from msg.Type() parsing

Extract current round number from tss-lib message type string using
regex pattern `Round(\d+)`. This enables real-time progress updates
(1/4, 2/4... for keygen, 1/9, 2/9... for signing) instead of only
showing completion status.

Changes across all three platforms:
- tss-wasm/main.go: Add extractRoundFromMessageType() and call
  OnProgress with parsed round on each outgoing message
- service-party-android/tsslib/tsslib.go: Same implementation for
  Android gomobile binding
- service-party-app/tss-party/main.go: Same implementation for
  Electron subprocess, with isKeygen parameter to distinguish
  keygen (4 rounds) vs signing (9 rounds)

Safe fallback: Returns 0 if parsing fails, which doesn't affect
protocol execution - only UI display.

🤖 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 2026-01-01 22:41:51 -08:00
parent f8de55e671
commit 2365a50b1b
3 changed files with 83 additions and 6 deletions

View File

@ -11,6 +11,8 @@ import (
"encoding/json"
"fmt"
"math/big"
"regexp"
"strconv"
"sync"
"time"
@ -20,6 +22,11 @@ import (
"github.com/bnb-chain/tss-lib/v2/tss"
)
// Regex to extract round number from tss-lib message type
// Message types look like: "binance.tsslib.ecdsa.keygen.KGRound1Message"
// or "binance.tsslib.ecdsa.signing.SignRound3Message"
var roundRegex = regexp.MustCompile(`Round(\d+)`)
// MessageCallback is the interface for receiving TSS protocol messages
// Android side implements this interface to handle message routing
type MessageCallback interface {
@ -531,6 +538,19 @@ func CancelSession() {
}
}
// extractRoundFromMessageType parses the round number from a tss-lib message type string.
// Returns 0 if parsing fails (safe fallback).
// Example: "binance.tsslib.ecdsa.keygen.KGRound2Message1" -> 2
func extractRoundFromMessageType(msgType string) int {
matches := roundRegex.FindStringSubmatch(msgType)
if len(matches) >= 2 {
if round, err := strconv.Atoi(matches[1]); err == nil {
return round
}
}
return 0 // Safe fallback - doesn't affect protocol, just shows 0 in UI
}
func (s *tssSession) handleOutgoingMessage(msg tss.Message) {
msgBytes, _, err := msg.WireBytes()
if err != nil {
@ -558,6 +578,14 @@ func (s *tssSession) handleOutgoingMessage(msg tss.Message) {
data, _ := json.Marshal(outMsg)
s.callback.OnOutgoingMessage(string(data))
// Extract current round from message type and send progress update
totalRounds := 4 // GG20 keygen has 4 rounds
if !s.isKeygen {
totalRounds = 9 // GG20 signing has 9 rounds
}
currentRound := extractRoundFromMessageType(msg.Type())
s.callback.OnProgress(currentRound, totalRounds)
}
func isDuplicateError(err error) bool {

View File

@ -15,6 +15,8 @@ import (
"math/big"
"os"
"os/signal"
"regexp"
"strconv"
"sync"
"syscall"
"time"
@ -25,6 +27,11 @@ import (
"github.com/bnb-chain/tss-lib/v2/tss"
)
// Regex to extract round number from tss-lib message type
// Message types look like: "binance.tsslib.ecdsa.keygen.KGRound1Message"
// or "binance.tsslib.ecdsa.signing.SignRound3Message"
var roundRegex = regexp.MustCompile(`Round(\d+)`)
// Message types for IPC
type Message struct {
Type string `json:"type"`
@ -290,7 +297,7 @@ func executeKeygen(
if !ok {
return
}
handleOutgoingMessage(msg)
handleOutgoingMessage(msg, true) // isKeygen = true
}
}
}()
@ -321,7 +328,7 @@ func executeKeygen(
}
}()
// Track progress
// Track progress (final completion reporting)
totalRounds := 4 // GG20 keygen has 4 rounds
// Wait for completion
@ -357,7 +364,20 @@ func executeKeygen(
}
}
func handleOutgoingMessage(msg tss.Message) {
// extractRoundFromMessageType parses the round number from a tss-lib message type string.
// Returns 0 if parsing fails (safe fallback).
// Example: "binance.tsslib.ecdsa.keygen.KGRound2Message1" -> 2
func extractRoundFromMessageType(msgType string) int {
matches := roundRegex.FindStringSubmatch(msgType)
if len(matches) >= 2 {
if round, err := strconv.Atoi(matches[1]); err == nil {
return round
}
}
return 0 // Safe fallback - doesn't affect protocol, just shows 0 in UI
}
func handleOutgoingMessage(msg tss.Message, isKeygen bool) {
msgBytes, _, err := msg.WireBytes()
if err != nil {
return
@ -379,6 +399,14 @@ func handleOutgoingMessage(msg tss.Message) {
data, _ := json.Marshal(outMsg)
fmt.Println(string(data))
// Extract current round from message type and send progress update
totalRounds := 4 // GG20 keygen has 4 rounds
if !isKeygen {
totalRounds = 9 // GG20 signing has 9 rounds
}
currentRound := extractRoundFromMessageType(msg.Type())
sendProgress(currentRound, totalRounds)
}
func handleIncomingMessage(
@ -682,7 +710,7 @@ func executeSign(
if !ok {
return
}
handleOutgoingMessage(msg)
handleOutgoingMessage(msg, false) // isKeygen = false (signing)
}
}
}()

View File

@ -10,6 +10,8 @@ import (
"encoding/json"
"fmt"
"math/big"
"regexp"
"strconv"
"sync"
"syscall/js"
@ -19,6 +21,11 @@ import (
"github.com/bnb-chain/tss-lib/v2/tss"
)
// Regex to extract round number from tss-lib message type
// Message types look like: "binance.tsslib.ecdsa.keygen.KGRound1Message"
// or "binance.tsslib.ecdsa.signing.SignRound3Message"
var roundRegex = regexp.MustCompile(`Round(\d+)`)
// Global state for active sessions
var (
activeSessions = make(map[string]*TSSSession)
@ -401,6 +408,19 @@ func stopSession(this js.Value, args []js.Value) interface{} {
return createSuccessResult(nil)
}
// extractRoundFromMessageType parses the round number from a tss-lib message type string.
// Returns 0 if parsing fails (safe fallback).
// Example: "binance.tsslib.ecdsa.keygen.KGRound2Message1" -> 2
func extractRoundFromMessageType(msgType string) int {
matches := roundRegex.FindStringSubmatch(msgType)
if len(matches) >= 2 {
if round, err := strconv.Atoi(matches[1]); err == nil {
return round
}
}
return 0 // Safe fallback - doesn't affect protocol, just shows 0 in UI
}
// handleOutgoingMessages processes messages from the TSS protocol
func (s *TSSSession) handleOutgoingMessages() {
totalRounds := 4 // GG20 keygen has 4 rounds
@ -440,8 +460,9 @@ func (s *TSSSession) handleOutgoingMessages() {
jsMsgJSON, _ := json.Marshal(jsMsg)
s.OnMessage.Invoke(string(jsMsgJSON))
// Send progress update
s.OnProgress.Invoke(totalRounds, totalRounds) // Simplified progress
// Extract current round from message type and send progress update
currentRound := extractRoundFromMessageType(msg.Type())
s.OnProgress.Invoke(currentRound, totalRounds)
}
}
}