プロトコル
完全な仕様は proxy-shopping-go の docs/spec.md にあります。ここでは要点だけをまとめます。
鍵
1 つのニーモニック(BIP39)から、用途ごとの鍵を導出します(すべて secp256k1)。
| 用途 | パス |
|---|---|
| 身元(Nostr) | m/44'/1237'/0'/0/0(NIP-06) |
| libp2p | m/7333'/0'/0' |
| BTC の注文鍵(利用者・shopper) | m/7333'/1'/{idx}'(idx は注文 ID のハッシュから決まる) |
| BTC の注文鍵(escrow) | m/7333'/2'/{idx}。xpub を公開するので、escrow がオフラインでも相手が導出できる |
| BTC の財布 | m/84'/1'/0'/0/0 |
| EVM | m/44'/60'/0'/0/0 |
信頼
| kind | 署名者 | 内容 |
|---|---|---|
| 30500 | coordinator | operator への委任書。revoked で失効させる |
| 30501 | operator | 地域 × shopper × escrow の一覧、推奨するリレーとチェーンの接続先 |
| 30502 / 30503 | shopper / escrow | プロフィール(手数料、現金で行ける地域、xpub、受け取りアドレス) |
| 10050 | 各主体 | 自分宛てのメッセージを受け取るリレー |
新旧は v タグのバージョンで決めます(ふつうは署名した時刻の UNIX 秒)。有効期限は持ちません。
配布は Nostr リレーと libp2p の gossipsub の両方で行い、Go ノードは一方で受け取ったものをもう一方へ中継します。
メッセージ
NIP-59(gift wrap → seal → 中身)で包みます。 中身は 署名付き のイベント(kind 5400)にします。紛争のとき、escrow が第三者として検証できるようにするためです。
- 受信箱のリレーのうち、k 個(既定 2)以上に送ります。
- 受け手は
ackを返し、送り手は ack が来るまで再送します。 - 1 通は 28000 byte までです。スクリーンショットのような大きい証拠は、ハッシュだけをメッセージに載せます。
紛争のときに、
attachmentとして分けて escrow に送ります。
order.request + order.escrow_key → order.quote → order.accept → (入金)→ order.funded + escrow.notice
→ order.purchased → order.shipping → order.release → order.completed
取り消し・払い戻し: order.cancel(入金前), order.refund(shopper からの協力的な払い戻し)
その他: ack(受領), chat
紛争: dispute.open → dispute.evidence_request → dispute.evidence (+ attachment) → dispute.ruling → dispute.countersigned
通報: report(operator 宛て)
BTC(P2WSH)
OP_IF
OP_2 <利用者> <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 <利用者> OP_CHECKSIG
OP_ENDIF
OP_ENDIF
T1 < T2(ブロック高)です。利用者が受け取り確認をしないまま T1 を過ぎると、shopper が単独で受け取れます。 shopper が消えたときは、T2 を過ぎると利用者が単独で取り戻せます。 escrow は、紛争を T1 より前に裁定する義務を負います。
USDC(Safe v1.4.1)
- 注文ごとに、所有者 3 人・しきい値 2 の Safe を作ります。
- アドレスは CREATE2 で決まるので、注文 ID から事前に計算できます。
- タイムロックは Safe のモジュール(
PSEscrowModule)で実装しています。- t1 以降は、shopper が
claimByShopperで受け取れます。 - t2 以降は、利用者が
refundToUserで取り戻せます。
- t1 以降は、shopper が
- 支払いと裁定は EIP-712 で署名した SafeTx です。裁定の分割には
MultiSendCallOnlyを使います。
身元と鍵の結び付け
注文の依頼(order.request)には key_proof を付けます。
Nostr の身元と、多重署名に入れるチェーンの鍵(BTC の注文鍵、または EVM のアカウント)が同じ人のものであることを、チェーンの鍵の署名で示します。
これが無いと、別の身元が利用者の公開鍵を写した依頼を作り、escrow に「自分が利用者だ」と名乗れてしまいます。
住所
届け先は使い捨ての鍵 K で暗号化します(XChaCha20-Poly1305)。
- K は、shopper 宛てと escrow 宛てに、それぞれ NIP-44 で包みます。
- escrow 宛てのものは依頼には入れず、
order.escrow_keyで shopper に預けます(依頼にはそのハッシュだけを入れます)。 紛争のときに shopper(または利用者)が escrow に渡すので、紛争の無い注文では escrow は住所を読めません。
地域
JP > JP-13(東京都)> JP-13-13104(新宿区)のように、前方一致で照合します。
市区町村の段は、全国地方公共団体コードを使います。