【架构安全修复 - ViewModel 层协程异常处理】 ## 问题背景 MainViewModel 使用的 viewModelScope 没有配置 CoroutineExceptionHandler: - 未捕获的异常会导致应用崩溃 - 用户操作触发的异常体验最差 - 有 29 处 viewModelScope.launch 调用都存在风险 ## 修复方案 ### 1. 添加 safeLaunch 辅助函数 创建一个扩展函数自动捕获异常: ### 2. 替换关键的 viewModelScope.launch 将 14 个最关键的用户交互点改为使用 safeLaunch: **已修复的函数:** 1. checkAllServices() - 服务初始化检查 2. connectToServer() - 连接服务器 3. createKeygenSession() - 创建密钥生成会话 4. validateInviteCode() - 验证邀请码 5. joinKeygen() - 加入密钥生成 6. joinSign() - 加入签名 7. initiateSignSession() - 发起签名会话 8. initiateSignSessionWithOptions() - 发起签名(带选项) 9. startSigningProcess() - 启动签名过程 10. prepareTransfer() - 准备转账 11. broadcastTransaction() - 广播交易 12. exportShareBackup() - 导出备份 13. importShareBackup() - 导入备份 14. confirmTransactionInBackground() - 后台确认交易 ## 修复的崩溃场景 ### 场景 1: 网络请求失败 - 原问题: 用户点击"创建钱包"时网络异常 - 修复前: 应用直接崩溃 ❌ - 修复后: 显示"网络错误"提示,应用继续运行 ✅ ### 场景 2: 参数验证失败 - 原问题: 邀请码格式错误抛出 IllegalArgumentException - 修复前: 应用崩溃 ❌ - 修复后: 显示"参数错误"提示 ✅ ### 场景 3: 状态不一致 - 原问题: 快速切换页面导致状态异常 - 修复前: 应用崩溃,用户丢失数据 ❌ - 修复后: 显示错误提示,状态可恢复 ✅ ### 场景 4: JSON 解析失败 - 原问题: 导入损坏的备份文件 - 修复前: 应用崩溃 ❌ - 修复后: 显示"导入失败"提示 ✅ ## 双重保护机制 现在有两层保护: 1. **内层 try-catch** - 函数内部的具体业务异常处理 2. **外层 safeLaunch** - 捕获所有未处理的异常,防止崩溃 示例: ## 异常分类处理 根据异常类型提供友好的错误提示: - SocketTimeoutException → "网络超时,请检查网络连接" - UnknownHostException → "无法连接到服务器,请检查网络设置" - IOException → "网络错误: {message}" - IllegalStateException → "状态错误: {message}" - IllegalArgumentException → "参数错误: {message}" - 其他异常 → "操作失败: {message}" ## 影响范围 ### 修改的代码位置 - MainViewModel.kt - 添加 safeLaunch 函数 - 14 个关键用户交互函数 - 替换 viewModelScope.launch 为 safeLaunch ### 行为变化 - BEFORE: 协程中未捕获异常导致应用崩溃 - AFTER: 异常被捕获,显示错误提示,应用继续运行 ### 完全向后兼容 - 所有现有的 try-catch 逻辑保持不变 - 仅在异常未被捕获时才触发 safeLaunch 的处理 - 不影响正常的业务流程 ## 测试验证 编译状态: ✅ BUILD SUCCESSFUL in 29s - 无编译错误 - 仅有警告 (unused parameters),不影响功能 ## 与 TssRepository 形成完整防护 现在有两层完整的异常保护: 1. **TssRepository 层** - 后台协程的异常处理 (CoroutineExceptionHandler) 2. **MainViewModel 层** - UI 交互的异常处理 (safeLaunch) 用户操作流程: 用户点击按钮 → MainViewModel.safeLaunch (外层保护) ↓ Repository 调用 → repositoryScope (后台保护) ↓ 双重保护,极大降低崩溃风险 Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> |
||
|---|---|---|
| .. | ||
| app | ||
| contracts | ||
| gradle/wrapper | ||
| tsslib | ||
| .gitignore | ||
| IMPLEMENTATION_PLAN.md | ||
| README.md | ||
| build-apk.bat | ||
| build.gradle.kts | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| settings.gradle.kts | ||
README.md
TSS Party Android
Android 版本的 TSS (Threshold Signature Scheme) Party 应用,用于多方共管钱包的密钥生成和签名。
项目结构
service-party-android/
├── app/ # Android 应用模块
│ ├── src/main/
│ │ ├── java/com/durian/tssparty/
│ │ │ ├── data/ # 数据层
│ │ │ │ ├── local/ # 本地存储 (Room, TSS Bridge)
│ │ │ │ ├── remote/ # 远程通信 (gRPC)
│ │ │ │ └── repository/ # 数据仓库
│ │ │ ├── domain/model/ # 领域模型
│ │ │ ├── presentation/ # UI 层
│ │ │ │ ├── screens/ # Compose 屏幕
│ │ │ │ └── viewmodel/ # ViewModels
│ │ │ ├── di/ # Hilt 依赖注入
│ │ │ ├── ui/theme/ # Material Theme
│ │ │ └── util/ # 工具类
│ │ ├── proto/ # gRPC Proto 文件
│ │ └── res/ # Android 资源
│ └── libs/ # TSS 原生库 (.aar)
├── tsslib/ # Go TSS 库源码
│ ├── tsslib.go # gomobile 绑定
│ ├── go.mod
│ ├── build.sh # Linux/macOS 构建脚本
│ └── build.bat # Windows 构建脚本
└── gradle/ # Gradle Wrapper
技术栈
- UI: Jetpack Compose + Material 3
- 架构: MVVM + Repository Pattern
- 依赖注入: Hilt
- 数据库: Room
- 网络: gRPC (protobuf-lite)
- TSS 核心: Go + gomobile (BnB Chain tss-lib v2)
构建步骤
1. 构建 TSS 原生库 (可选,需要 Go 环境)
# 安装 gomobile
go install golang.org/x/mobile/cmd/gomobile@latest
gomobile init
# 构建 Android AAR
cd tsslib
./build.sh # Linux/macOS
# 或
build.bat # Windows
这将在 app/libs/ 生成 tsslib.aar。
注意: 当前版本使用 Kotlin stub 实现,无需编译 Go 库即可构建 APK。 实际运行需要真正的
tsslib.aar。
2. 构建 APK
# Debug 版本
./gradlew assembleDebug
# Release 版本 (需要签名配置)
./gradlew assembleRelease
APK 输出路径: app/build/outputs/apk/debug/app-debug.apk
功能
- 加入 Keygen 会话 - 扫描/输入邀请码,参与多方密钥生成
- 查看钱包 - 显示已创建的共管钱包列表
- 签名交易 - 使用密钥份额参与多方签名
- 设置 - 配置 Message Router 服务器地址
配置
默认服务器配置:
- Message Router:
localhost:50051 - Kava RPC:
https://evm.kava.io
与 Electron 版本的对应关系
| Electron 版本 | Android 版本 |
|---|---|
electron/main.ts |
TssNativeBridge.kt + GrpcClient.kt |
electron/preload.ts |
TssRepository.kt |
src/pages/*.tsx |
presentation/screens/*.kt |
tss-party/ (Go 子进程) |
tsslib/ (gomobile .aar) |
| sql.js | Room Database |
许可证
MIT