Proposal to add Merge Avoidance extension to Payment Protocol
The motivation behind the proposed extension is to encourage
Merge Avoidance in Bitcoin usage, by having intermediary steps, between the PaymentRequest message from the merchant's server and the Payment message from the customer's wallet app, wherein the customer's wallet app notifies the merchant's server of how many UTXOs they will spend to satisfy the payment request, and the merchant's server subsequently provides a corresponding number of receiving Bitcoin addresses (Outputs in the Payment Protocol) for the customer's wallet app to send the payment to.
By matching the number of receiving Bitcoin addresses with the number of UTXOs spent, the merging of outputs from the customer's wallet app is avoided.
The proposed additions to the payment protocol are:
new 'optional uint64 total_amount' field in the PaymentDetails message.
This will be field 8 in the PaymentDetails message:
message PaymentDetails {
optional string network = 1 [default = "main"]; // "main" or "test"
repeated Output outputs = 2; // Where payment should be sent
required uint64 time = 3; // Timestamp; when payment request created
optional uint64 expires = 4; // Timestamp; when this request should be considered invalid
optional string memo = 5; // Human-readable description of request for the customer
optional string payment_url = 6; // URL to send OutputDetails and get AddressDetails
optional bytes merchant_data = 7; // Arbitrary data to include in the OutputDetails and Payment messages
optional uint64 total_amount = 8 // total amount requested in integer-number-of-satoshis
}
new OutputDetails message that is sent by the customer's wallet app:
message OutputDetails {
required uint32 output_number = 1 // Number of UTXOs payer will use to pay PaymentDetails.total_amount
optional bytes merchant_data = 2 // From PaymentDetails.merchant_data
}
new PaymentRequestFinal message that is sent by the merchant's server:
message PaymentRequestFinal {
optional uint32 payment_details_version = 1 [default = 1];
optional string pki_type = 2 [default = "none"]; // none / x509+sha256 / x509+sha1
optional bytes pki_data = 3; // depends on pki_type
required bytes serialized_address_details = 4; // AddressDetails
optional bytes signature = 5; // pki-dependent signature
}
new AddressDetails message that is wrapped in the PaymentRequestFinal message that is sent by the merchant's server:
message AddressDetails {
repeated Output outputs = 1 // Where payemnts should be sent, number of Outputs should match OutputDetails.output_number
optional bytes merchants data = 2 // From PaymentDetails.merchant_data
}
The flow of the payment protocol with the Merge Avoidance extension is:
1. When the PaymentDetails message is sent, the new PaymentDetails.total_amount field notifies the customer's wallet app the total amount to be paid.
2. If the customer's wallet app supports the Merge Avoidance extension, it sends an OutputDetails message to notifies the merchant's server how many UTXOs they will spend to satisfy the total amount requested to be paid. If the customer's wallet app does not support the extension, they proceed according to the original protocol, and send the Payment message.
3. If the customer's wallet app sends an OutputDetails message, the merchant's server responds with a PaymentRequest_Final message which contains an AddressDetails message notifying the customer's wallet app of which bitcoin addresses to make the payment to.
4. The customer's wallet app spends each UTXO to a different receiving address, which enables merging of outputs at common addresses to be avoided. From this step onward, the protocol works like the original version, as the customer's wallet app sends the Payment message and optionally publishes the payment transaction(s) to the Bitcoin P2P network