- 新增系统称号模板与效果配置表及相关CRUD接口 - 实现用户称号分配与抽奖效果应用逻辑 - 优化抽奖接口支持用户ID参数以应用称号效果 - 新增称号管理前端页面与分配功能 - 修复Windows时区错误与JSON字段初始化问题 - 移除无用管理接口代码并更新文档说明
3.8 KiB
头衔加概率与折扣的可验证设计
结论
-
采用“权重修饰”的方式为持有头衔的用户提升抽奖概率。
-
哈希算法(HMAC-SHA256 随机熵)保持不变;只扩展承诺与收据的字段以固化规则与有效权重,保证可验证性与不可篡改。
必要扩展
-
承诺扩展(IssueRandomCommitment)
- 新增
AlgoRulesHash:对“权重修饰规则(由头衔配置确定的纯函数)”做哈希并随期承诺固化。服务端在抽取前不能更改规则。
- 新增
-
收据扩展(Receipt)
-
新增
UserId:明确本次抽取的用户。 -
新增
WeightsTotalEffective:按用户头衔修饰后的总权重,用于位置采样与第三方复核。 -
新增
UserWeightFactorsRoot:以reward_id -> factor做 Merkle 根,第三方可据此对Items(snapshot)重建有效权重。
-
-
编码消息扩展(不改算法,仅改输入)
- 仍使用
HMAC(serverSubSeed, encodeMessage(...));encodeMessage增加UserId与WeightsTotalEffective字段(保持确定性)。
- 仍使用
规则与确定性
-
规则来源:头衔模板配置(百分比或加点),以及叠加策略(none|max|multiply)。
-
纯函数:
factor = F(user_titles, reward_id),只依赖用户持有的头衔与静态规则;不依赖随机数或服务端临时状态。 -
可复核:第三方得到
ItemsRoot、AlgoRulesHash、UserWeightFactorsRoot、UserId与收据内快照,即可重建每个reward_id的有效权重与WeightsTotalEffective,据同样的消息编码与哈希熵验证SelectedIndex。
核心流程(抽奖不变,仅插入修饰步骤)
- 读取承诺:
GetIssueRandomCommit(...)(internal/service/activity/random_commit.go:99)。 - 载入奖励池快照:同现有实现(
internal/service/activity/draw_execute.go:21-35)。 - 计算用户权重修饰:
effective_weight[i] = base_weight[i] * factor(user, reward_id[i]);汇总WeightsTotalEffective。 - 使用 HMAC-SHA256 生成熵(算法不变),对
encodeMessage(..., UserId, WeightsTotalEffective)取样位点。 - 按有效权重的累加区间选中
SelectedIndex/SelectedItemId。 - 返回收据,并包含
UserWeightFactorsRoot与证明材料。
折扣集成(独立不影响随机)
-
抽奖订单创建(新增):以活动门票价
PriceDraw(internal/repository/mysql/model/activities.gen.go:22)为基价。 -
头衔折扣:按叠加策略计算
discount_amount,落到订单字段DiscountAmount/ActualAmount(internal/repository/mysql/model/orders.gen.go:22)。 -
与优惠券/积分叠加:默认“优惠券优先 + 头衔折上折”,可通过
stack_policy切到“取最大”。
接口与服务
-
管理端:头衔模板 CRUD + 发放;配置权重修饰参数与叠加策略。
-
APP:
-
抽奖订单创建接口(新):返回计算后的金额。
-
抽奖接口:保持路径不变(
internal/api/activity/draw_app.go:28),服务内执行权重修饰。
-
-
模拟与校验:
-
模拟接口增加
user_id,输出期望概率与观测分布。 -
校验接口以收据扩展字段重建有效权重,验证
SelectedIndex。
-
验收标准
-
头衔发放后,持有用户的抽奖订单能正确展示并结算折扣。
-
抽奖收据包含新增字段,第三方使用承诺与收据可重放选中过程;不持有头衔的用户与持有者的分布差异符合规则。
-
哈希熵算法未变,安全与不可预测性不受影响。
说明:关于“加概率是否影响哈希算法”
-
不影响哈希算法本身(仍是 HMAC-SHA256)。
-
影响的是“采样空间”——由原始
weights_total改为WeightsTotalEffective,并且将该值与用户标识作为消息输入的一部分来固定采样过程;承诺和收据的扩展确保服务端无法事后调参。