Received: from sog-mx-1.v43.ch3.sourceforge.com ([172.29.43.191] helo=mx.sourceforge.net) by sfs-ml-4.v29.ch3.sourceforge.com with esmtp (Exim 4.76) (envelope-from ) id 1WIVYd-0008Tl-LB for bitcoin-development@lists.sourceforge.net; Wed, 26 Feb 2014 03:53:19 +0000 Received-SPF: pass (sog-mx-1.v43.ch3.sourceforge.com: domain of kill-bill.org designates 209.85.160.46 as permitted sender) client-ip=209.85.160.46; envelope-from=stephane@kill-bill.org; helo=mail-pb0-f46.google.com; Received: from mail-pb0-f46.google.com ([209.85.160.46]) by sog-mx-1.v43.ch3.sourceforge.com with esmtps (TLSv1:RC4-SHA:128) (Exim 4.76) id 1WIVYb-0002KV-F9 for bitcoin-development@lists.sourceforge.net; Wed, 26 Feb 2014 03:53:19 +0000 Received: by mail-pb0-f46.google.com with SMTP id um1so391536pbc.5 for ; Tue, 25 Feb 2014 19:53:11 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:content-type:mime-version:subject:from :in-reply-to:date:cc:message-id:references:to; bh=Go9SX7rLPg9GTGqTc6W3tyIdo3a6QxZwGJYtsul8ddM=; b=jqKVC3XVImfkSZFvfG2iHsmtoudK/FEcLcwf07h6igwAAX4ozAoIWEzwlwgwd7ZgI0 fuZGaCy0Qh1ye7GUoTtUDjUak9DQZM4COowQXvnlbzx7XWWvXVH6IBr9HE3c3dPOWhhy hFRbdY/eX7XAaCl0+1ofGzGiSl38CBSZ/Uwgrd9EXYeYBuixvr5VWcbCT7n9JIL0huMU lv8W9ZVgQK7bNlzGBqislijtKHyPedO+adOLVlvV6L2Bf+pFUcskMwQVv3peyaZT8bCf THLHD0/w8Jryzehc/ywIK+xEyEE9EDm2ojXvJuqrSLUkI4ZgKlO/Pjf9lI3OYFM+2UX5 2sOQ== X-Gm-Message-State: ALoCoQk879B7jk+tpKoDoetD/KuEeTEgZoZtS3Prq4c+x9hP0UEKRSJrAtsE2idnX4/JcDZyr6yn X-Received: by 10.66.148.230 with SMTP id tv6mr5774664pab.155.1393386791528; Tue, 25 Feb 2014 19:53:11 -0800 (PST) Received: from [192.168.1.107] (adsl-71-146-11-193.dsl.pltn13.sbcglobal.net. [71.146.11.193]) by mx.google.com with ESMTPSA id bc4sm15896882pbb.2.2014.02.25.19.53.09 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Tue, 25 Feb 2014 19:53:10 -0800 (PST) Content-Type: multipart/alternative; boundary="Apple-Mail=_95094412-BF43-4F67-807D-5F2DC2CB942C" Mime-Version: 1.0 (Mac OS X Mail 6.6 \(1510\)) From: Stephane Brossier In-Reply-To: Date: Tue, 25 Feb 2014 19:53:08 -0800 Message-Id: References: <0CC0BE1D-1DAA-4994-B034-EB7712F845CF@kill-bill.org> <5F91BEBF-ECDD-4CBD-A85E-FD7E7DB3F01F@kill-bill.org> <81FBEA67-45A9-4531-BEA0-071CE9FAEF7E@kill-bill.org> To: Mike Hearn X-Mailer: Apple Mail (2.1510) X-Spam-Score: -0.5 (/) X-Spam-Report: Spam Filtering performed by mx.sourceforge.net. See http://spamassassin.org/tag/ for more details. -1.5 SPF_CHECK_PASS SPF reports sender host as permitted sender for sender-domain -0.0 SPF_PASS SPF: sender matches SPF record 1.0 HTML_MESSAGE BODY: HTML included in message X-Headers-End: 1WIVYb-0002KV-F9 Cc: Bitcoin Dev , Pierre-Alexandre Meyer Subject: Re: [Bitcoin-development] Extension for BIP-0070 to support recurring payments X-BeenThere: bitcoin-development@lists.sourceforge.net X-Mailman-Version: 2.1.9 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 26 Feb 2014 03:53:19 -0000 --Apple-Mail=_95094412-BF43-4F67-807D-5F2DC2CB942C Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=windows-1252 Hi Mike, Jeremy, Drak, Before going through your questions, I would like to bring some clarity = on a few key elements in that protocol. There are really two aspects to = it: The contract negotiation; when the user first subscribes, it is prompted = by a contract that will define the payment bounds associated with that = subscription.=20 Once accepted, the wallet is in charge and the user does not have to = interact anymore -- this is the point of the recurring payment protocol. = The wallet will poll the merchant and issue payments as they are = requested by the merchant as long as they stay within the bounds of what = was specified by the contract (and accepted by the customer). I think it would help to explain how we ended up with the type of = contract we introduced in that protocol. In an ideal world and in a NON = recurring scheme, the contract should simply be the exact amount to be = paid. In our case the exact amount may not be completely known in = advance -- for e.g taxes, shipping, pro-rations, =85 and so we decided = to introduce first a max amount per payment, and also a max amount per = period. It is up to the merchant to decide whether to specify none, any = or both bounds (max amount per payment and max amount per period). By = specifying both, the contract is tighter and the client would feel safer = to accept it. In the extreme case, by specifying none, the client would = be presented with a contract to pay whatever is requested -- probably = not a good option in the Bitcoin world unless there is a high sense of = trust with the merchant. =20 =46rom reading your comments, it appears we have not been clear on how = that frequency (PaymentFrequencyType) is being used. Its sole purpose is = to define the max amount per period in the contract. The frequency of = the payment is implicitly dictated by the merchant but not specified in = the protocol by design: the wallet has to poll with a fine granularity = (ideally each day when it is up) to understand if there is something = pending. In the same way, a specified amount was not enough in the = contract, we feel it would be restrictive to specify in advance when = payments are due. There are a lot of complex scenarios in the billing = space, and having the wallet poll the merchant to inquire for pending = payments is the most flexible option and the contract is there to ensure = the client will not be abused. To give a concrete example, imagine a = data plan where you pay a base recurring price of $70 per month, but you = are charged $10 per GB of data used beyond your included limit. If you = exceed your limit on the 15th and the 23rd of a given month, two extra = payment attempts will be requested by the merchant, that you couldn=92t = predict (this scenario is often referred to as usage billing with Prepay = Credits and Top-up, where the customer pays in advance for blocks of N = units, and once they are consumed another N are purchased). See answers in your questions inlined below: >=20 > I have the following comments: > There's no need to serialize RecurringPaymentDetails as bytes here. = It's done that way outside of PaymentDetails in order to support digital = signatures over protobufs that may have extensions the wallet app isn't = aware of, but it's a pain and inside PaymentDetails (and therefore for = most extensions) it shouldn't be necessary. So you can just use = "optional RecurringPamentDetails recurring_payments =3D 8;" >=20 OK, we'll fix it. > There's only 4 possibilities here for recurrences. That seems rather = restrictive. Is the cost of being more expressive really so high? Why = not allow more flexible specification of periods? > If there's no payment_frequency_type field then what happens? A quirk = of protobufs to be aware of is that making an enum field "required" can = hurt backwards compatibility. Because it will be expressed using a = languages underlying enum type, if there's a new enum member added later = old software that attempts to deserialize this will throw exceptions = because the new "unknown" member would be unrepresentable in the old = model. Making the field optional avoids this problem (it will be treated = as missing instead) but means software needs to be written to know what = to do when it can't read the enum value / sees enum values from the = future. >=20 I hope the explanation above answers the questions. > I assume the amounts are specified in terms of satoshi, and timestamps = are UNIX time, but better to make that explicit. >=20 Yes. > Seems there's an implicit value constraint that max_payment_amount <=3D = max_payment_per_period. What happens if that constraint is violated? = Best to document that. >=20 As explained above, contract would define none, 1 or both conditions. = First the merchant should not return such 'conditions' but if it does = the client should not accept the contract. If the client decides to = accept it anyway, then the wallet just verifies both conditions are met = separately regardless of whether there is such violation and if so, = makes the payment. > What's the "merchant ID" namespace thing about? What's it for? What = happens if I set my competitors merchant ID there? I agree, we can easily get rid of it. > What's the "subscription ID"? Is this stuff not duplicative/redundant = with the existing merchant_data field? In an ideal world the merchant should return unique subscriptionId (UUID = for instance). That subscriptionId is used in the code to identify the = contracts associated with the subscription. The merchant_data if i = understand correctly the payment protocol is opaque from the client = point of view, so it cannot be used by the client for that purpose.=20 > In what situations would you have >1 contract per payment request? I'm = not sure I understand why it's repeated. Presumably if there are zero = contracts included the data should be ignored, or an error thrown and = the entire payment request rejected? Which should it be? >=20 There are many example where that could happen; for instance if you = subscribe to a service, then later decide to downgrade to a lower = product. The merchant may decide to only let you downgrade at the end of = your paid period-- to avoid generating extra credit-- and in that = situation you end up with two contracts: One for the current product you = are in and one for the future product you will end up on when the = downgrade becomes effective. > It's unclear to me given such a contract when the payment should = actually occur. For instance if it's "monthly" then what day in the = month would the payment occur? >=20 As outlined above in the introduction, the protocol is designed in such = a way that the wallet does not have to know what is the exact date when = payment should occur, but instead polls the merchant for pending = payments. There are many situations when specifying an exact payment = date is not an option so that flexibility is essential. A simple example = would be for a customer who started subscribing on the 31th of a month. = Since there will be months with 28/29/30 days, the payment date would = change depending on the month. > You'll notice I moved the comments to be above the field definitions. = I know the current proto isn't done that way, but let's change it - long = comments are good and putting them above the field definitions = encourages people to write enough detail without being put off by line = length constraints >=20 Fine. > I think the next step would be to talk to BitPay/get Jeff+Stephen = involved because I know they have customers that really want recurring = payments, and those guys will have a clearer idea of customer = requirements than we do. I feel uncomfortable with designing or = reviewing in a vacuum without some actual people who would use it = chiming in, as I don't really know much about the underlying business = processes. We are totally open to receive feedbacks from them.. How do we bring = them in the discussion? >=20 > I have some other comments about the bitcoinj implementation = specifically - for instance, we don't have a "wallet directory" concept: = everything goes into the wallet file. So we'll need to think about how = to structure the code to allow that. Also, just using a background = polling thread is likely not flexible enough, as on some platforms you = can't stay running all the time (e.g. Android) without upsetting people, = but the underlying OS can wake you up at the right times, so wallet apps = should have an ability to control wakeup tasks. But we can discuss that = over on the bitcoinj list specifically. Let's keep this thread for the = general protocol design. Ok that makes sense. >=20 > BIP 70 is indeed implemented in Bitcoin Core on the C++ side, so that = isn't a concern. It could be done there too. >=20 Great to know. --Apple-Mail=_95094412-BF43-4F67-807D-5F2DC2CB942C Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=windows-1252
Hi Mike, Jeremy, = Drak,

Before going through your questions, I would like to bring = some clarity on a few key elements in that protocol. There are really = two aspects to it:
  1. The contract = negotiation; when the user first subscribes, it is prompted by a = contract that will define the payment bounds associated with that = subscription.
  2. Once accepted, the wallet is in charge and the = user does not have to interact anymore -- this is the point of the = recurring payment protocol. The wallet will poll the merchant and issue = payments as they are requested by the merchant as long as they stay = within the bounds of what was specified by the contract (and accepted by = the customer).

I think it would help to explain how we ended = up with the type of contract we introduced in that protocol. In an ideal = world and in a NON recurring scheme, the contract should simply be the = exact amount to be paid. In our case the exact amount may not be = completely known in advance -- for e.g taxes, shipping, pro-rations, =85 = and so we decided to introduce first a max amount per payment, and also = a max amount per period. It is up to the merchant to decide whether to = specify none, any or both bounds (max amount per payment and max amount = per period). By specifying both, the contract is tighter and the client = would feel safer to accept it. In the extreme case, by specifying none, = the client would be presented with a contract to pay whatever is = requested -- probably not a good option in the Bitcoin world unless = there is a high sense of trust with the merchant. =   

=46rom reading your comments, it appears we = have not been clear on how that frequency (PaymentFrequencyType) is = being used. Its sole purpose is to define the max amount per period in = the contract. The frequency of the payment is implicitly dictated by the = merchant but not specified in the protocol by design: the wallet has to = poll with a fine granularity (ideally each day when it is up) to = understand if there is something pending. In the same way, a specified = amount was not enough in the contract, we feel it would be restrictive = to specify in advance when payments are due. There are a lot of complex = scenarios in the billing space, and having the wallet poll the merchant = to inquire for pending payments is the most flexible option and the = contract is there to ensure the client will not be abused. To give a = concrete example, imagine a data plan where you pay a base recurring = price of $70 per month, but you are charged $10 per GB of data used = beyond your included limit. If you exceed your limit on the 15th and the = 23rd of a given month, two extra payment attempts will be requested by = the merchant, that you couldn=92t predict (this scenario is often = referred to as usage billing with Prepay Credits and Top-up, where the = customer pays in advance for blocks of N units, and once they are = consumed another N are purchased).

See answers in your = questions inlined below:


=
I have the following comments:
  1. There's no need to serialize RecurringPaymentDetails as = bytes here. It's done that way outside of PaymentDetails in order to = support digital signatures over protobufs that may have extensions the = wallet app isn't aware of, but it's a pain and inside PaymentDetails = (and therefore for most extensions) it shouldn't be necessary. So you = can just use "optional RecurringPamentDetails recurring_payments =3D = 8;"


OK, we'll fix = it.


  1. There's only 4 possibilities here = for recurrences. That seems rather restrictive. Is the cost of being = more expressive really so high? Why not allow more flexible = specification of periods?
  1. If there's no payment_frequency_type field then what happens? A quirk of = protobufs to be aware of is that making an enum field "required" can = hurt backwards compatibility. Because it will be expressed using a = languages underlying enum type, if there's a new enum member added later = old software that attempts to deserialize this will throw exceptions = because the new "unknown" member would be unrepresentable in the old = model. Making the field optional avoids this problem (it will be treated = as missing instead) but means software needs to be written to know what = to do when it can't read the enum value / sees enum values from the = future.


I hope the = explanation above answers the questions.

  1. I assume the = amounts are specified in terms of satoshi, and timestamps are UNIX time, = but better to make that = explicit.


Yes.

  1. Seems there's an implicit value constraint that = max_payment_amount <=3D max_payment_per_period. What happens if that = constraint is violated? Best to document that.


As explained = above, contract would define none, 1 or both conditions.  First the = merchant should not return such 'conditions' but if it does the client = should not accept the contract. If the client decides to accept it = anyway, then the wallet just verifies both conditions are met separately = regardless of whether there is such violation and if so, makes the = payment.

  1. What's the "merchant ID" namespace = thing about? What's it for? What happens if I set my competitors = merchant ID there?

I = agree, we can easily get rid of it.

  1. What's the = "subscription ID"? Is this stuff not duplicative/redundant with the = existing merchant_data = field?

In an = ideal world the merchant should return unique subscriptionId (UUID for = instance). That subscriptionId is used in the code to identify the = contracts associated with the subscription. The merchant_data if i = understand correctly the payment protocol is opaque from the client = point of view, so it cannot be used by the client for that = purpose. 
  1. In what situations would you have >1 contract per = payment request? I'm not sure I understand why it's repeated. Presumably = if there are zero contracts included the data should be ignored, or an = error thrown and the entire payment request rejected? Which should it = be?
    =


= There are many example where that could  happen; for instance if = you subscribe to a service,  then later decide to downgrade to a = lower product. The merchant may decide to only let you downgrade at the = end of your paid period-- to avoid generating extra credit-- and in that = situation you end up with two contracts: One for the current product you = are in and one for the future product you will end up on when the = downgrade becomes effective.


  1. It's unclear to = me given such a contract when the payment should actually occur. For = instance if it's "monthly" then what day in the month would the payment = occur?


As = outlined above in the introduction, the protocol is designed in such a = way that the wallet does not have to know what is the exact date when = payment should occur, but instead polls the merchant for pending = payments. There are many situations when specifying an exact payment = date is not an option so that flexibility is essential. A simple example = would be for a customer who started subscribing on the 31th of a month. = Since there will be months with 28/29/30 days, the payment date would = change depending on the = month.




  1. You'll notice I = moved the comments to be above the field definitions. I know the current = proto isn't done that way, but let's change it - long comments are good = and putting them above the field definitions encourages people to write = enough detail without being put off by line length constraints
  2. =


Fine.


I = think the next step would be to talk to BitPay/get Jeff+Stephen involved = because I know they have customers that really want recurring payments, = and those guys will have a clearer idea of customer requirements than we = do. I feel uncomfortable with designing or reviewing in a vacuum without = some actual people who would use it chiming in, as I don't really know = much about the underlying business = processes.


We = are totally open to receive feedbacks from them.. How do we bring them = in the discussion?


I have some other comments about the bitcoinj = implementation specifically - for instance, we don't have a "wallet = directory" concept: everything goes into the wallet file. So we'll need = to think about how to structure the code to allow that. Also, just using = a background polling thread is likely not flexible enough, as on some = platforms you can't stay running all the time (e.g. Android) without = upsetting people, but the underlying OS can wake you up at the right = times, so wallet apps should have an ability to control wakeup tasks. = But we can discuss that over on the bitcoinj list specifically. Let's = keep this thread for the general protocol = design.

Ok that makes = sense.


BIP 70 is indeed implemented = in Bitcoin Core on the C++ side, so that isn't a concern. It could be = done there too.


Great to = know.



= --Apple-Mail=_95094412-BF43-4F67-807D-5F2DC2CB942C--