feat: seller receipt signing (EIP-191) for PurchaseLog - #63
feat: seller receipt signing (EIP-191) for PurchaseLog#63M2M-TRC8004-Registry wants to merge 1 commit into
Conversation
Implement ECDSA receipt signing so sellers can attest to purchases on-chain via PurchaseLog.sol. The seller signs a digest of (listingId, buyerAgentId, paymentHash, amount, chainId, contractAddress) using EIP-191 personal-sign, and the buyer submits this signature to PurchaseLog.logPurchase() for on-chain verification. Key changes: - New receipt_signer.py: compute_receipt_digest() and sign_receipt() - SellerSigningConfig for endpoint-level configuration - FastAPI middleware: auto-sign receipts after successful settlement - paymentHash = SHA-256 of PAYMENT-SIGNATURE header (not tx hash) - uint32 overflow validation for listingId and buyerAgentId - validAfter -= 60s to prevent facilitator timing edge cases - ReceiptSignatureData types added to Python and TypeScript SDKs
|
|
Thanks for the contribution and for the detailed PurchaseLog receipt-signing work. We’re going to close this PR as not planned for now. The feature is useful, but the implementation couples an application-specific PurchaseLog receipt format directly into the core x402 FastAPI middleware and shared If we revisit seller receipt signing, we’d likely bring it back as a separate extension or app-level helper with explicit tests and a design that works across the current Python and TypeScript middleware layers, rather than embedding PurchaseLog-specific behavior in the generic settlement response. Thanks again for the thoughtful implementation and e2e validation. |
Summary
receipt_signer.py: Implementscompute_receipt_digest()andsign_receipt()for EIP-191 personal-sign overkeccak256(abi.encode(listingId, buyerAgentId, paymentHash, amount, chainId, contractAddress)), matchingPurchaseLog.sol's on-chain verification.SellerSigningConfigparameter tox402_protected(). After successful settlement, the middleware auto-signs a receipt and includes it in thePAYMENT-RESPONSEheader asreceiptSignature.paymentHash= SHA-256 ofPAYMENT-SIGNATUREheader: The payment hash is derived from the buyer's raw payment header (not the settlement tx hash), ensuring a cryptographic binding between the x402 payment and the on-chain purchase record.ReceiptSignatureDataadded to both SDKs'SettleResponse.validAfter = now - 60to prevent facilitatornot_yet_validrace conditions.Security
listingIdandbuyerAgentIdbefore signingchainId+address(this)in digest prevents cross-chain / cross-contract replays ≤ half-orderenforced by eth-account's signing library (malleability guard)Usage
Test plan
verified: truepaymentHashmatches across seller middleware, buyer receipt, and on-chain submission