Commit Graph

2110 Commits

Author SHA1 Message Date
hailin f9619b7df1 fix(participate_signing): 恢复 Execute 方法的 UserShareData 分支
关键修复:
- Execute 方法完全恢复原有逻辑(不重构、不委托)
- 保留 UserShareData 分支(delegate party - Android 客户端)
- 保留 Persistent party 分支(从数据库加载)
- executeWithSessionInfo 独立实现(仅供 ExecuteWithSessionInfo 调用)

影响分析:
 Android 客户端(delegate party): 现在可以正常签名
 server-party (persistent party): 不受影响
 server-party-co-managed: 使用 ExecuteWithSessionInfo(persistent only)

破坏性变更已修复:
- 之前的实现删除了 UserShareData 分支
- 导致 Android 客户端签名会失败(强制从数据库加载不存在的 share)
- 现在已完全恢复

架构原则:
- Execute: 完整保留原有逻辑(delegate + persistent)
- ExecuteWithSessionInfo: 独立方法(仅 persistent - 供 co-managed 使用)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 19:00:52 -08:00
hailin 514722143f docs(co-managed): co-sign 实施详细备注和回滚方法
## 提交信息
- 功能提交: ad4549e7
- 回滚目标: dbeef9f4

## 修改文件
1. services/server-party/application/use_cases/participate_signing.go
   - 新增 ExecuteWithSessionInfo 方法(Line 66-88)
   - 重构 Execute 委托给 executeWithSessionInfo(Line 90-107)
   - 新增 executeWithSessionInfo 私有方法(Line 109-241)

2. services/server-party-co-managed/cmd/server/main.go
   - 初始化 participateSigningUC(Line 152-156)
   - 传递 participateSigningUC 参数(Line 205)
   - 更新函数签名(Line 322-328)
   - session_created: 移除签名拒绝,添加 2-of-3 检查(Line 361-383)
   - session_started: 根据 messageHash 判断 keygen/sign(Line 420-505)

## 架构原则
 100% 寄生 server-party 的 use_cases(与 co-keygen 一致)
 不影响 server-party 现有功能
 仅支持 2-of-3 配置
 向后兼容(KeygenSessionID fallback)

## 回滚方法

### 方法 1: 完全回滚(推荐)
git reset --hard dbeef9f4
git push origin main --force

### 方法 2: 选择性回滚(保留 Android)
cd services/server-party/application/use_cases
git checkout dbeef9f4 -- participate_signing.go
cd ../../../server-party-co-managed/cmd/server
git checkout dbeef9f4 -- main.go
git commit -m "revert: 回滚 co-sign 后端"
git push origin main

### 方法 3: 手动回滚代码修改点

participate_signing.go:
1. 删除 ExecuteWithSessionInfo(Line 66-88)
2. 删除 executeWithSessionInfo(Line 109-241)
3. 恢复 Execute 原有实现(不委托)

server-party-co-managed/main.go:
1. 删除 participateSigningUC 初始化(Line 152-156)
2. 移除 participateSigningUC 参数(Line 205, 328)
3. session_created 恢复拒绝逻辑:
   if len(event.MessageHash) > 0 {
       logger.Debug("Ignoring sign session")
       return
   }
4. session_started 移除 isSignSession 判断,只保留 keygen 分支

## 部署验证
编译测试:  go build 成功
功能测试: 待部署后验证
日志关键字: "co_managed_sign", "Sign session detected (2-of-3)"

## 已知风险
- Android UI 已存在,后端未部署会导致功能不可用
- 用户勾选"包含服务器备份"会永久等待(不会丢失资产)
- 需要重启 server-party-co-managed 服务

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 18:55:32 -08:00
hailin ad4549e767 feat(co-managed): 支持 2-of-3 服务器参与签名功能
修改内容:
1. participate_signing.go: 添加 ExecuteWithSessionInfo 方法
   - 新增方法供 server-party-co-managed 调用
   - 跳过 JoinSession 步骤(已在 session_created 阶段完成)
   - 将核心逻辑提取到 executeWithSessionInfo 共享方法

2. server-party-co-managed/main.go: 完整实现 co-sign 支持
   - 初始化 participateSigningUC
   - session_created: 移除签名会话拒绝逻辑,添加 2-of-3 安全检查
   - session_started: 根据 messageHash 判断 keygen/sign 并调用对应 use case

功能特性:
-  仅支持 2-of-3 配置的签名会话
-  100% 寄生 server-party 的 use_cases(与 co-keygen 架构一致)
-  不影响现有 server-party 功能
-  完整的两阶段事件处理(session_created + session_started)

安全限制:
- 仅当 threshold_t=2 且 threshold_n=3 时参与签名
- 其他配置(3-of-5, 4-of-7等)会被拒绝

测试:
-  server-party-co-managed 编译成功

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 18:53:38 -08:00
hailin dbeef9f415 fix(android): 修正2-of-3服务器备份参与方选择逻辑
问题描述:
之前的实现在勾选"包含服务器备份"时,会选择全部3个参与方
(2个用户设备 + 1个服务器),导致后端报错:
"need exactly 2 parties for threshold 2, got 3"

根本原因:
buildSigningParticipantList() 方法在 includeServerParties=true 时,
返回了所有参与方,没有排除丢失的设备。

修复内容:
1. buildSigningParticipantList() 新增 currentPartyId 参数
2. includeServerBackup=true 时的新逻辑:
   - 只选择当前设备 (currentPartyId)
   - 加上服务器方 (co-managed-party-*)
   - 排除另一个丢失的用户设备
   - 总共正好 2 个参与方,满足 threshold t=2
3. 增强调试日志:
   - [PARTICIPANT-LIST] Device lost mode
   - Selected X parties for signing

测试场景:
- 不勾选:2个用户设备参与(默认行为)
- 勾选:1个当前设备 + 1个服务器 = 2方(设备丢失场景)

修改文件:
- TssRepository.kt (lines 3719-3744, 3796-3804)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 18:11:17 -08:00
hailin 0eea1815ae feat(android): 实现 2-of-3 钱包服务器备份参与签名功能
目的:允许 2-of-3 MPC 用户在丢失一个设备时,使用服务器备份参与签名转出资产
实现方式:纯新增代码,不修改现有逻辑,保持完全向后兼容

详细修改:

1. TssRepository.kt (新增 256 行)
   - 新增 buildSigningParticipantList() 辅助方法 (lines 3715-3743)
     * 根据 includeServerParties 参数决定是否包含服务器方
     * 默认 false,保持现有行为
   - 新增 createSignSessionWithOptions() 方法 (lines 3746-3959)
     * 完整复制 createSignSession 逻辑
     * 使用辅助方法构建参与方列表
     * 支持 includeServerBackup 参数
   - 详细日志标记: [CO-SIGN-OPTIONS]

2. MainViewModel.kt (新增 72 行)
   - 新增 initiateSignSessionWithOptions() 方法 (lines 1387-1467)
     * 调用 repository.createSignSessionWithOptions()
     * 处理签名会话创建和自动加入逻辑
     * 保留原有 initiateSignSession() 方法不变
   - 详细日志标记: [SIGN-OPTIONS]

3. TransferScreen.kt (新增 47 行)
   - 修改 onConfirmTransaction 回调: () -> Unit 改为 (Boolean) -> Unit
   - 在 TransferConfirmScreen 中新增复选框 UI (lines 736-776)
     * 仅在 2-of-3 时显示 (wallet.thresholdT == 2 && wallet.thresholdN == 3)
     * 主文本: "包含服务器备份参与签名"
     * 说明文本: "如果您丢失了一个设备,勾选此项以使用服务器备份完成签名"
   - 传递 checkbox 状态到回调

4. MainActivity.kt (新增 10 行)
   - 更新 onConfirmTransaction 回调接受 Boolean 参数
   - 条件调用:
     * includeServerBackup = true: 调用 initiateSignSessionWithOptions()
     * includeServerBackup = false: 调用 initiateSignSession() (原逻辑)

5. IMPLEMENTATION_PLAN.md (新增文件)
   - 详细记录实施方案、安全限制、测试场景
   - 包含完整的回滚方法

核心设计:

安全限制:
- 仅 2-of-3 配置显示选项
- 其他配置 (3-of-5, 4-of-7 等) 不显示
- 需要用户主动勾选,明确操作意图
- 服务器只有 1 个 key < t=2,无法单独控制钱包

向后兼容:
- 默认行为完全不变 (includeServerBackup = false)
- 不勾选或非 2-of-3 时使用原有方法
- 所有现有方法保持不变,无任何修改

代码特点:
- 所有新增代码都有详细中文注释
- 标注 "【新增】" 或 "新增参数" 便于识别
- 说明目的、安全性、回滚方法
- 详细的调试日志 ([CO-SIGN-OPTIONS], [SIGN-OPTIONS])

测试场景:

1. 2-of-3 正常使用 (不勾选)
   - 设备A + 设备B 签名 
   - 服务器被过滤 (现有行为)

2. 2-of-3 设备丢失 (勾选)
   - 设备A + 服务器 签名 
   - 用户明确勾选 "包含服务器备份"

3. 3-of-5 配置
   - 不显示复选框 
   - 保持现有行为

回滚方法:

按以下顺序删除新增代码即可完全回滚:
1. MainActivity.kt: lines 365-377 恢复为简单调用
2. TransferScreen.kt: 删除 checkbox UI (lines 736-776) 和参数修改
3. MainViewModel.kt: lines 1387-1467 删除新方法
4. TssRepository.kt: lines 3715-3960 删除新方法和辅助方法
5. 删除 IMPLEMENTATION_PLAN.md

编译状态:
 Kotlin 编译通过 (BUILD SUCCESSFUL in 1m 8s)
 无编译错误
 待运行时测试验证服务器 party ID 格式和在线状态

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 17:32:36 -08:00
hailin 0b22928d9a fix(android): 添加交易记录保存的错误处理
修复问题:
- saveTransactionRecord() 调用没有错误处理,保存失败会静默
- 如果保存失败,交易已广播但没有本地记录

改进:
- 添加 try-catch 捕获保存异常
- 保存失败时提示用户"交易已广播但保存记录失败"
- 添加成功日志便于调试

影响:
- 确保本地发起的交易 100% 被记录或提示失败原因

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 09:19:43 -08:00
hailin 656f75a4d1 fix(android): 使用 Kavascan Etherscan API 同步交易记录
替换之前的 BlockScout v2 API(返回404)为 Kavascan 的 Etherscan 兼容 API:
- action=tokentx: 获取 ERC-20 代币交易
- action=txlist: 获取原生 KAVA 交易

优势:
- 一次请求获取所有历史交易,无需分批扫描区块
- 速度快(<5秒 vs 之前的30-45秒)
- API 稳定可靠

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 08:51:40 -08:00
hailin d974fddda5 feat(android): 使用 Kavascan BlockScout API 同步交易记录
替换慢速的 eth_getLogs 区块扫描方案为官方推荐的 BlockScout REST API:
- 使用 /api/v2/addresses/{address}/transactions 端点
- 一次性获取所有交易历史(自动分页)
- 支持 ERC-20 代币转账和原生 KAVA 转账
- 从 30-45 秒优化到 < 5 秒
- 解析 token_transfers 字段识别代币类型
- 根据合约地址映射到 GREEN_POINTS/ENERGY_POINTS/FUTURE_POINTS

参考: https://kavascan.com/api-docs
       https://docs.blockscout.com/devs/apis/rest

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 08:36:33 -08:00
hailin 144d28238e perf(android): 优化交易记录同步速度
- 减少扫描区块数从 100000 到 20000(只扫描最近约 2 天)
- 并行查询 SENT 和 RECEIVED 交易(提速 2倍)
- 从约 100 秒减少到约 10-15 秒每个代币
- 总同步时间从 5 分钟减少到 30-45 秒

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 08:24:36 -08:00
hailin 78e105d46d fix(android): 分批查询交易记录以绕过 RPC 10000 区块限制
RPC 节点限制每次查询最多 10000 个区块,修改为分批查询:
- 每批查询 10000 个区块
- 总共扫描最近 100000 个区块(约 10 批)
- 添加批次日志输出

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 08:04:58 -08:00
hailin 6e03c1c798 fix(android): 进一步修复交易记录同步问题
- 将扫描区块数从 50000 增加到 200000(确保覆盖足够长时间)
- 统一地址格式为 lowercase,避免大小写不匹配导致记录无法同步
- 添加详细的交易哈希日志用于调试
- 修复 saveTransactionRecord 和 syncNativeTransactionHistory 中的地址格式问题

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 07:55:18 -08:00
hailin a516006117 fix(android): 修复交易记录同步功能
- 修复 fromBlock 使用 "earliest" 导致 RPC 请求超时的问题
- 改为只扫描最近 50000 个区块(约 1-2 个月历史)
- 添加自动获取当前区块号功能
- 进入交易记录页面时自动触发同步
- 添加同步结果提示消息(Snackbar)
- 增加详细的调试日志用于排查问题
- 暂时禁用原生 KAVA 交易同步(KavaScan API 需验证)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 07:41:24 -08:00
hailin 3727b0e817 feat(android): 实现交易记录功能
- TssRepository 添加交易记录管理方法 (saveTransactionRecord, updateTransactionStatus, confirmTransaction, getTransactionRecords)
- 添加历史交易同步功能 (syncERC20TransactionHistory, syncNativeTransactionHistory, syncAllTransactionHistory)
- MainViewModel 添加交易记录状态和后台确认轮询
- 新建 TransactionHistoryScreen 交易记录列表界面
- WalletsScreen 添加"记录"按钮入口
- 转账成功后自动保存记录并后台确认状态
- 首次导入钱包时自动同步链上历史交易

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 06:55:25 -08:00
hailin 7b3d28c957 feat(android): 添加导出/导入备份功能的详细调试日志
添加日志位置:
- TssRepository: exportShareBackup 和 importShareBackup 函数
- MainViewModel: exportShareBackup 和 importShareBackup 函数
- MainActivity: 文件选择器回调、LaunchedEffect、导出/导入触发点

日志标签:
- [EXPORT] / [IMPORT]: Repository 和 ViewModel 层
- [EXPORT-FILE] / [IMPORT-FILE]: 文件选择器回调
- [EXPORT-EFFECT] / [IMPORT-EFFECT]: LaunchedEffect
- [EXPORT-TRIGGER] / [IMPORT-TRIGGER]: 用户操作触发点

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 05:39:56 -08:00
hailin c002640911 fix(android): 修复导出备份后返回启动屏幕的问题
问题原因:
- 当文件选择器 (ActivityResultContracts.CreateDocument) 启动时,
  Android 可能会销毁并重新创建 Activity(配置更改)
- startupComplete、pendingExportJson、pendingExportAddress 使用 remember
  存储状态,在 Activity 重建时会丢失
- startupComplete 重置为 false 导致显示启动检查屏幕

修复方案:
- 将 startupComplete 从 remember 改为 rememberSaveable
- 将 pendingExportJson 和 pendingExportAddress 从 remember 改为 rememberSaveable
- rememberSaveable 会通过 Android 的 savedInstanceState 机制持久化状态

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 05:32:43 -08:00
hailin 2799eb5a3a fix(tss-android): 修复备份恢复后钱包无法签名的问题
## 问题根因

备份恢复后的钱包在签名时失败,根本原因是 gRPC 通信使用了**设备的 partyId**,
而不是 **share 的原始 partyId**(keygen 时生成的 partyId)。

这导致:
1. 消息订阅使用错误的 partyId,无法接收其他参与方发送的消息
2. 消息发送使用错误的 fromParty,其他参与方无法正确路由消息
3. Session 事件订阅使用错误的 partyId,无法接收 session_started 等事件
4. API 调用使用错误的 partyId,服务端无法正确识别参与方

## 修改内容

### 1. 添加新的成员变量用于跟踪正确的 partyId
- `currentMessageRoutingPartyId`: 消息路由使用的 partyId
- `currentSessionEventPartyId`: Session 事件订阅使用的 partyId

### 2. 修改 startMessageRouting 方法
- 添加 `routingPartyId` 可选参数
- 签名流程中使用 signingPartyId(share 原始 partyId)
- 消息发送 (routeMessage fromParty) 使用正确的 partyId
- 消息订阅 (subscribeMessages) 使用正确的 partyId

### 3. 修改 startSessionEventSubscription 方法
- 添加 `subscriptionPartyId` 可选参数
- 签名流程中使用 signingPartyId

### 4. 修改 ensureSessionEventSubscriptionActive 方法
- 添加 `signingPartyId` 可选参数
- 支持动态切换订阅的 partyId

### 5. 修复所有签名流程中的调用

#### joinSignSessionViaGrpc 流程:
- grpcClient.joinSession 使用 signingPartyId
- startMessageRouting 使用 signingPartyId
- ensureSessionEventSubscriptionActive 使用 signingPartyId

#### joinSignSessionViaApiAndExecute 流程:
- joinSignSessionViaApi HTTP 请求使用 signingPartyId
- grpcClient.joinSession 使用 signingPartyId
- startMessageRouting 使用 signingPartyId

#### createSignSession 流程:
- ensureSessionEventSubscriptionActive 使用 signingPartyId
- join_tokens 查找使用 originalPartyId
- grpcClient.joinSession 使用 signingPartyId
- startMessageRouting 使用 signingPartyId

#### startSigning 流程:
- startMessageRouting 使用 signingPartyId

### 6. 修复 joinSignSessionViaApi 函数
- 添加 signingPartyId 参数
- HTTP 请求体中的 party_id 和 device_id 使用 signingPartyId

### 7. 修复重连恢复逻辑 (restoreStreamsAfterReconnect)
- startMessageRouting 使用保存的 currentMessageRoutingPartyId
- startSessionEventSubscription 使用保存的 currentSessionEventPartyId

## 测试场景

修复后应支持以下场景:
1. 原设备 keygen → 原设备签名 ✓
2. 原设备 keygen → 备份 → 新设备恢复 → 新设备发起签名 ✓
3. 原设备 keygen → 备份 → 新设备恢复 → 新设备参与签名 ✓

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-26 04:15:52 -08:00
hailin 37d3300b17 fix(contribution-service): CDC planting_orders 阶段按 order_id 排序处理
## 问题背景

用户 D25122700018 的层级已解锁(unlocked_level_depth=5),但缺少 TEAM_LEVEL 算力记录。
其下级用户 D25122700019 的团队算力被错误地分配给了 D25122700015(level 2)而非 D25122700018(level 1)。

## 根本原因分析

1. 源系统数据顺序正确:
   - D25122700018: order_id=55, created_at=2026-01-09 11:57:01 (先认种)
   - D25122700019: order_id=57, created_at=2026-01-09 12:00:38 (后认种)

2. Kafka 消息顺序错误:
   - D25122700019: offset=732, synced_at=10:15:32 (先处理)
   - D25122700018: offset=798, synced_at=10:15:41 (后处理)

3. 原因:Debezium snapshot 按 PostgreSQL 物理存储顺序(heap order)读取数据,
   而非按主键顺序。即使 topic 只有 1 个分区,消息顺序仍然错误。

4. 后果:当处理 D25122700019 的认种时,D25122700018 的 unlocked_level_depth 还是 0,
   导致 D25122700019 的 TEAM_LEVEL 算力跳过 level 1 直接分配给 level 2。

## 解决方案

对 planting_orders 阶段实现"收集-排序-处理"模式:
1. 先收集所有消息到内存数组(不立即处理)
2. 按 order_id(源系统主键)升序排序
3. 再按排序后的顺序逐条处理

这确保上游用户的认种记录先于下游用户处理,避免算力分配错误。

## 受影响用户案例

- 上游用户: D25122700018 (order_id=55)
- 下游用户: D25122700019 (order_id=57, 58, 59)
- 错误分配: D25122700019 的 TEAM_LEVEL 给了 D25122700015 而非 D25122700018

## 回滚方法

如需回滚此修改,将 consumePhaseToEnd 方法中的判断条件改为 false:
```typescript
const needsSorting = false; // 原: phase.tableName === 'planting_orders'
```
或直接 revert 此 commit。

## 风险评估

- 业务逻辑完全不变,只改变处理顺序
- user_accounts 和 referral_relationships 阶段保持原有逻辑
- 内存开销可控(10000 条记录约 5MB)
- 排序开销可忽略(O(n log n))

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 03:41:14 -08:00
hailin e9dea69ee9 feat(batch-mining): 动态获取批量补发计算起始日期
重构批量补发功能,将硬编码的起始日期(2025-11-08)改为从 Excel 数据中
动态获取,提高计算的准确性和灵活性。

后端改动 (mining-service):
- 新增 DEFAULT_MINING_START_DATE 常量作为找不到有效数据时的默认值
- 新增 getCalculatedStartDate() 方法:从批次1用户的 miningStartDate 中
  获取最早日期
- 新增 parseDate() 方法:支持解析 2025.11.8、2025-11-08、2025/11/8 格式
- 修改 buildMiningPhases() 方法:新增 startDateStr 参数,不再硬编码日期
- 修改 preview/execute 方法:在返回结果中包含 calculatedStartDate 字段

前端改动 (mining-admin-web):
- 更新 BatchPreviewResult 接口,新增 calculatedStartDate 字段
- 预览结果描述中显示计算起始日期(蓝色高亮)
- 确认对话框中新增"计算起始日期"行

降级策略:
- 若批次1用户不存在或日期均无效,自动使用默认日期 2025-11-08

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-23 02:01:40 -08:00
hailin e56c86545c docs: 添加 RWADurian 2.0 部署与运维成本方案
- 方案一:高可用架构(3台服务器,100Mbps,月成本 ¥20,950)
- 方案二:标准架构(1台服务器,10Mbps,月成本 ¥5,150)
- 包含数据存储与带宽需求分析
- 包含架构设计与服务器配置说明

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 03:29:51 -08:00
hailin 0009a9358d fix(mining-admin-service): 修正调用 mining-service admin API 路径
mining-service 的 AdminController 路由前缀改为 mining/admin 后,
mining-admin-service 中调用的路径也需要相应修改

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 02:15:12 -08:00
hailin f3d460ba09 fix(mining-app): 修复批量补发记录解析字段名
API 返回 records 字段,而非 data 或 items

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 02:11:10 -08:00
hailin ab320083f7 fix(mining-service): 修复批量补发记录分页参数类型问题
Query 参数是字符串类型,需要显式转换为数字

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 02:05:16 -08:00
hailin c7f7c10d59 fix(mining-service): 修正 AdminController 路由前缀
将 AdminController 路由从 /admin 改为 /mining/admin,
以匹配 Kong 网关路由 /api/v2/mining

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 01:51:11 -08:00
hailin 623e695353 fix(mining-app): 修正批量补发记录 API 路径
添加 /admin 前缀以匹配 mining-service 的 AdminController 路由

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 01:45:41 -08:00
hailin b6d723333c fix(mining-app): 修复 BatchMiningRecordsPage 类名冲突
将页面类重命名为 BatchMiningRecordsListPage 以避免与实体类冲突

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 01:42:46 -08:00
hailin d5dc248a16 feat(mining-app): 添加补发记录功能
- 添加批量补发记录 API endpoint
- 创建 BatchMiningRecord 实体和模型
- 添加批量补发记录 provider 和页面
- 在"我的"页面动态显示补发记录入口(仅当用户有记录时显示)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 01:35:53 -08:00
hailin 134e45e0bf fix(mining-admin-service): 审计日志失败不影响批量补发返回结果
批量补发实际操作完成后,即使审计日志创建失败也应返回成功响应。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 00:57:00 -08:00
hailin 8a47659c47 feat(batch-mining): 按阶段创建补发记录并添加用户查询功能
- 修改BatchMiningRecord表结构,添加phase和daysInPhase字段
- 修改execute函数,按阶段为每个用户创建记录
- 添加用户批量补发记录查询API
- mining-admin-web用户详情页添加"批量补发"Tab

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 00:30:06 -08:00
hailin f44af3a2ed fix(batch-mining): 修正grandTotalAmount重复累加问题
用户可能在多个批次中出现,之前按批次累加batchTotalAmount会导致
同一用户的收益被重复计算。改为直接累加所有用户的amount(去重)。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-22 00:04:35 -08:00
hailin 18e9749ad8 fix(batch-mining): 修正总天数计算逻辑
- 总挖矿天数 = 从2025-11-08到今天的自然天数
- 最后阶段天数 = 总天数 - 前面各阶段天数之和
- 不再累加preMineDays作为总天数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:46:27 -08:00
hailin d47276a460 fix(batch-mining): 添加详细日志追踪阶段划分和总天数计算
- 添加更清晰的阶段划分注释说明
- 添加日志打印最后批次preMineDays=0时改为1天的情况
- 添加预期总金额日志用于验证计算正确性

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:44:10 -08:00
hailin 0adc4c8c26 fix(batch-mining): 最后批次preMineDays=0时改为1天
最后一个批次即使 preMineDays=0,也要算1天(所有人一起挖1天生成收益)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:37:35 -08:00
hailin d98e22f151 fix(batch-mining): 移除多余的最后阶段
根据需求:总天数 = 所有批次的 preMineDays 之和
- 阶段1: 只有第一批,分配第一批的 preMineDays 天
- 阶段2: 第一批+第二批,分配第二批的 preMineDays 天
- 依次类推...

没有额外的"最后阶段",不再使用 maxTotalMiningDays

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:35:50 -08:00
hailin c90d88a047 Revert "fix(batch-mining): 修正阶段划分逻辑"
This reverts commit 9e9c791283.
2026-01-21 23:34:12 -08:00
hailin 9e9c791283 fix(batch-mining): 修正阶段划分逻辑
preMineDays 表示该批次比最后批次提前多少天开始挖矿
阶段天数 = 当前批次的preMineDays - 下一批次的preMineDays(差值)

例如:批次1(3天)、批次2(2天)、批次3(1天)、批次4(0天)
- 阶段1:只有批次1,持续 3-2=1 天
- 阶段2:批次1+2,持续 2-1=1 天
- 阶段3:批次1+2+3,持续 1-0=1 天
- 最后阶段:所有批次一起挖剩余天数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:33:58 -08:00
hailin 2358b3ea17 fix(batch-mining): 修复重复用户计算问题
- 添加 userBatchContributions 按用户-批次跟踪算力
- 修复阶段计算时同一用户被重复计算的问题
- 修复输出结果时同一用户金额被重复累加的问题
- 使用 processedInPhase Set 避免同一阶段重复处理同一用户

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:24:03 -08:00
hailin f14ad0b7ad fix(batch-mining): 修正补发计算逻辑
- 去掉虚构的'全网算力'概念
- 每天固定分配70%产出给参与用户
- 用户收益 = 每日产出 × 70% × 天数 × (用户算力/当前参与总算力)
- 总补发金额固定为: 日产出 × 70% × 总天数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 23:08:55 -08:00
hailin 702fa937e8 fix(batch-mining): 修正阶段划分逻辑
- preMineDays 是该批次加入后挖矿的天数,不是差值
- 批次1的preMineDays=3 → 批次1先独挖3天
- 批次2的preMineDays=2 → 批次1+2一起挖2天
- 批次3的preMineDays=1 → 批次1+2+3一起挖1天
- 最后所有批次一起挖剩余天数

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:29:34 -08:00
hailin 8b8d1f7d16 Revert "fix(batch-mining): 简化计算逻辑"
This reverts commit 4dcbe38309.
2026-01-21 21:17:00 -08:00
hailin 4dcbe38309 fix(batch-mining): 简化计算逻辑
- 移除分阶段计算,改用简单公式
- 用户收益 = (用户算力/全网算力) × 每日产出 × 天数
- 全网算力 = 用户算力 / 0.7

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:16:14 -08:00
hailin 97b3a20a7c fix(batch-mining): 修正70%比例计算逻辑
- 移除 PERSONAL_RATE,避免70%被乘两次
- 用户算力 = 棵数 × 22617(不再乘70%)
- 全网算力 = 用户算力 / 0.7(70%体现在这里)
- 预期结果:(1000000/365/2)*70%*74 = 70958.90411

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 21:07:35 -08:00
hailin e79d42db61 fix(batch-mining): 修复计算逻辑,批量补发用户只占全网70%
- 添加 BATCH_USERS_NETWORK_RATIO 常量(0.70)
- 计算全网算力时:实际全网算力 = 用户算力 / 0.7
- 修正预期结果约为 70,958 而非 104,656

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 20:58:42 -08:00
hailin 16daa7403c fix(mining-admin): 修正Excel列索引
Excel实际格式是:
- 索引0: 序号
- 索引1: 注册ID
- 索引2: 认种量(棵)
- 索引3: 挖矿开始时间
- 索引4: 批次
- 索引5: 授权提前挖的天数
- 索引6: 备注

之前代码从索引0读取用户ID是错误的,现在修正为从索引1开始读取。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:58:17 -08:00
hailin ca5de3add1 debug: 添加原始Excel数据日志 2026-01-21 19:46:31 -08:00
hailin 390cc3131d fix(contribution): 修复T2/T3补发记录缺少treeCount和baseContribution
补发奖励时从SyncedAdoption查询原始认种数据,
确保补发记录包含正确的棵数和基础贡献值。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 19:38:18 -08:00
hailin e4c320970f fix(batch-mining): 重构分阶段挖矿计算逻辑
核心修改:
1. 正确理解 preMineDays 的含义:该批次比下一批次提前的天数
2. 新增 totalMiningDays:从挖矿开始日期到今天的总天数
3. 分阶段计算收益:
   - 阶段1: 批次1独挖 (preMineDays1 - preMineDays2) 天
   - 阶段2: 批次1+2共挖 (preMineDays2 - preMineDays3) 天
   - 阶段3: 批次1+2+3共挖 (preMineDays3 - 0) 天
   - 最终阶段: 所有批次共挖 (totalMiningDays - 已用天数) 天
4. 每个阶段按当时的全网算力比例分配收益

示例:
- 批次1 preMineDays=3,批次2 preMineDays=2,批次3 preMineDays=1
- totalMiningDays=74(从11.8到1.21)
- 阶段1: 批次1独挖1天 (3-2=1)
- 阶段2: 批次1+2共挖1天 (2-1=1)
- 阶段3: 批次1+2+3共挖1天 (1-0=1)
- 阶段4: 所有批次共挖71天 (74-3=71)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 18:56:45 -08:00
hailin af95f8da0c fix(mining-admin): 根据挖矿开始时间自动计算挖矿天数
之前错误地从Excel第6列读取preMineDays,但该列为空。
现在根据"挖矿开始时间"到今天自动计算实际挖矿天数。

修改内容:
- 修正Excel列索引(用户ID在第1列,不是第2列)
- 解析日期支持多种格式(2025.11.8, 2025-11-08, 2025/11/8)
- 自动计算从挖矿开始日期到今天的天数作为preMineDays

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 18:50:46 -08:00
hailin 7a5faad665 feat(mining-app): UI调整 - 隐藏部分功能和文案修改
- 兑换页面:将"挖矿账户"改为"分配账户"
- 我的页面:隐藏"账户设置"栏目(2.0版本暂不需要)
- 贡献值页面:隐藏"今日预估收益"栏目
- 贡献值明细页:同伴上贡献值不显示用户ID
- 参与记录页:将"算力"改为"贡献值"

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 18:00:40 -08:00
hailin 8f0fc09a4c fix(mining-admin-web): 解包 mining-admin-service 响应的 TransformInterceptor 包装
mining-admin-service 也使用 TransformInterceptor 将所有响应包装为 { success, data, timestamp } 结构,
前端需要从 res.data.data 中提取实际数据。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:34:36 -08:00
hailin 30a82f09f3 fix(mining-admin): 解包 mining-service 响应的 TransformInterceptor 包装
mining-service 使用 TransformInterceptor 将所有响应包装为 { success, data, timestamp } 结构,
mining-admin-service 需要从 result.data 中提取实际数据。

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-21 06:26:56 -08:00