Files
zkPix/README.md
T
2026-09-14 21:19:58 -03:00

4.3 KiB

P2Pix zkTLS prover

Proves that a BB Pay Pix charge was paid by having a Primus attestor replay the bank's own GET /solicitacoes/{n} over zkTLS. The attestor signs what the bank answered: the request URL and five revealed fields (amount, settled sum, payee, Pix txId, reconciliation code). The P2Pix contract verifies that signature and the fields in release(lockID, proof). The charge is bound to P2Pix's convênio only through the numeroConvenio query of the attested URL, so the contract's URL suffix must be pinned to the URL exactly as the attestor records it. The prover holds no signing key of its own.

Variáveis de ambiente (.env, ver .env.example)

  • CLIENT_ID, CLIENT_SECRET, DEV_APP_KEY, CONVENIO: fornecidas pelo Banco do Brasil
  • ITP_OAUTH_URL, ITP_API_URL: endpoints BB Pay (homologação ou produção)
  • CLIENT_CRT, CLIENT_KEY: certificado cliente mTLS e sua chave privada (PEM)
  • PRIVATE_KEY: carteira que paga as tarefas Primus (ETH na PRIMUS_CHAIN_ID, Base Sepolia por padrão); o endereço dela é o recipient da atestação e tem que ser o prover configurado no contrato

Como rodar

bun install        # ou npm install
bun start          # ou npm start

DEBUG=true liga os logs, inclusive o registro completo de cada atestação (request, resolves, data, attConditions, additionParams, verificação).

Endpoints

POST /register

Registra um participante. Chamado pelo vendedor antes do deposit.

curl -X POST http://localhost:5000/register -H 'content-type: application/json' -d '{
  "chainID": "11155111", "tipoDocumento": 1, "numeroDocumento": 12345678900,
  "numeroConta": 1234567890123456, "numeroAgencia": 123, "tipoConta": 1, "codigoIspb": 0
}'

Retorna a resposta do BB, com numeroParticipante (usado no deposit como <chainId>-<numeroParticipante>).

POST /request

Cria a solicitação de pagamento. Chamado pelo comprador depois do lock. lockId e chainId viram o código de conciliação <chainId>-<lockId>, que o contrato exige na prova.

curl -X POST http://localhost:5000/request -H 'content-type: application/json' -d '{
  "amount": 100.00, "pixTarget": 123, "lockId": "42", "chainId": "11155111"
}'

Retorna a resposta do BB mais numeroSolicitacao (string) e textoQrCode.

GET /release/{numeroSolicitacao}

Prova de pagamento Pix. Chamado pelo comprador depois de pagar.

  • 402 enquanto o banco não confirma o pagamento
  • 202 enquanto a atestação está sendo produzida (15 s a 1 min)
  • 200 com a prova
  • 502 banco ou Primus falharam de forma definitiva; 503 vale repetir
curl -i http://localhost:5000/release/1408799
{
  "numeroSolicitacao": "1408799",
  "proof": {
    "recipient": "0x…", "attestor": "0x…",
    "data": "{\"amount\":\"100\",…}",
    "timestamp": 1766377317483,
    "additionParams": "{\"algorithmType\":\"proxytls\"}",
    "attConditions": "",
    "signature": "0x…", "taskId": "0x…", "reportTxHash": "0x…",
    "requests": [{ "url": "…", "header": "", "method": "GET", "body": "" }],
    "responseResolves": [[…]],
    "selfVerified": true, "contractRebuildMatches": true
  }
}

release(lockID, proof) takes numeroSolicitacao, recipient, data, timestamp, additionParams, attConditions, attestor and signature; the rest is evidence. selfVerified means the signature recovers the attestor over the returned struct; contractRebuildMatches means the contract's rebuild rules (empty header and body, GET) reproduce it.

bun run digest-check <release-body.json> recomputes the digest of a saved answer and prints the URL, header, parseType and data layout the contract constants are pinned to.

mTLS

CLIENT_CRT is the certificate chain BB has on file for this application and CLIENT_KEY its private key, both PEM. Register a dedicated client certificate for the prover; the attested requests run through the Primus attestor, so the key material should not be the company e-CNPJ. To extract a key-only PEM from a PKCS#12 file:

umask 077
openssl pkcs12 -in <arquivo>.p12 -legacy -nocerts -noenc -out client.key
openssl pkcs12 -in <arquivo>.p12 -legacy -nokeys -out client.crt

The *.mtls.api.*.bb.com.br hosts present a publicly trusted chain, so no extra CA is needed; set BB_CA only for hosts signed by BB's own CA.