150 lines
4.7 KiB
Go
150 lines
4.7 KiB
Go
// Package genexchain — Compliance Ante Handler Integration
|
||
//
|
||
// 本文件将独立的 ComplianceAnteHandler (x/evm/ante/) 桥接到
|
||
// Cosmos SDK ante handler 链中,实现验证节点级交易拦截。
|
||
//
|
||
// 对应指南: 06-区块链开发指南.md §6 (链级合规能力) 和 §16 (验证节点级交易拦截)
|
||
//
|
||
// 架构:
|
||
//
|
||
// TX → ComplianceAnteWrapper (OFAC/TravelRule/Structuring)
|
||
// → cosmos/evm AnteHandler (签名/Gas/Nonce/...)
|
||
// → Mempool → Block
|
||
//
|
||
// ComplianceAnteHandler 执行三项检查:
|
||
// 1. OFAC 地址拦截 — 制裁名单地址的交易直接拒绝,不进入 mempool
|
||
// 2. Structuring 检测 — 24h 内拆分交易规避 $3,000 阈值,标记为可疑
|
||
// 3. Travel Rule 预打包检查 — ≥$3,000 转移必须已记录身份哈希
|
||
//
|
||
// OFAC 名单由链下合规服务通过 ComplianceHandler.UpdateOFACList() 定期同步。
|
||
// Travel Rule 数据由 compliance-service 通过 ComplianceHandler.RecordTravelRule() 写入。
|
||
package genexchain
|
||
|
||
import (
|
||
"fmt"
|
||
"math/big"
|
||
|
||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||
evmtypes "github.com/cosmos/evm/x/vm/types"
|
||
"github.com/ethereum/go-ethereum/common"
|
||
|
||
genexante "github.com/genex/genex-chain/x/evm/ante"
|
||
)
|
||
|
||
// ComplianceAnteWrapper 将独立的 ComplianceAnteHandler 桥接到 Cosmos SDK ante 链。
|
||
//
|
||
// 工作流程:
|
||
// 1. 遍历 tx 中的所有消息
|
||
// 2. 对 MsgEthereumTx 类型的消息提取 from/to/value
|
||
// 3. 调用 ComplianceAnteHandler.AnteHandle() 执行合规检查
|
||
// 4. 如果被拒绝 → 返回错误,交易不会被打包
|
||
// 5. 如果可疑 → 记录日志,交易仍可打包
|
||
// 6. 记录转移金额用于 Structuring 滑动窗口检测
|
||
// 7. 合规通过后委托给标准 cosmos/evm ante handler
|
||
type ComplianceAnteWrapper struct {
|
||
compliance *genexante.ComplianceAnteHandler
|
||
inner sdk.AnteHandler
|
||
}
|
||
|
||
// NewComplianceAnteWrapper 创建包含合规检查的 ante handler。
|
||
//
|
||
// 参数:
|
||
// - inner: 标准 cosmos/evm ante handler (由 evmante.NewAnteHandler 创建)
|
||
// - compliance: Genex 合规检查处理器
|
||
//
|
||
// 用法 (在 app.go 中):
|
||
//
|
||
// standardHandler := evmante.NewAnteHandler(options)
|
||
// complianceHandler := genexante.NewComplianceAnteHandler()
|
||
// wrappedHandler := NewComplianceAnteWrapper(standardHandler, complianceHandler)
|
||
// app.SetAnteHandler(wrappedHandler)
|
||
func NewComplianceAnteWrapper(
|
||
inner sdk.AnteHandler,
|
||
compliance *genexante.ComplianceAnteHandler,
|
||
) sdk.AnteHandler {
|
||
w := &ComplianceAnteWrapper{
|
||
compliance: compliance,
|
||
inner: inner,
|
||
}
|
||
return w.AnteHandle
|
||
}
|
||
|
||
// AnteHandle 在标准 ante handler 之前执行合规检查。
|
||
//
|
||
// 对于非 EVM 的 Cosmos SDK 消息(如 staking、gov),合规检查被跳过,
|
||
// 直接委托给内部 handler。
|
||
//
|
||
// 模拟模式 (simulate=true) 下跳过合规检查,因为 gas 估算不应被合规拒绝。
|
||
func (w *ComplianceAnteWrapper) AnteHandle(
|
||
ctx sdk.Context, tx sdk.Tx, simulate bool,
|
||
) (sdk.Context, error) {
|
||
// 模拟模式跳过合规检查(gas 估算)
|
||
if simulate {
|
||
return w.inner(ctx, tx, simulate)
|
||
}
|
||
|
||
for _, msg := range tx.GetMsgs() {
|
||
// 仅拦截 EVM 交易;Cosmos 原生消息直接放行
|
||
ethMsg, ok := msg.(*evmtypes.MsgEthereumTx)
|
||
if !ok {
|
||
continue
|
||
}
|
||
|
||
// 获取底层 go-ethereum Transaction 对象
|
||
ethTx := ethMsg.AsTransaction()
|
||
if ethTx == nil {
|
||
continue
|
||
}
|
||
|
||
// 提取发送方 (from) — Cosmos AccAddress bytes → Ethereum hex
|
||
fromBytes := ethMsg.GetFrom()
|
||
fromAddr := common.BytesToAddress(fromBytes)
|
||
|
||
// 提取接收方 (to) — 合约创建时为 nil
|
||
toHex := ""
|
||
if ethTx.To() != nil {
|
||
toHex = ethTx.To().Hex()
|
||
}
|
||
|
||
// 提取交易金额
|
||
value := ethTx.Value()
|
||
if value == nil {
|
||
value = new(big.Int)
|
||
}
|
||
|
||
// ====== 执行合规检查 ======
|
||
result := w.compliance.AnteHandle(fromAddr.Hex(), toHex, value)
|
||
|
||
// 检查 1: OFAC / Travel Rule 拒绝 → 交易不进入 mempool
|
||
if !result.Allowed {
|
||
ctx.Logger().Error("Transaction rejected by compliance",
|
||
"module", "genex-compliance",
|
||
"from", fromAddr.Hex(),
|
||
"to", toHex,
|
||
"value", value.String(),
|
||
"reason", result.Reason,
|
||
)
|
||
return ctx, fmt.Errorf("genex compliance: %s", result.Reason)
|
||
}
|
||
|
||
// 检查 2: 可疑但允许 → 记录警告日志,交易仍可打包
|
||
if result.Suspicious {
|
||
ctx.Logger().Warn("Suspicious transaction detected",
|
||
"module", "genex-compliance",
|
||
"from", fromAddr.Hex(),
|
||
"to", toHex,
|
||
"value", value.String(),
|
||
"reason", result.SuspReason,
|
||
)
|
||
}
|
||
|
||
// 检查 3: 记录转移金额用于 Structuring 滑动窗口检测
|
||
if value.Sign() > 0 {
|
||
w.compliance.RecordTransfer(fromAddr.Hex(), value)
|
||
}
|
||
}
|
||
|
||
// 合规通过,委托给标准 cosmos/evm ante handler
|
||
return w.inner(ctx, tx, simulate)
|
||
}
|