What do you gain by making PoPs actually valid transactions? You could for example change the signature hashing algorithm (prepend a constant string, or add a second hashing step) for signing, rendering the signatures in a PoP unusable for actual transaction, while still committing to the same actual transaction. That would also remove the need for the OP_RETURN to catch fees. Also, I would call it "proof of transaction intent", as it's a commitment to a transaction and proof of its validity, but not a proof that an actual transaction took place, nor a means to prevent it from being double spent. On Sat, Jun 6, 2015 at 4:35 PM, Kalle Rosenbaum wrote: > Hi > > Following earlier posts on Proof of Payment I'm now proposing the > following BIP (To read it formatted instead, go to > https://github.com/kallerosenbaum/poppoc/wiki/Proof-of-Payment-BIP). > > Regards, > Kalle Rosenbaum > >
>   BIP: 
>   Title: Proof of Payment
>   Author: Kalle Rosenbaum 
>   Status: Draft
>   Type: Standards Track
>   Created: 
> 
> > == Abstract == > > This BIP describes how a wallet can prove to a server that it has the > ability to sign a certain transaction. > > == Motivation == > > There are several scenarios in which it would be useful to prove that you > have paid for something. For example: > > * A pre-paid hotel room where your PoP functions as a key to the door. > * An online video rental service where you pay for a video and watch it on > any device. > * An ad-sign where you pay in advance for e.g. 2 weeks exclusivity. During > this period you can upload new content to the sign whenever you like using > PoP. > * Log in to a pay site using a PoP. > * A parking lot you pay for monthly and the car authenticates itself using > PoP. > * A lottery where all participants pay to the same address, and the winner > is selected among the transactions to that address. You exchange the prize > for a PoP for the winning transaction. > > With Proof of Payment, these use cases can be achieved without any > personal information (user name, password, e-mail address, etc) being > involved. > > == Rationale == > > Desirable properties: > > # A PoP should be generated on demand. > # It should only be usable once to avoid issues due to theft. > # It should be able to create a PoP for any payment, regardless of script > type (P2SH, P2PKH, etc.). > # It should prove that you have enough credentials to unlock all the > inputs of the proven transaction. > # It should be easy to implement by wallets and servers to ease adoption. > > Current methods of proving a payment: > > * In BIP0070, the PaymentRequest together with the transactions fulfilling > the request makes some sort of proof. However, it does not meet 1, 2 or 4 > and it obviously only meets 3 if the payment is made through BIP0070. Also, > there's no standard way to request/provide the proof. If standardized it > would probably meet 5. > * Signing messages, chosen by the server, with the private keys used to > sign the transaction. This could meet 1 and 2 but probably not 3. This is > not standardized either. 4 Could be met if designed so. > > If the script type is P2SH, any satisfying script should do, just like for > a payment. For M-of-N multisig scripts, that would mean that any set of M > keys should be sufficient, not neccesarily the same set of M keys that > signed the transaction. This is important because strictly demanding the > same set of M keys would undermine the purpose of a multisig address. > > == Specification == > > === Data structure === > > A proof of payment for a transaction T, here called PoP(T), is used to > prove that one has ownership of the credentials needed to unlock all the > inputs of T. It has the exact same structure as a bitcoin transaction with > the same inputs and outputs as T and in the same order as in T. There is > also one OP_RETURN output inserted at index 0, here called the pop output. > This output must have the following format: > > OP_RETURN > > {| > ! Field !! Size [B] !! Description > |- > | <version> || 2 || Version, little endian, currently 0x01 0x00 > |- > | <txid> || 32 || The transaction to prove > |- > | <nonce> || 6 || Random data > |} > > The value of the pop output is set to the same value as the transaction > fee of T. Also, if the outputs of T contains an OP_RETURN output, that > output must not be included in the PoP because there can only be one > OP_RETURN output in a transaction. The value of that OP_RETURN output is > instead added to the value of the pop output. > > An illustration of the PoP data structure and its original payment is > shown below. > >
>   T
>  +----------------------------------------------+
>  |inputs       | outputs                        |
>  |       Value | Value   Script                 |
>  +----------------------------------------------+
>  |input0 1     |     0   pay to A               |
>  |input1 3     |     2   OP_RETURN   |
>  |input2 4     |     1   pay to B               |
>  |             |     4   pay to C               |
>  +----------------------------------------------+
>
>   PoP(T)
>  +----------------------------------------------------------+
>  |inputs       | outputs                                    |
>  |       Value | Value   Script                             |
>  +----------------------------------------------------------+
>  |input0 1     |     3   OP_RETURN    |
>  |input1 3     |     0   pay to A                           |
>  |input2 4     |     1   pay to B                           |
>  |             |     4   pay to C                           |
>  +----------------------------------------------------------+
> 
> > The PoP is signed using the same signing process that is used for bitcoin > transactions. > > The purpose of the nonce is to make it harder to use a stolen PoP; Once > the PoP has reached the server, that PoP is useless since the server will > generate a new nonce for every PoP request. > > Since a PoP is indistinguishable from a bitcoin transaction, there is a > risk that it, accidently or maliciously, enters the bitcoin p2p network. If > T is still unconfirmed, or if a reorg takes place, chances are that PoP(T) > ends up in a block, invalidating T. Therefore it is important that the > outputs of the PoP are the same as in T. The zero transaction fee in PoP(T) > is to minimize the incentives for miners to select PoP(T) for inclusion. > > === Process === > > # A proof of payment request is sent from the server to the wallet. The > PoP request contains: > ## a random nonce > ## a destination where to send the PoP, for example a https URL > ## data hinting the wallet which transaction to create a proof for. For > example: > ##* txid, if known by the server > ##* PaymentRequest.PaymentDetails.merchant_data (in case of a BIP0070 > payment) > ##* amount, label, message or other information from a BIP0021 URL > # The wallet identifies a transaction T, if possible. Otherwise it asks > the user to select among the ones that match the hints in 1.iii. > # The wallet creates an unsigned PoP (UPoP) for T, and asks the user to > sign it. > # The user confirms > # The UPoP(T) is signed by the wallet, creating PoP(T). > # The PoP is sent to the destination in 1.ii. > # The server receiving the PoP validates it and responds with “valid” or > “invalid”. > # The wallet displays the response in some way to the user. > > '''Remarks:''' > > * The method of transferring the PoP request at step 1 is not specified > here. Instead that is specified in separate specifications. See [btcpop > scheme BIP](btcpop scheme BIP). > * The nonce must be randomly generated by the server for every new PoP > request. > > === Validating a PoP === > > The server needs to validate the PoP and reply with "valid" or "invalid". > That process is outlined below. If any step fails, the validation is > aborted and "invalid" is returned: > > # Check the format of the PoP. It must pass normal transaction checks, > except that the inputs may already be spent. > # Check the PoP output at index 0. It must conform to the OP_RETURN output > format outlined above. > # Check that the rest of the outputs exactly corresponds to the outputs of > T and that they appear in the same order as in T. An exception to this is > that any OP_RETURN outputs of T must not be included in the PoP. All output > value from the OP_RETURN must instead be included in the PoP output. > # Check that the nonce is the same as the one you requested. > # Check that the inputs of the PoP are exactly the same as in transaction > T, and in the same order. > # Check the scripts of all the inputs, as would be done on a normal > transaction. > # Check that the txid in the PoP output is the transaction you actually > want proof for. If you don’t know exactly what transaction you want proof > for, check that the transaction actually pays for the product/service you > deliver. > # Return "valid". > > == Security considerations == > > * Someone can intercept the PoP-request and change the PoP destination so > that the user sends the PoP to the bad actor. > * Someone can intercept the PoP-request and change for example the txid to > trick the user to sign a PoP for another transaction than the intended. > This can of course be avoided if the user is actually looking at the UPoP > before signing it. The bad actor could also set hints for a transaction, > existing or not, that the user didn’t make, resulting in a broken service. > * Someone can steal a PoP and try to use the service hoping to get a > matching nonce. Probability per try: 1/(2^48). The server should have a > mechanism for detecting a brute force attack of this kind, or at least slow > down the process by delaying the PoP request by some 100 ms or so. > * Even if a wallet has no funds it might still be valuable as a generator > for PoPs. This makes it important to keep the security of the wallet after > it has been emptied. > * Transaction malleability may cause the server to have another > transaction id than the wallet for the payment. In that case the wallet > will not be able to prove the transaction for the server. Wallets should > not rely on the transaction id of the outgoing transaction. Instead it > should listen for the transaction on the network and put that in its list > of transactions. > > The first two issues are the same attack vector as for traditional, ie > BIP0021, bitcoin payments. They could be mitigated by using secure > connections. > > == Reference implementation == > > [https://github.com/kallerosenbaum/poppoc poppoc on GitHub] > > [https://github.com/kallerosenbaum/wallet Mycelium fork on GitHub] > > == References == > > [https://github.com/bitcoin/bips/blob/master/bip-0021.mediawiki BIP0021]: > URI Scheme > > [https://github.com/bitcoin/bips/blob/master/bip-0070.mediawiki BIP0070]: > Payment Protocol > > [[btcpop scheme BIP]] > > > > ------------------------------------------------------------------------------ > > _______________________________________________ > Bitcoin-development mailing list > Bitcoin-development@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/bitcoin-development > >