Протокол
Полная спецификация — docs/spec.md в proxy-shopping-go. На этой странице кратко изложено главное.
Ключи
Все ключи выводятся из одной мнемоники (BIP39), по одному на каждое назначение (все secp256k1).
| Назначение | Путь |
|---|---|
| идентичность (Nostr) | m/44'/1237'/0'/0/0 (NIP-06) |
| libp2p | m/7333'/0'/0' |
| BTC-ключ заказа (пользователь (user), покупатель-посредник (shopper)) | m/7333'/1'/{idx}' (idx берётся из хеша ID заказа) |
| BTC-ключ заказа (гарант (escrow)) | 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 | покупатель-посредник / гарант | профиль (комиссии, регионы для наличных, 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 покупатель-посредник может забрать средства через
- Выплаты и решения — это SafeTx, подписанные по EIP-712. Раздел средств по решению использует
MultiSendCallOnly.
Привязка идентичности к ключам
Каждый запрос заказа (order.request) содержит key_proof:
подпись ключом блокчейна, который входит в мультиподпись (BTC-ключ заказа или EVM-аккаунт),
показывающую, что он принадлежит тому же человеку, что и идентичность Nostr.
Без неё другая идентичность могла бы скопировать открытые ключи пользователя в свой запрос и заявить гаранту, что она и есть пользователь.
Адрес доставки
Адрес шифруется одноразовым ключом K (XChaCha20-Poly1305).
- K оборачивается по NIP-44 для покупателя-посредника и отдельно для гаранта.
- Копия для гаранта не входит в запрос: она передаётся покупателю-посреднику в
order.escrow_key(в запросе есть только её хеш). В споре покупатель-посредник (или пользователь) передаёт её гаранту, поэтому гарант не может прочитать адрес в заказах без спора.
Регионы
Коды сопоставляются по префиксу: JP > JP-13 (Токио) > JP-13-13104 (Синдзюку).
Уровень муниципалитетов использует японские коды органов местного самоуправления.