在不触及交易引擎的情况下为 FIX 添加加密审计追踪
Source: Dev.to
请提供您希望翻译的完整文本内容,我将为您翻译成简体中文,并保留原始的链接和格式。
传统日志的不足之处
┌─────────────────────────────────────────┐
│ Traditional Logging │
├─────────────────────────────────────────┤
│ ✗ Admin can modify logs │
│ ✗ No proof of completeness │
│ ✗ Timestamp ≠ proof of time │
│ ✗ Auditor must trust submitter │
│ ✗ Deletion is undetectable │
└─────────────────────────────────────────┘
MiFID II RTS 25 要求时钟同步至 100 µs。即使拥有完美的时间戳,也 没有加密证明 表明:
- 日志未被修改,
- 没有条目被删除,
- 序列是完整的。
Sidecar 解决方案
如果您能够在每个交易事件中添加加密证明 而无需触碰您的 FIX 引擎,会怎样?
┌─────────────────────────────────────────────────────────┐
│ Trading System │
│ │
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ │
│ │ Algo │────▶│ Order │────▶│ FIX │──────▶│ Venue
│ │ Engine │ │ Manager │ │ Engine │ │
│ └────┬─────┘ └────┬─────┘ └────┬─────┘ │
│ │ │ │ │
│ │ ┌───────────┴────────────────┘ │
│ │ │ Event Tap (async copy) │
│ ▼ ▼ │
│ ┌─────────────────────────────────────┐ │
│ │ VCP Sidecar Process │ │
│ │ ┌─────────┐ ┌─────────┐ ┌───────┐ │ │
│ │ │ Collect │▶│ Hash │▶│ Sign │ │──▶ Auditor│
│ │ │ Events │ │ Chain │ │Ed25519│ │ │
│ │ └─────────┘ └─────────┘ └───────┘ │ │
│ └─────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
关键: FIX 消息流保持不变。零延迟影响。
Sidecar 的工作流程
| 步骤 | 操作 | 目的 |
|---|---|---|
| 接收 | 事件异步复制(不阻塞) | 非侵入式 |
| 哈希 | 每个事件使用 SHA‑256 | 防篡改证据 |
| 链接 | 链接到前一个哈希 | 检测删除/重新排序 |
| 签名 | Ed25519 签名 | 不可否认性 |
| 锚定 | 批量 Merkle 根(周期性) | 高效的外部验证 |
给我看看代码
FIX ExecutionReport(未更改)
8=FIX.4.4|9=256|35=8|49=BROKER|56=CLIENT|
11=ORD-2025-001|37=EXE-12345|17=EXEC-67890|
150=F|39=2|55=XAUUSD|54=1|38=100|44=2650.50|
14=100|151=0|31=2650.45|32=100|6=2650.45|
60=20251222-14:30:05.120|10=078|
VCP 审计事件(并行)
{
"header": {
"event_id": "01934e3a-7b2c-7f93-8f2a-1234567890ab",
"trace_id": "01934e3a-6a1b-7c82-9d1b-0987654321dc",
"timestamp": "2025-12-22T14:30:05.120000000Z",
"event_type": "EXE",
"clock_sync": "PTP_SYNCED",
"symbol": "XAUUSD"
},
"payload": {
"order_id": "EXE-12345",
"side": "BUY",
"price": "2650.50",
"quantity": "100",
"filled_qty": "100"
},
"security": {
"event_hash": "sha256:8f2a7b3c4d5e6f...",
"prev_hash": "sha256:a1b2c3d4e5f6...",
"signature": "ed25519:7g8h9i0j..."
}
}
prev_hash 链接到前一个事件。破坏链条?可立即检测到。
哈希链解释
Event 1 (SIG) Event 2 (ORD) Event 3 (EXE)
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
│ hash: a1b2c3 │ │ hash: d4e5f6 │ │ hash: g7h8i9 │
│ prev: 000000 │──────▶│ prev: a1b2c3 │──────▶│ prev: d4e5f6 │
│ sig: xxxxx │ │ sig: yyyyy │ │ sig: zzzzz │
└──────────────┘ └──────────────┘ └──────────────┘
│ │ │
└──────────────────────┴──────────────────────┘
│
Merkle Root: m1n2o3
(定期锚定)
- 删除 Event 2 → 链在 Event 3 处中断。
- 修改 Event 1 → 哈希改变,Event 2 的
prev_hash不匹配。 - 插入 假事件 → 签名验证失败。
映射到 FIX 标签(可选嵌入)
| Tag | 名称 | 描述 |
|---|---|---|
| 20001 | AuditEventHash | SHA‑256 哈希(前 16 个字符) |
| 20002 | AuditPrevHash | 前一个事件的链接 |
| 20003 | AuditTraceID | UUID v7 将 SIG → ORD → EXE 关联 |
| 20004 | ClockSyncStatus | 0 = 未知,1 = NTP,2 = PTP,3 = GPS |
| 20005 | AuditMerkleRoot | 批次完整性证明 |
标签 20001‑20999 是根据 FIX 规范用户自定义的,非常适合无需正式批准的概念验证(PoC)。
为什么不直接使用公共区块链?
- 延迟: 每块 12 + 秒 vs. 纳秒级交易。
- 成本: 燃气费在每天 10 K+ 事件时激增。
- 隐私: 公共账本上的订单流是不可取的。
- 复杂性: 你的运维团队会爱上你 (/s)。
Sidecar 优势
- 本地哈希链 → 即时验证。
- 定期 Merkle‑root 锚定(可选,批处理)。
- 默认私密。
- 与现有基础设施并行运行,对 FIX 引擎零代码更改。
监管方面如何?
| 监管 | 要求 | 这如何帮助 |
|---|---|---|
| MiFID II RTS 25 | 时钟同步 ≤ 100 µs | clock_sync 字段证明同步状态 |
| MiFID II RTS 6 | 算法审计追踪 | 完整、防篡改的事件链 |
| SEC Rule 17a‑4 | 保存与完整性 | 加密哈希和签名满足“完整性” |
| EMIR | 交易报告 | 事件 ID 与追踪 ID 实现端到端可追溯性 |
SIG → ORD → EXE chain
监管背景
- EU AI Act – Art. 12 – 自动记录,密码学完整性证明
- SEC Rule 17a‑4 – 防篡改记录,哈希链 + 签名
欧盟《人工智能法案》对高风险人工智能系统的截止日期为 2027年8月。
算法交易系统很可能在适用范围内。
入门
1. 最小化 Python 实现
import hashlib
import json
from datetime import datetime, timezone
import uuid
def generate_uuid_v7() -> str:
"""Placeholder for a UUID‑v7 generator."""
return str(uuid.uuid4())
def create_event(event_type: str, payload: dict, prev_hash: str) -> dict:
header = {
"event_id": generate_uuid_v7(),
"timestamp": datetime.now(timezone.utc).isoformat(),
"event_type": event_type,
"clock_sync": "NTP_SYNCED"
}
# Canonical JSON for consistent hashing
canonical = json.dumps(
{"header": header, "payload": payload},
sort_keys=True,
separators=(',', ':')
)
event_hash = hashlib.sha256(canonical.encode()).hexdigest()
return {
"header": header,
"payload": payload,
"security": {
"event_hash": event_hash,
"prev_hash": prev_hash
}
}
# ── Chain events ────────────────────────────────────────
prev = "0" * 64
sig_event = create_event(
"SIG",
{"algo": "momentum-v2", "confidence": 0.87},
prev
)
prev = sig_event["security"]["event_hash"]
ord_event = create_event(
"ORD",
{"symbol": "XAUUSD", "side": "BUY", "qty": 100},
prev
)
prev = ord_event["security"]["event_hash"]
exe_event = create_event(
"EXE",
{"fill_price": 2650.45, "fill_qty": 100},
prev
)
2. 接入你的 FIX 引擎
大多数 FIX 引擎都提供回调钩子。下面是一个 QuickFIX 示例:
void Application::onMessage(const FIX44::ExecutionReport& msg,
const FIX::SessionID& session) {
// Normal processing
processExecution(msg);
// Async emit to VCP side‑car (non‑blocking)
vcpSidecar.emitAsync("EXE", extractPayload(msg));
}
对关键路径零影响。
完整规范
| Item | Link |
|---|---|
| Spec | VCP v1.0 |
| IETF Draft | draft‑kamimura‑scitt‑vcp |
| GitHub | github.com/veritaschain |
| License | CC BY 4.0 (spec), Apache 2.0 (code) |
无供应商锁定,无专有格式——仅有密码学证明。
TL;DR
| What | How |
|---|---|
| 问题 | 交易日志可能被修改、删除或伪造 |
| 解决方案 | 在旁路进程中使用哈希链 + 签名 |
| 对 FIX 的影响 | 零 – 消息流保持不变 |
| 对延迟的影响 | 零 – 异步事件捕获 |
| 验证 | 任何人都可以在不信任提交者的情况下进行验证 |
下次审计员问“你能证明吗?”时,你可以用加密证明来回答,而不是“相信我们”。
有问题吗?
- 技术:
- 参考材料:
如果您正在构建算法交易系统并考虑审计追踪,我很想了解您面临的挑战。请在下方留言。 👇