<oembed><type>rich</type><version>1.0</version><author_name>npub1m230cem2yh3mtdzkg32qhj73uytgkyg5ylxsu083n3tpjnajxx4qqa2np2</author_name><author_url>https://nostr.ae/npub1m230cem2yh3mtdzkg32qhj73uytgkyg5ylxsu083n3tpjnajxx4qqa2np2</author_url><provider_name>njump</provider_name><provider_url>https://nostr.ae</provider_url><html>📅 Original date posted:2012-11-28&#xA;📝 Original message:On Wed, Nov 28, 2012 at 11:43:19AM +0100, Mike Hearn wrote:&#xA;&gt; Peter is correct that there are a few degrees of freedom in protobuf&#xA;&gt; serialization, though far fewer than with JSON.&#xA;&#xA;FWIW I re-read the specs again and turns out my memory was wrong. (I&#xA;last looked at this about four months ago) Duplicated fields are handled&#xA;in a defined manner, with the last field seen in the serialization being&#xA;the one whose value is used. Again, repeated fields are treated as&#xA;elements of a list, preserving order.&#xA;&#xA;It does raise the interesting question do the implementations that don&#39;t&#xA;preserve order of unknown fields, preserve the order of multiple unknown&#xA;fields, either repeated or not?&#xA;&#xA;&gt; I&#39;d like to think upstream would be open to resolving these&#xA;&gt; ambiguities.&#xA;&#xA;I gotta admit, I suspect they won&#39;t be that open. Protocol buffers was&#xA;designed because Google needed a fast serialization method suitable for&#xA;many different internal projects. Needing round-trip idempotence seems&#xA;like a rare requirement to me, especially for internal use.&#xA;&#xA;&gt; Re-serialization of an Invoice message in the Payment message is a&#xA;&gt; potential source of mistakes. There&#39;s no need to ever concatenate&#xA;&gt; these messages and alternative implementations that don&#39;t order&#xA;&gt; serialized fields by tag number are missing an important optimization,&#xA;&gt; so they could be fixed. The main issue is treatment of unknown fields.&#xA;&gt; If/when the Invoice message is extended with other fields that are&#xA;&gt; round-tripped through an old client, the data may get lost. JSON&#xA;&gt; doesn&#39;t help resolve that either, of course. There are a few&#xA;&gt; solutions:&#xA;&#xA;Well, actually you can take advantage of the message concatination&#xA;ability of protocol buffers to extend a message by simply appending the&#xA;new fields to the existing thus either defining new fields, or&#xA;overriding old values as required. If you want to de-duplicate though&#xA;you run into the problem all over again.&#xA;&#xA;On the other hand JSON handles this case fine too provided that your&#xA;JSON implementation supports dictionary objects with arbitrary fields.&#xA;Just use the object as is and the unknown fields will be re-serialized&#xA;properly at the other end. Some implementations will have to be careful&#xA;to handle collisions with existing keys in the namespace. (consider in&#xA;Python what would happen if you mapped your object to a class instance,&#xA;and the serialization included the key &#34;__init__&#34;)&#xA;&#xA;That said, JSON is quite problematic with numbers. For instance, you&#xA;have to be careful to keep integers represented as pure integers below&#xA;what Javascript can handle, the maximum integer exactly representable in&#xA;a double float, or the JSON won&#39;t be parsable in Javascript even if many&#xA;other languages handle it fine. Protocol buffers is at least pretty&#xA;explicit about what size integers are.&#xA;&#xA;&gt; 1) Change the type of the Invoice field in Payment to be &#34;bytes&#34; and&#xA;&gt; set it to be the hash of the originally received binary Invoice&#xA;&gt; message. Downside, requires merchants to track all outstanding&#xA;&gt; invoices.&#xA;&gt; 2) Ask protobufs upstream to modify the spec/implementations so&#xA;&gt; ordering of unknown fields is specified. The Python implementation&#xA;&gt; could be extended to support them so Python implementors don&#39;t end up&#xA;&gt; with accidental message downgrades.&#xA;&gt; 3) Language of the spec could be changed to explicitly state that the&#xA;&gt; received Invoice may not be binary-identical to the one that was sent,&#xA;&gt; in the case of a client that incorrectly downgrades the message. Thus&#xA;&gt; you&#39;d be expected to check what the Invoice was using merchant_data&#xA;&gt; which is opaque and could just be, eg, a database key on your own end.&#xA;&gt; 4) Instead of submitting the entire Invoice back to the merchant, just&#xA;&gt; the merchant_data could be in the Payment message.&#xA;&gt; &#xA;&gt; Of the four options I prefer the last. What is the use case for&#xA;&gt; resubmitting the entire invoice anyway? Even if protobufs are improved&#xA;&#xA;Note that I think the SignedInvoice message itself is broken, because&#xA;protobuf implementations have no reason to guarantee that they can give&#xA;you the serialized bytes of the Invoice sub-message. It&#39;s a quite&#xA;specific use-case that isn&#39;t needed for pretty much anything but crypto.&#xA;FWIW I took a quick look at the official API&#39;s, C++, Java and Python,&#xA;and as far as I can tell none of them support accessing the binary&#xA;serialization of a message field other than by re-serializing the&#xA;message.&#xA;&#xA;Really the invoice field should be declared as bytes serialized_invoice,&#xA;as inconvenient as that is to work with.&#xA;&#xA;&gt; so handling of round-tripping new messages through old [Python]&#xA;&gt; clients is more rigorous, some implementors will probably convert the&#xA;&gt; protobuf objects into some internal forms for whatever reason (or&#xA;&gt; serialize them to a database, etc) and they&#39;re very likely to mess up&#xA;&gt; the handling of unknown fields when they do it.&#xA;&#xA;Since the Payment message includes an *untrusted* Invoice that the&#xA;vendor needs to authenticate the whole invoice no matter what on Payment&#xA;reception. In many cases that implies they have to keep some sort of&#xA;database of &#34;quotes&#34; or similar anyway as the client can change anything&#xA;they want otherwise. Again that leads back to the argument of why not&#xA;just stick with the merchant_dat as you suggest, which will usually be&#xA;some short invoice number attached to a database? A vendor that wants to&#xA;operation a stateless invoicing system can just stuff a HMAC-protected&#xA;serialized invoice into the merchant_data&#xA;&#xA;I guess you could use a mutable invoice field as a way of achieving some&#xA;sort of negotiation protocol, but I think it&#39;s better to stick to the&#xA;original concept of just ensuring that the user is really paying the&#xA;right amount to the right address.&#xA;&#xA;-- &#xA;&#39;peter&#39;[:-1]@petertodd.org&#xA;-------------- next part --------------&#xA;A non-text attachment was scrubbed...&#xA;Name: signature.asc&#xA;Type: application/pgp-signature&#xA;Size: 490 bytes&#xA;Desc: Digital signature&#xA;URL: &lt;http://lists.linuxfoundation.org/pipermail/bitcoin-dev/attachments/20121128/46255e3d/attachment.sig&gt;</html></oembed>