协议
完整规范见 proxy-shopping-go 中的 docs/spec.md。本页概括其要点。
密钥
所有密钥都由同一个助记词(BIP39)派生,每种用途一个(均为 secp256k1)。
| 用途 | 路径 |
|---|---|
| 身份(Nostr) | m/44'/1237'/0'/0/0(NIP-06) |
| libp2p | m/7333'/0'/0' |
| BTC 订单密钥(用户、代购者) | m/7333'/1'/{idx}'(idx 由订单 ID 的哈希得出) |
| BTC 订单密钥(托管方) | m/7333'/2'/{idx}。xpub 是公开的,因此即使托管方离线,其他人也能派生出它 |
| BTC 钱包 | m/84'/1'/0'/0/0 |
| EVM | m/44'/60'/0'/0/0 |
信任
| kind | 签名者 | 内容 |
|---|---|---|
| 30500 | 协调者(coordinator) | 对运营者的委托;用 revoked 撤销 |
| 30501 | 运营者(operator) | 地区 × 代购者 × 托管方列表、推荐的中继和链端点 |
| 30502 / 30503 | 代购者(shopper) / 托管方(escrow) | 资料(费用、现金地区、xpub、收款地址) |
| 10050 | 所有人 | 自己接收消息所用的中继 |
由 v 标签的版本决定哪个更新(通常是签名时的 UNIX 时间)。没有任何东西会过期。
事件同时通过 Nostr 中继和 libp2p gossipsub 传播;Go 节点会把从一方收到的内容转发到另一方。
消息
消息用 NIP-59 封装(gift wrap → seal → 内容)。 内容是一个已签名的事件(kind 5400),这样托管方在纠纷中可以作为第三方验证它。
- 一条消息至少发往接收者收件中继中的 k 个(默认 2 个)。
- 接收者用
ack回复;发送者会一直重发,直到收到回复。 - 一条消息最多 28000 字节。截图等大型证据只以哈希引用;
在纠纷中会以
attachment消息分块发给托管方。
order.request + order.escrow_key → order.quote → order.accept → (funding) → order.funded + escrow.notice
→ order.purchased → order.shipping → order.release → order.completed
cancel and refund: order.cancel (before funding), order.refund (cooperative refund from the shopper)
other: ack (receipt), chat
dispute: dispute.open → dispute.evidence_request → dispute.evidence (+ attachment) → dispute.ruling → dispute.countersigned
report: report (to the operator)
BTC(P2WSH)
OP_IF
OP_2 <user> <shopper> <escrow> OP_3 OP_CHECKMULTISIG
OP_ELSE
OP_IF <T1> OP_CHECKLOCKTIMEVERIFY OP_DROP <shopper> OP_CHECKSIG
OP_ELSE <T2> OP_CHECKLOCKTIMEVERIFY OP_DROP <user> OP_CHECKSIG
OP_ENDIF
OP_ENDIF
T1 < T2(区块高度)。如果用户一直不确认收货且 T1 已过,代购者可以单独取走资金。 如果代购者消失,用户在 T2 之后可以单独取回资金。 托管方必须在 T1 之前对纠纷作出裁决。
USDC(Safe v1.4.1)
- 每笔订单对应一个有三个所有者、阈值为二的 Safe。
- 它的地址来自 CREATE2,因此可以根据订单 ID 预先计算出来。
- 时间锁以 Safe 模块(
PSEscrowModule)的形式实现。- t1 之后,代购者可以用
claimByShopper取走资金。 - t2 之后,用户可以用
refundToUser取回资金。
- t1 之后,代购者可以用
- 付款和裁决都是用 EIP-712 签名的 SafeTx。裁决的分配使用
MultiSendCallOnly。
把身份绑定到密钥
每个订单请求(order.request)都带有一个 key_proof:
由进入多签的链上密钥(BTC 订单密钥或 EVM 账户)作出的签名,
证明该密钥与 Nostr 身份属于同一个人。
没有它,另一个身份就可以把用户的公钥复制到自己的请求里,并向托管方声称自己就是该用户。
收货地址
地址用一次性密钥 K 加密(XChaCha20-Poly1305)。
- K 分别用 NIP-44 为代购者和托管方各封装一份。
- 托管方的那份不在请求中:它通过
order.escrow_key交给代购者(请求中只带它的哈希)。 发生纠纷时,由代购者(或用户)把它交给托管方,因此对于没有纠纷的订单,托管方无法读取地址。
地区
代码按前缀匹配:JP > JP-13(东京都)> JP-13-13104(新宿区)。
市区町村一级使用日本的地方公共团体代码。