交易所钱包 #5 - 风控设计

  • Tiny熊
  • 发布于 8小时前
  • 阅读 57

在前几篇文章,我们分别介绍了交易所钱包系统的整体架构设计、签名机与用户账户生成的方案、用户充值以及用户提现,这篇文章介绍风控,提升系统的安全性。风控的主要目标是防止盗币、欺诈、洗钱以及内部作恶,同时要尽量在不破坏用户体验的前提下拦截高风险行为,提升系统的整体安全性。架构更新在之前的架构

在前几篇文章,我们分别介绍了 交易所钱包系统的整体架构设计签名机与用户账户生成的方案 、用户充值 以及用户提现, 这篇文章介绍风控,提升系统的安全性。

风控的主要目标是防止盗币、欺诈、洗钱以及内部作恶,同时要尽量在不破坏用户体验的前提下拦截高风险行为,提升系统的整体安全性。

架构更新

在之前的架构设计中,其实存在一些安全风险:例如 wallet 和 scan 模块都直接读写业务数据库,缺乏统一的权限控制。这种情况下,开发人员可能绕过业务逻辑,直接在数据库中修改敏感数据。

为了解决这个问题,我们可以添加一个数据库网关(DB Gateway),由数据库网关统一控制数据写入。 wallet 模块或 scan 模块需要写入数据时,都通过数据库网关发送请求。 数据库网关单独部署,只允许内网服务访问,从而降低数据库被篡改的风险。

同时,对于高风险操作(如修改用户资金流水、执行用户提现),需要有风控签名确认

调整后的系统关系如下图所示:

钱包系统设计

数据库权限控制

加入风控和数据库网关模块后,可以对数据库的读写权限进行细粒度控制:

  1. 只读权限(ReadOnly Wallet 模块和 scan 模块从数据库读取数据时,可以不经过数据库网关,以提升效率。
  2. 普通写权限 数据库网关验证业务模块签名后写入。适用于非敏感数据(如 blockstransactions 表)。 除了防火墙控制内网访问外,数据库网关还需验证请求方的签名。
  3. 敏感写权限 数据库网关需要验证业务签名风控签名。 这类操作通常包括对 withdraws(取款)和 credits(资金流水)表的修改。 哪些表属于敏感表,可在配置文件中定义。

现在数据读写流程大概是这样的:

sequenceDiagram

    participant wallet/scan
    participant 风控
    participant DB 网关
    participant DB

    note over wallet/scan,DB: 确保数据库操作安全
    DB ->> wallet/scan: 读取数据(直接读、效率优先)
    wallet/scan->> DB 网关: 写数据(附带业务签名)
    DB 网关 ->> DB: 验证签名后写入
    wallet/scan->> 风控: 敏感操作请求风控签名
    风控 -->> wallet/scan: 返回风控签名 或 风控建议
    wallet/scan->> DB 网关: 提交业务签名 + 风控签名
    DB 网关->> DB: 验证双签后写入

签名机拥有独立数据库,私钥仅保存在本机,外部无法访问。 风控系统也有独立数据库,用于存储规则与评估记录,避免业务人员接触内部风控数据,并可根据需要限制风控管理员访问用户钱包数据。

提现权限控制

加入风控模块后,每笔提现同样需要风控签名确认。提现流程如下:

sequenceDiagram

    participant wallet
    participant 风控    
    participant 签名机
    participant RPC 节点

    note over wallet, RPC 节点: 确保提现交易安全
    wallet->>风控: 请求风控检查,获取签名
    风控->>wallet: 返回风控签名或建议
    wallet ->> 签名机: 提交业务签名 + 风控签名
    签名机-->>wallet: 返回交易签名
    wallet->>RPC 节点: 广播交易

风控模块设计与实现

风控常见规则包括:

  1. 账户地址判定:满足监管与合规要求。若检测到违规、反洗钱或被制裁地址,立即冻结或拒绝交易。
  2. 交易监控:限制单笔、单日提现金额与频率。可根据 KYC 等级设定不同额度。新设备或新绑定地址可限制短期提现,防止“即冲即提”,大额交易可转人工审批。

为了配合监控,系统需要实现可审计与可追溯的设计。

我们在风控模块中设计了三张核心表:

风险地址表address_risk_list):管理风险地址,黑名单地址

风控评估记录表(risk_assessments): 记录评估内容以及评估通过状态

risk_manual_reviews (人工审批记录表):记录所有人工审核操作,包括审核员信息、审核结果等。

完整的表结构见这里

风控评估记录表(risk_assessments)

这里我们主要看一下 风控评估记录表(risk_assessments):

字段名 类型 约束 说明
id INTEGER PRIMARY KEY AUTOINCREMENT 主键ID
operation_id TEXT UNIQUE NOT NULL 操作ID (由业务层生成的UUID)
table_name TEXT 业务表名 (withdrawals/credits),提现评估时为空
record_id INTEGER 业务表记录ID (双向关联)
action TEXT NOT NULL 操作类型 (insert/update/delete)
user_id INTEGER 关联用户ID
operation_data TEXT NOT NULL JSON: 原始操作数据,如果是提现保存交易信息
suggest_operation_data TEXT JSON: 风控建议的操作数据
suggest_reason TEXT 建议原因说明
risk_level TEXT NOT NULL 风险级别: low/medium/high/critical
decision TEXT NOT NULL 决策: auto_approve/manual_review/deny
approval_status TEXT 审批状态: pending/approved/rejected (仅用于manual_review)
reasons TEXT JSON: 风险原因数组
risk_signature TEXT 风控签名
expires_at DATETIME 签名过期时间
created_at DATETIME DEFAULT CURRENT_TIMESTAMP 创建时间
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP 更新时间
  • operation_id: 由业务层生成的UUID,为每一次操作进行编号,这样每一次操作都可以追踪,通知方便以后的日志审计。

  • actionoperation_data:记录操作的动作和数据,可以记录对数据库操作的数据,也可以记录交易数据。

  • suggest_operation_data : 记录风控的操作建议,例如,风控可能给出建议对一笔存款做冻结处理。

  • risk_signature: 风控评估后,对评估的数据(operation_idactionoperation_datasuggest_operation_datatimestamp等)签名。

    业务层拿到了风控签名后,会加上自己的业务签名,交给数据库网关或签名机,注意这里风控签名和业务签名,所签名的数据是一致的。

预防签名重放

我们这里选择了 Ed25519 曲线的签名算法(同 Solana 公链的签名算法),Ed25519的签名和验证速度都非常快。

在任何时候处理签名, 都需要考虑可能的签名重放攻击,因此签名的数据会加入 operation_idtimestamp

在提现交易中, 签名机除了检查风控和业务签名的有效性外,还会检查签名是否在有效期(例如 1 分钟)。

在 数据库网关中,会使用表 used_operation_ids 维护已使用的 operation_id, 从而防止签名重放攻击。

字段 类型 说明
id INTEGER 主键,自增
operation_id TEXT 操作ID(UUID),唯一
used_at INTEGER 使用时间戳(毫秒)
expires_at INTEGER 过期时间戳(毫秒)
created_at DATETIME 创建时间

人工审核

当一些操作风控系统无法独立判断是否通过时,需要进入人工审查, 在人工审查 通过后,业务层需要知道通过状态并继续原操作。可以使用轮询回调通知两种方式通知业务审核状态,我们这里选择使用回调通知。

例如,以提现进入人工审查为例,执行流程类似这样:

sequenceDiagram

    participant 审核员
    participant wallet
    participant 风控
    participant DB
    participant RPC

    note over 审核员,RPC: 以人工审查提现为例
    审核员 ->> 风控: 读取待审核
    审核员 ->> 风控: 提交人工审核结构(假设通过)
    风控 ->> wallet: 回调钱包、继续提现流程
    wallet ->> DB: 选择热钱包 、获取 Nonce 等
    wallet ->> 风控 : 再次请求风控签名
    wallet ->> RPC : 业务签名 + 风控签名,发起交易

为了让业务层正确关联操作,需要在业务表(如 withdraws)中添加 operation_id 字段,以便风控通过后,可以通过 operation_id 直接找到对应的提现操作。

后续优化方向

当前的风控设计仍是初版,后续可进一步优化:

  • 可配置的风控规则

  • 全链路操作记录可追踪和审计

  • 高频繁操作模式识别、风险智能评估

  • 各业务的通知可使用消息队列

总结

通过本文的风控设计,各模块职责更加明确,且通过签名机制有效提升了安全性:

  • wallet / scan:业务逻辑与业务签名
  • risk_control:风险评估与风控签名
  • db_gateway:数据库操作与双签验证
  • signer:交易签名与双签验证

这种设计既兼顾性能,也保障安全性: 普通数据可直接查询数据库,而敏感操作必须经过双签验证。 即使业务系统被攻破,没有风控签名也无法执行敏感操作。

点赞 0
收藏 1
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论
Tiny熊
Tiny熊
0xD682...E8AB
登链社区发起人 通过区块链技术让世界变得更好而尽一份力。