Regardless, I think this highlights some shortcomings in the payment protocol as it stands. It's been designed with a focus on merchants and as such is overly limited in its use for different use-cases. At its heart, it provides a mechanism for building a specific type of transaction between two parties without the users having to mess around with raw transactions. If you think a little bigger, you can cover the case of arbitrary transaction building and signing between multiple (not just 2) parties which subsumes the use-cases already catered for.
The current idea is that the merchant specifies which outputs the user should pay to and expects the transaction to be returned complete and signed.
The idea I've just come up with is that a general transaction (not just outputs) is passed around being build over a number of exchanges without the client software needing to know anything about how the exchange should happen. Signatures are not necessarily required, so arbitrary transactions can be built between multiple clients and a single server, allowing users to review the final transaction before authorizing it.
The thing that gets passed around is a transaction and some details about how the client should further build the transaction - what it should add to the transaction or if it should sign it. Wrap this as before with other useful details like the url, pki-sign etc.
message BuildDetails {
// max number of inputs to add. Thus zero prevents adding inputs, one allows
// enforcement of SIGHASH_SINGLE, other values to prevent huge dust txns etc
optional uint_64 maxInputs;
// total value of the inputs you need to provide
optional uint_64 inputsValue;
// max number of outputs to add (thus zero prevents adding outputs etc)
optional uint_64 maxOutputs;
// total value of the outputs you need to provide
optional uint_64 outputsValue;
// whether you need to sign the inputs
required boolean sign;
// how to sign them
optional uint_8 sigHash;
}
message TxBuilder {
optional bytes transaction;
required BuildDetails buildDetails;
}
Now, in the standard use-case, originally the merchant creates the outputs he wants and wraps them in a PaymentDetails object and signs it, creating a PaymentRequest.
He sends it to the user who's client interprets this to mean 'I should add some inputs to pay for those outputs, (and maybe add an output for my change), sign it, and then send it back to the url given'. This interpretation is all implicit and built in and thus is limiting.
With the TxBuilder approach the interpretation is explicit.
The merchant takes the outputs he wants as before and creates a transaction. He wants the user to provide inputs who's value matches his outputs, so he specifies the 'inputsValue' and he wants the transaction to be signed, so he specifies this too. He doesn't care about additional outputs (maybe he cares about not creating a huge transaction, so limits outputs to 1 - whatever).
The user's client can read the build details and determine that it wants him to provide input of a certain value, is free to add outputs how he pleases and should sign the result.
My solution to Sergio's use case is also possible now:
Merchant creates a Tx with the output for his payment (maybe not with his change output yet). He specifies the value that the inputs should total and specifies that the transaction should NOT be signed.
The user's client can easily determine what is required and inform the user of the details if need be (as no signature is needed, there is little harm either way). The user agrees and the client fills in the inputs, adds a change output for itself and sends the transaction back.
The merchant can then add his fee payment input and change output. He specifies 0 inputs or outputs are to be added, and specifies to sign the transaction with SIGHASH_ALL.
The users client can then display the details of the final transaction and ask if the user agrees to sign. If so, it returns the almost completed transaction to the merchant who signs it himself (or of course he signs it in the previous step and gives up his ability to refuse the transaction).
The merchant can finally issue an acknowledgement as before so that the user knows that the exchange is complete and its status.
EDIT: @Sergio, sorry for hijacking