Protocolo
A especificação completa é docs/spec.md no proxy-shopping-go. Esta página resume o essencial.
Chaves
Todas as chaves são derivadas de um único mnemônico (BIP39), uma por finalidade (todas secp256k1).
| Finalidade | Caminho |
|---|---|
| identidade (Nostr) | m/44'/1237'/0'/0/0 (NIP-06) |
| libp2p | m/7333'/0'/0' |
| chave BTC do pedido (usuário, comprador) | m/7333'/1'/{idx}' (idx vem de um hash do ID do pedido) |
| chave BTC do pedido (custodiante) | m/7333'/2'/{idx}. O xpub é público, então outros podem derivá-la enquanto o custodiante está offline |
| carteira BTC | m/84'/1'/0'/0/0 |
| EVM | m/44'/60'/0'/0/0 |
Confiança
| kind | Assinado por | Conteúdo |
|---|---|---|
| 30500 | coordenador (coordinator) | delegação a um operador; revogada com revoked |
| 30501 | operador (operator) | lista região × comprador × custodiante, relays e endpoints de blockchain recomendados |
| 30502 / 30503 | comprador (shopper) / custodiante (escrow) | perfil (taxas, regiões de pagamento em dinheiro, xpub, endereços de recebimento) |
| 10050 | todos | os relays onde cada um recebe mensagens |
A versão na tag v decide qual é a mais nova (normalmente o horário UNIX da assinatura). Nada expira.
Os eventos trafegam tanto pelos relays Nostr quanto pelo gossipsub do libp2p; os nós em Go repassam para um o que recebem do outro.
Mensagens
As mensagens são embrulhadas com NIP-59 (gift wrap → seal → conteúdo). O conteúdo é um evento assinado (kind 5400), para que um custodiante possa verificá-lo como terceiro em uma disputa.
- Uma mensagem vai para pelo menos k (padrão 2) dos relays de caixa de entrada do destinatário.
- O destinatário responde com um
ack; o remetente reenvia até recebê-lo. - Uma mensagem tem no máximo 28000 bytes. Provas grandes, como capturas de tela, são referenciadas apenas por hash;
em uma disputa, são enviadas ao custodiante em partes, como mensagens
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 (alturas de bloco). Se o usuário nunca confirmar o recebimento e T1 passar, o comprador pode sacar os fundos sozinho. Se o comprador sumir, o usuário pode reavê-los sozinho depois de T2. O custodiante precisa decidir uma disputa antes de T1.
USDC (Safe v1.4.1)
- Cada pedido recebe um Safe com três donos e limite (threshold) de dois.
- Seu endereço vem do CREATE2, então pode ser calculado com antecedência a partir do ID do pedido.
- Os timelocks são implementados como um módulo do Safe (
PSEscrowModule).- Depois de t1, o comprador pode sacar os fundos com
claimByShopper. - Depois de t2, o usuário pode reavê-los com
refundToUser.
- Depois de t1, o comprador pode sacar os fundos com
- Pagamentos e decisões são SafeTxs assinadas com EIP-712. A divisão de uma decisão usa
MultiSendCallOnly.
Vinculando a identidade às chaves
Cada solicitação de pedido (order.request) traz um key_proof:
uma assinatura feita pela chave de blockchain que entra na multisig (a chave BTC do pedido ou a conta EVM),
mostrando que ela pertence à mesma pessoa que a identidade Nostr.
Sem isso, outra identidade poderia copiar as chaves públicas do usuário para a própria solicitação e alegar ao custodiante que é o usuário.
Endereço de entrega
O endereço é criptografado com uma chave de uso único K (XChaCha20-Poly1305).
- K é embrulhada com NIP-44 para o comprador e, separadamente, para o custodiante.
- A cópia do custodiante não faz parte da solicitação: ela é entregue ao comprador em
order.escrow_key(a solicitação traz apenas o hash dela). O comprador (ou o usuário) a repassa ao custodiante em uma disputa, então o custodiante não consegue ler o endereço de pedidos sem disputa.
Regiões
Os códigos são comparados por prefixo: JP > JP-13 (Tóquio) > JP-13-13104 (Shinjuku).
O nível de município usa os códigos de governos locais do Japão.