Skip to content

Commit a424ac5

Browse files
committed
RVDS: support ledger eventlog record and ethereumAdapter
Signed-off-by: Jiale Zhang <[email protected]>
1 parent 01c3c1d commit a424ac5

File tree

20 files changed

+1194
-13
lines changed

20 files changed

+1194
-13
lines changed

Cargo.lock

Lines changed: 401 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

rvds/Cargo.toml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,5 +19,13 @@
1919
thiserror = { workspace = true }
2020
tokio = { workspace = true, features = ["full"] }
2121
url = "2"
22+
sha2 = { workspace = true }
23+
async-trait = { workspace = true }
24+
hex = { workspace = true }
25+
rand = "0.8"
26+
web3 = { version = "0.19", default-features = false, features = ["http", "signing"] }
27+
ethabi = "18"
28+
secp256k1 = { version = "0.27", features = ["rand"] }
29+
base64 = { workspace = true }
2230

2331

rvds/docs/architecture.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
- **HTTP API(Actix-web)**:暴露 `/rvds/*` 接口,负责参数校验与响应封装。
1515
- **订阅注册表(Subscriber Registry)**:用 `HashSet` 存储已注册的 Trustee 基址,持久化于 `data/rvds/subscribers.json`
1616
- **事件转发器(Forwarder)**:接收发布事件后,构造 RVPS 期望的 `message` 包裹并并发调用各 Trustee 的 `/api/rvps/register`
17+
- **账本记录器(Ledger Recorder)**:对 `PublishEventRequest` 做规范化哈希,写入外部不可篡改账本(默认 noop,可配置 HTTP ledger 以对接公链/透明日志网关),返回记录凭据。
1718
- **配置与启动器(Config / Bootstrap)**:从环境变量加载监听地址、数据目录、下游调用超时等参数。
1819

1920
## 数据模型
@@ -45,7 +46,7 @@
4546
- 返回:已新增的地址列表。
4647
- `POST /rvds/rv-publish-event`
4748
- 功能:校验事件并转发到全部 Trustee。
48-
- 返回:每个 Trustee 的投递结果(成功/失败与错误信息)。
49+
- 返回:每个 Trustee 的投递结果(成功/失败与错误信息),以及可选的 ledger 记录凭据
4950

5051
## 工作流程
5152

rvds/docs/audit-guide.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# 第三方审计操作手册(RVDS + RVPS + 以太坊账本)
2+
3+
本手册指导审计者仅凭 RVPS 返回的参考值(含审计字段)完成端到端验证,确认 RVDS 发布事件已被写入不可篡改账本(以太坊为例),并与 RVPS 内的参考值一致。
4+
5+
## 前提信息
6+
- RVPS 查询到的 `ReferenceValue`,其中新增可选字段 `audit_proof`
7+
```json
8+
{
9+
"name": "...",
10+
"hash-value": [...],
11+
"audit_proof": {
12+
"backend": "ethereum-gateway",
13+
"handle": "0x<tx_hash>",
14+
"event_hash": "<sha256 of canonical PublishEventRequest>",
15+
"payload_hash": "<sha256 of payload>",
16+
"payload_b64": "<base64 of payload>"
17+
}
18+
}
19+
```
20+
- RVDS 账本记录:在 ledger_receipt 中会返回与 `audit_proof` 对应的字段。
21+
- 合约地址与链信息:`ETH_CONTRACT_ADDRESS`,链 ID,RPC/浏览器入口。
22+
23+
## 步骤 1:本地重算并校验摘要
24+
1.`audit_proof` 取出 `payload_b64`,base64 解码得到 canonical `PublishEventRequest` JSON。
25+
2. 本地计算:
26+
- `sha256(payload)` → 对比 `payload_hash`
27+
- `sha256(canonical payload)` → 对比 `event_hash`
28+
若不一致,审计失败。
29+
30+
## 步骤 2:链上验证交易与事件
31+
1.`handle``tx_hash`),在浏览器或本地节点查询:
32+
- 浏览器:输入 tx_hash。
33+
- 节点:`eth_getTransactionReceipt <tx_hash>`.
34+
2. 确认交易成功,找到来自合约 `RvdsEventLog``EventRecorded` 事件。
35+
3. 解码事件参数(浏览器通常自动解码):
36+
- `eventHash` (bytes32) 应等于 `audit_proof.event_hash`
37+
- 第二个参数存储的是 `payload_b64`(当前实现直接上链 payload base64,gas 较高),可解码后再次对比 `payload_hash`
38+
39+
## 步骤 3:对照 RVPS 参考值
40+
1.`payload` 中的 `slsa_provenance` 解析 `subject[].digest`(和 RVPS 逻辑一致)。
41+
2. 确认解析出的制品哈希与 RVPS 返回的 `hash-value` 完全匹配。
42+
3. 如有多份参考值(多个 subject),逐一对应。
43+
44+
## 命令行示例
45+
假设已拿到 `tx_hash``event_hash``payload_b64`
46+
47+
```bash
48+
# 1) 解码 payload
49+
echo "<payload_b64>" | base64 -d > payload.json
50+
51+
# 2) 重算 hash
52+
PAYLOAD_HASH_LOCAL=$(sha256sum payload.json | awk '{print $1}')
53+
echo "local payload hash: $PAYLOAD_HASH_LOCAL"
54+
55+
# 3) 查询交易(需已配置 ETH_RPC_URL)
56+
curl -s -X POST "$ETH_RPC_URL" \
57+
-H "Content-Type: application/json" \
58+
-d '{
59+
"jsonrpc":"2.0",
60+
"method":"eth_getTransactionReceipt",
61+
"params":["<tx_hash>"],
62+
"id":1
63+
}' | jq .
64+
65+
# 4) 在输出中找到 logs,解码 eventHash/payload(可使用链上浏览器或 ABI 工具)
66+
```
67+
68+
## 浏览器快速校验
69+
1. 打开区块浏览器,输入 `tx_hash`
70+
2. 在 Logs/Events 中找到 `EventRecorded`
71+
- `eventHash` 对比 `audit_proof.event_hash`
72+
- data/decoded payload 对比 `payload_b64`(解码后再比对 `payload_hash`)。
73+
74+
## 注意事项与影响
75+
- 本实现将 payload(base64)直接上链,gas 成本随 payload 大小线性增加;建议在生产评估费用,或只上链摘要(当前同时附带摘要与原文)。
76+
- `audit_proof` 是可选字段,未开启账本时保持兼容(字段缺失不影响现有接口)。
77+
- 若使用其它账本(如 Rekor),只需在 `audit_proof.backend/handle` 填入对应证明,并在审计时使用相应验证工具;结构不变。
78+

rvds/docs/eth-gateway.md

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
# RVDS 以太坊网关使用指南
2+
3+
> 作用:提供一个具备签名与上链能力的 HTTP 网关,接受 RVDS 的事件摘要请求,调用链上合约 `record(bytes32 eventHash, string payloadHash)`,并返回真实交易哈希。
4+
5+
## 功能
6+
7+
- 端点:`POST /record`
8+
- 请求:
9+
```json
10+
{
11+
"event_hash": "0x<sha256 hex>", // 32字节
12+
"payload": "canonical PublishEventRequest JSON"
13+
}
14+
```
15+
- 响应:
16+
```json
17+
{ "tx_hash": "0x<real-ethereum-tx-hash>" }
18+
```
19+
- 内部逻辑:
20+
- 对 payload 做 sha256,作为 `payloadHash`
21+
- ABI 编码调用合约 `record(eventHash, payloadHash)`
22+
- 使用私钥签名交易并通过 RPC 发送,返回 tx_hash。
23+
- 默认 gas 200000,gas_price 来自链上 `eth_gasPrice`
24+
25+
## 启动
26+
27+
```bash
28+
cd /root/design/trustee/rvds
29+
cargo run --bin eth_gateway
30+
```
31+
32+
必需环境变量:
33+
- `ETH_RPC_URL`:以太坊 RPC 地址(可用公用节点或自建节点)
34+
- `ETH_PRIVATE_KEY`:0x 前缀的私钥(用于签名)
35+
- `ETH_CONTRACT_ADDRESS`:已部署的合约地址(示例见下)
36+
37+
可选环境变量:
38+
- `ETH_GATEWAY_LISTEN`:监听地址,默认 `0.0.0.0:8095`
39+
- `ETH_CHAIN_ID`:链 ID,默认 `1`
40+
41+
## 合约示例(Solidity 0.8.x)
42+
43+
```solidity
44+
// SPDX-License-Identifier: Apache-2.0
45+
pragma solidity ^0.8.17;
46+
47+
contract RvdsEventLog {
48+
event EventRecorded(bytes32 indexed eventHash, string payloadHash, address indexed sender, uint256 blockNumber);
49+
50+
function record(bytes32 eventHash, string calldata payloadHash) external {
51+
emit EventRecorded(eventHash, payloadHash, msg.sender, block.number);
52+
}
53+
}
54+
```
55+
56+
部署后将合约地址写入 `ETH_CONTRACT_ADDRESS`
57+
58+
## 与 RVDS 对接
59+
60+
在 RVDS 配置:
61+
- `RVDS_LEDGER_BACKEND=eth`
62+
- `RVDS_LEDGER_ETH_GATEWAY=http://<gateway-host>:8095/record`
63+
- `RVDS_LEDGER_ETH_GATEWAY_API_KEY`(当前未校验,可留空)
64+
65+
RVDS 在 `/rvds/rv-publish-event` 时调用网关,`ledger_receipt.handle` 将包含真实链上 `tx_hash`
66+
67+
## 生产注意
68+
69+
- 私钥务必放在可信环境,可优先使用 KMS/HSM 管理;当前示例从环境变量读取,仅适用于 PoC。
70+
- 请确认 gas 费、nonce 管理符合预期;当前实现使用链上 `gasPrice`,固定 gas=200000,可按需调整或改为 `eth_estimateGas`
71+
- 如需鉴权,可在网关增加 API Key/Token 校验,并在 RVDS 设置 `RVDS_LEDGER_ETH_GATEWAY_API_KEY`
72+

rvds/docs/flow.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
}
2424
```
2525
- 并发调用每个 Trustee 的 `https://<trustee>/api/rvps/register`
26+
- 同步将事件摘要(canonical + sha256)写入外部账本(若启用),返回 ledger 凭据。
2627
4. **校验与入库**
2728
- Trustee Gateway 将请求转给 RVPS gRPC `RegisterReferenceValue`
2829
- RVPS 通过 `slsa` extractor:

rvds/docs/ledger-design.md

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# RVDS 发布事件不可篡改账本记录设计
2+
3+
## 背景与目标
4+
5+
- 发布事件需要“公开可审计、不可篡改”地留痕(典型载体:区块链 / 透明日志)。
6+
- RVDS 在收到 `PublishEventRequest` 时,除转发给 Trustee 外,还需将事件摘要写入外部账本,并返回记录凭据。
7+
- 设计需可扩展:不同场景可接入不同账本(链、透明日志、第三方网关)。
8+
9+
## 设计概览
10+
11+
- 新增 **Ledger Recorder** 组件,核心是 `LedgerAdapter` 抽象:
12+
- `record_event(event, canonical_payload) -> LedgerReceipt`
13+
- 内置实现:`NoopLedger`(默认)、`HttpLedger`(对接外部账本网关)、`EthGatewayLedger`(通过以太坊网关写入链上日志)。
14+
- 事件哈希:
15+
- 使用 canonical JSON(对 `PublishEventRequest` 进行稳定序列化)后计算 `SHA256`,得到 `event_hash`
16+
- 账本只存摘要与最小元数据;原始业务数据仍在 RVDS/RVPS 流程内处理。
17+
- RVDS API 回包增强:
18+
- `PublishResponse` 增加 `ledger_receipt`,便于 CI 在发布日志中附带证明。
19+
20+
## 账本适配层
21+
22+
### 接口
23+
```rust
24+
pub trait LedgerAdapter {
25+
async fn record_event(&self, event: &PublishEventRequest, canonical_payload: &str) -> Result<LedgerReceipt>;
26+
}
27+
```
28+
29+
### 内置实现
30+
- `NoopLedger`:不写外部账本,返回合成的 `event_hash`
31+
- `HttpLedger`:将 `{event_hash, payload}` POST 到外部网关,由网关负责上链或写入透明日志;返回 `handle` 作为凭据。
32+
- `EthGatewayLedger`:面向以太坊链,通过网关 POST 事件,网关签名并调用链上合约,返回 `tx_hash`
33+
34+
### 选择与配置
35+
- 环境变量:
36+
- `RVDS_LEDGER_BACKEND``none`(默认)、`http``eth`
37+
- `RVDS_LEDGER_HTTP_ENDPOINT`:后端网关地址(`http` 模式必填)
38+
- `RVDS_LEDGER_HTTP_API_KEY`:可选鉴权
39+
- `RVDS_LEDGER_ETH_GATEWAY`:以太坊网关地址(`eth` 模式必填)
40+
- `RVDS_LEDGER_ETH_GATEWAY_API_KEY`:以太坊网关鉴权(可选)
41+
- 未来扩展:
42+
- 可增加 `RekorAdapter`(Sigstore 透明日志)、`EthereumAdapter`(合约记录 `event_hash`),只需实现 `LedgerAdapter` 并在工厂中注册。
43+
44+
## 时序(含账本)
45+
46+
1. CI 调用 `POST /rvds/rv-publish-event`
47+
2. RVDS 规范化序列化 payload,计算 `event_hash`
48+
3. Ledger Recorder 通过适配器写入外部账本,获得 `ledger_receipt`(可能为空)。
49+
4. RVDS 按原逻辑并发转发给各 Trustee 的 `/api/rvps/register`
50+
5. RVDS 返回:
51+
```json
52+
{
53+
"forwarded": [...],
54+
"ledger_receipt": {
55+
"backend": "http",
56+
"handle": "<opaque-proof>",
57+
"event_hash": "<sha256>"
58+
}
59+
}
60+
```
61+
6. 可选:Trustee/RVPS 存储或透传 `ledger_receipt`,便于后续审计。
62+
63+
- ## 容错与安全
64+
-
65+
- Ledger 失败策略:记录 warning 并继续转发(可根据需求改成强制失败)。
66+
- 哈希基于 canonical payload,避免字段顺序影响;业务如需更强规范,可固定字段排序/移除冗余。
67+
- 如需强制验证 ledger 成功,可在生产环境加开关:失败则拒绝发布。
68+
-
69+
- ## 实现范围(本次)
70+
-
71+
- 新增适配层与配置,默认 `none`,支持 `http` 网关写入,以及 `eth`(以太坊网关)模式。
72+
-`PublishResponse` 返回 `ledger_receipt`
73+
- 文档同步:architecture、flow 以及本设计说明。
74+
75+
## 以太坊链设计(网关模式)与合约示例
76+
77+
- 模式:RVDS 通过 `EthGatewayLedger``event_hash + payload` POST 到以太坊网关;网关负责签名并调用链上合约记录事件哈希,返回 `tx_hash`
78+
- 网关接口建议:
79+
- `POST /record` `{ "event_hash": "<hex>", "payload": "<canonical json>" }`
80+
- 返回 `{ "tx_hash": "0x..." }`
81+
- 合约示例(Solidity 0.8.x):
82+
```solidity
83+
// SPDX-License-Identifier: Apache-2.0
84+
pragma solidity ^0.8.17;
85+
86+
contract RvdsEventLog {
87+
event EventRecorded(bytes32 indexed eventHash, string payloadHash, address indexed sender, uint256 blockNumber);
88+
89+
function record(bytes32 eventHash, string calldata payloadHash) external {
90+
emit EventRecorded(eventHash, payloadHash, msg.sender, block.number);
91+
}
92+
}
93+
```
94+
- 部署与网关步骤(概要):
95+
1. 选择链(主网/测试网)并配置 RPC。
96+
2. 部署合约 `RvdsEventLog`,记录下合约地址。
97+
3. 网关持有链上账户私钥,暴露 REST 接口 `/record`
98+
-`event_hash``payloadHash`(可使用同样的 sha256/canonical)调用合约 `record`
99+
- 返回 `tx_hash` 供 RVDS 作为 `handle`
100+
4. 在 RVDS 配置:
101+
- `RVDS_LEDGER_BACKEND=eth`
102+
- `RVDS_LEDGER_ETH_GATEWAY=https://<your-eth-gateway>/record`
103+
- `RVDS_LEDGER_ETH_GATEWAY_API_KEY=<token>`(若需要)
104+
5. 审计时:根据 `event_hash` 计算后,在链上事件日志中查找 `EventRecorded`,确认对应 `tx_hash` 与区块高度。
105+

0 commit comments

Comments
 (0)