- From: Ben Sharafian <sharafian@ripple.com>
- Date: Fri, 18 Aug 2017 23:39:10 +0200
- To: Adrian Hope-Bailie <adrian@hopebailie.com>
- Cc: Evan Schwartz <evan@ripple.com>, Interledger Community Group <public-interledger@w3.org>, Interledger Mailing List - IETF <ledger@ietf.org>
- Message-ID: <CAEcG=+3m+3siROp3LR08EmKZ=y6DpbSF=vhcHMJVt_biTP8BFg@mail.gmail.com>
> > My point is that it goes beyond that. ILP doesn't care if the layer below > even has a concept of HTLAs. I can do ILP over Bitcoin without the overlay > layer if I want to but I need to find a peer that is prepared to do that > with me. Because that's not how you build a protocol stack. A protocol stack is not > defined through interfaces. It's defined through layers of data where each > layer has a standard packet format with headers carrying data for that > layer and encapsulates the data of layer(s) above in the payload. I guess we're just using the term "doing ILP" differently. When I say it I'm referring to the flow with prepare/fulfill/reject on a sha256 condition. If I'm understanding you correctly, you mean it to refer to the data format; anything that gets the ILP packet to the destination via peering or ledger connections counts as ILP. On Fri, Aug 18, 2017 at 10:07 PM, Adrian Hope-Bailie <adrian@hopebailie.com> wrote: > > > On 18 August 2017 at 15:09, Ben Sharafian <sharafian@ripple.com> wrote: > >> What you're describing is an implementation of a local transfer service >>> that doesn't (or can't) take advantage of Interledger. In fact, this will >>> be the norm for most existing payment networks that we want to add to the >>> Interledger and this is where your work on payment channels and HTLAs comes >>> in to play. >> >> >> >>> >>> If you have a local transfer channel that doesn't support conditions >>> natively or supports them in a way that requires some adaption you can >>> create an overlay network that does what's needed. Example: Bitcoin is not >>> a suitable network to use for ILP so we use a payment channel between the >>> peers that is underwritten by Bitcoin. >> >> >> Exactly, when I say you need a to handle the condition and fulfillment >> via a clearing layer, this "overlay network" is what I'm referring to. The >> whole point of an HTLA is that from ILP's point of view it's just a >> lower-level protocol that can commit conditional transfers and fulfill >> them. ILP doesn't care how the ledger/HTLA works under the hood, whether >> it's a clearing/overlay layer or a "real" ledger. >> > > My point is that it goes beyond that. ILP doesn't care if the layer below > even has a concept of HTLAs. I can do ILP over Bitcoin without the overlay > layer if I want to but I need to find a peer that is prepared to do that > with me. > > In that case all I have to do is send them the ILP packet in a message > that says I owe them some Bitcoin. the "owe them some Bitcoin" isn't being > enforced anywhere using an HTLA. > >> >> >> You're equating this "overlay network," which is a type of ledger, with >> the ILP layer. >> > > Not at all. I agree with what you have below. It's a layer that exists > below ILP but above the actual ledger. But crucially it's not a requirement > for ILP to work so the protocol should depend on it existing. > > >> If there is an overlay network that handles the condition and >> fulfillment, that means you _are_ using a ledger, because the overlay >> network _is_ a ledger. The ILP layer is a layer above this. >> > > Agreed. > >> >> If we assume the ILP packet is well defined with all the ILP-required >>> data elements then when a lower layer wants to use that data it can but >>> should do it in a way that doesn't break the ILP layer for everyone else. >>> How that is implemented in practice will depend on the lower layer protocol. >> >> >> That's one way to see it, but what I'm wondering is why that's a better >> model than saying there's a clearly defined interface that the ledger-layer >> exposes, and then building the ILP layer on top of that. >> > > Because that's not how you build a protocol stack. A protocol stack is not > defined through interfaces. It's defined through layers of data where each > layer has a standard packet format with headers carrying data for that > layer and encapsulates the data of layer(s) above in the payload. > > The condition, fulfillment and expiry are part of ILP so they belong in > the ILP packet. If there are lower layers that want to use those things > then they can but ILP shouldn't depend on that. > > >> >> Unless the next hop is backwards >> >> >> There's no reason to send a backwards hop. If you don't want to forward a >> payment you reject it. >> > > That's what I mean by a backwards hop. I was illustrating my point that > validating a packet is part of the routing decision. > > >> >> Not at all. You're assuming that there is no expiry on the local >>> transfer. As a receiving node I have an incoming transfer with an expiry >>> and it carries an ILP packet that also has an expiry. >> >> >> If that's what you're talking about, the ILP packet already has an >> expiry. It's implemented in the PSK details so the receiver knows whether >> the packet it issued is still valid. But that's an application layer >> concern, because it's only the receiver who looks at the ILP packet's >> expiry. The connectors only need to know the expiries of the local >> transfers. >> > > There is a big misconception in your statement. The expiry is an > end-to-end concern, or as you put it the sender sets and "the receiver > looks at the ILP packet's expiry". That's why it's in the ILP packet. > > The idea that anything to be exchanged end-to-end must be in higher layers > is completely wrong. The reason you'd put something in a higher layer > payload is because the endpoints have agreed to use a higher layer protocol > that requires it to be there. > > >> On Fri, Aug 18, 2017 at 3:21 PM, Adrian Hope-Bailie < >> adrian@hopebailie.com> wrote: >> >>> >>> >>> On 18 August 2017 at 10:38, Ben Sharafian <sharafian@ripple.com> wrote: >>> >>>> Two connectors exchanging a transfer only care about the data that is >>>>> relevant to them for that transfer. It's quite possible for two connectors >>>>> to perform a transfer that has no conditions or fulfillments or a transfer >>>>> that has a different condition and fulfillment (such as an atomic mode >>>>> transfer where the condition is a compound one that has multiple >>>>> sub-conditions). >>>> >>>> >>>> Yes, two connectors could absolutely send an unconditional transfer on >>>> an underlying ledger in order to settle an Interledger payment. But in >>>> order to benefit from any of Interledger's guarantees (trustless >>>> connectors, retry-ability, etc.), they MUST keep a conditional local >>>> transfer, at least for clearing. If the local transfer cannot time out, it >>>> cannot be safely retried. If the local transfer clears without a >>>> fulfillment, it loses the "receipt or your money back" property. Yes, two >>>> parties in the chain could eschew these benefits but that is no longer a >>>> correct implementation of Interledger. >>>> >>> >>> Aha! That is where I disagree! Interledger is not implemented at the >>> local transfer layer, it is implemented at the Interledger layer. The whole >>> point is that it an Interledger payment can travel over payment networks >>> that know nothing about ILP but the greatest value comes from using ones >>> that do. >>> >>> What you're describing is an implementation of a local transfer service >>> that doesn't (or can't) take advantage of Interledger. In fact, this will >>> be the norm for most existing payment networks that we want to add to the >>> Interledger and this is where your work on payment channels and HTLAs comes >>> in to play. >>> >>> If you have a local transfer channel that doesn't support conditions >>> natively or supports them in a way that requires some adaption you can >>> create an overlay network that does what's needed. Example: Bitcoin is not >>> a suitable network to use for ILP so we use a payment channel between the >>> peers that is underwritten by Bitcoin. >>> >>> >>>> >>>> If a protocol at a lower layer wants to use that data then it must >>>>> replicate it. That seems inefficient but it's the correct way to do it. >>>> >>>> >>>> What's the actual reasoning behind this, and why is it considered the >>>> correct approach? If there's some IETF document that says this I'd like to >>>> see it, because it intuitively feels wrong to have lower level abstractions >>>> looking into higher levels. >>>> >>> >>> The data in the ILP layer is there for a specific reason. It's part of >>> an end-to-end exchange between the sender and receiver. >>> >>> >>> *Side note: It's unusual to be designing the whole stack at once so we >>> keep being tempted to move things around but in reality we should look at >>> the ILP layer in isolation and make sure it is complete. Alternatively we >>> should try to test our design against a number of lower and upper layer >>> protocols to make sure our thinking is sound.* >>> If we assume the ILP packet is well defined with all the ILP-required >>> data elements then when a lower layer wants to use that data it can but >>> should do it in a way that doesn't break the ILP layer for everyone else. >>> How that is implemented in practice will depend on the lower layer >>> protocol. >>> >>> >>>> >>>> Routing requires looking at the condition, expiry and amount. A >>>>> connector's routing logic shouldn't forward a packet if the expiry is too >>>>> low or if the condition is obviously corrupted. >>>> >>>> >>>> Those are validity checks and you're right that they are performed in >>>> the connector, but the destination account, destination amount, and data >>>> are enough to figure out what the best next hop is. >>>> >>> >>> Unless the next hop is backwards >>> >>> >>>> >>>> The ILP Packet's purpose is to describe where a payment is going. >>>> >>> >>> Not only that. For comparison, an IP packet does a lot more than just >>> describe where a packet is going. All end-to-end concerns need to be in >>> there too. >>> >>> >>>> The data it carries is only for the purpose of making sure the receiver >>>> can identify that payment. >>>> >>> >>> No, the condition is there so the receiver can ensure it is sending back >>> the correct fulfillment and the expiry to give the receiver some assurance >>> that the packet is still worth processing. >>> >>> >>>> In that context, the expiry has no bearing on where it will be routed >>>> nor on how much to route, only on whether or not an individual connector >>>> will take the risk of forwarding it. >>>> >>>> The ILP packet just contains the end-to-end condition (always a SHA-256 >>>>> hash) and then the local transfer can have a different condition that is >>>>> derived from the condition in the ILP packet. >>>> >>>> >>>> Fair enough; in your case you can transmit the condition twice and >>>> verify the structure of the complex local condition, and in the >>>> no-condition-in-ILP version you can verify the structure of the local >>>> condition and extract the SHA256 condition to pass on. >>>> >>>> I think the expiry should always be the expiry set by the sender. It >>>>> won't be changed. >>>> >>>> >>>> That increases connector risk enormously, allowing anybody to cause a >>>> connector to lose money by submitting a fulfillment at the last moment. >>>> >>> >>> Not at all. You're assuming that there is no expiry on the local >>> transfer. As a receiving node I have an incoming transfer with an expiry >>> and it carries an ILP packet that also has an expiry. >>> >>> My routing logic should look at both and decide a) if this is safe to >>> route on (i.e. put some of my own capital at risk) and b) what expiry to >>> set on the next hop. >>> >>> There is no incentive to change the expiry in the packet as this can >>> only be targeted at upstream connectors and the result will simply be that >>> the payment is declined and the upstream local transfer rolls back. >>> >>> >>>> If an attacker knows enough about latency in the chain, they could even >>>> target this attack at somebody many hops away. Staggering expiries (giving >>>> you a minimum amount of time to fulfill a source transfer) is an easy >>>> mitigation against this attack; we shouldn't take it out. >>>> >>> >>> I agree. We would still have the local expiry. >>> >>> >>>> >>>> Comparing the condition in the local transfer and the one in the ILP >>>>> packet should be part of the routing logic. >>>> >>>> >>>> Sure, it can be done as an extra validity check, but it's just more >>>> code and more attack surface. I still don't see any tangible benefit >>>> from doing the layering in this way, aside from your assertion that it's >>>> the correct way to do it. If you've read any documents that explain why >>>> this is the correct way to do layering, I think I'd understand you better. >>>> >>>> >>>> On Thu, Aug 17, 2017 at 7:32 PM, Adrian Hope-Bailie < >>>> adrian@hopebailie.com> wrote: >>>> >>>>> >>>>> >>>>> On 16 August 2017 at 10:22, Ben Sharafian <sharafian@ripple.com> >>>>> wrote: >>>>> >>>>>> OK, I think in that case we're mostly disagreeing over where the >>>>>> condition/fulfillment/expiry actually go in the data. >>>>>> >>>>> >>>>> That's one way to look at it but that's ultimately what the >>>>> architecting the layering is. Deciding at which layer (and therefor >>>>> encapsulated in what packet) certain data should be. >>>>> >>>>> >>>>>> The reason I don't agree with your position is based on which parties >>>>>> I think should be aware of ILP. >>>>>> >>>>> >>>>> I don't think that's the right way to look at it. The connector needs >>>>> to be able to understand at least the ILP layer data AND the lower layer >>>>> data. Normally the way the processing stack is implemented is that there is >>>>> a module for each layer that processes the data from that layer and then >>>>> passes the payload and any other important information up to the next layer. >>>>> >>>>> >>>>>> In order to track the balance between each other accurately, the two >>>>>> connectors have to keep track of conditions, fulfillments, and expiries on >>>>>> each of the transfers. >>>>>> >>>>> >>>>> This is where I disagree with you. Two connectors exchanging a >>>>> transfer only care about the data that is relevant to them for that >>>>> transfer. It's quite possible for two connectors to perform a transfer that >>>>> has no conditions or fulfillments or a transfer that has a different >>>>> condition and fulfillment (such as an atomic mode transfer where the >>>>> condition is a compound one that has multiple sub-conditions). >>>>> >>>>> >>>>>> That means the connectors' accounting logic that handles the >>>>>> conditions, fulfillments, and expiries is going to be using some >>>>>> information inside the ILP packet and some information outside of it in >>>>>> order to perform these transfers. >>>>>> >>>>> >>>>> It will only use info inside the packet if it uses conditional >>>>> transfers that use that same condition. This is the most likely scenario >>>>> but that is not a protocol requirement. >>>>> >>>>> >>>>>> >>>>>> I think it's cleaner to say everything required to make these local >>>>>> transfers should go in one protocol, so the accounting logic of these >>>>>> connectors doesn't have to deal with ILP directly. >>>>>> >>>>> >>>>> I strongly disagree with that. That's entirely the wrong reason to put >>>>> data into a specific layer. The data in the ILP layer is there because it's >>>>> "end-to-end" data. >>>>> >>>>> If a protocol at a lower layer wants to use that data then it must >>>>> replicate it. That seems inefficient but it's the correct way to do it. >>>>> >>>>> One could define a lower layer protocol that doesn't replicate the >>>>> data but the rules of the protocol are "Get the condition from the ILP >>>>> packet". In that case, that specific lower level protocol is forcing >>>>> implementations to understand the ILP packet format, that's an >>>>> implementation detail. >>>>> >>>>> Another lower layer protocol might take the condition from the ILP >>>>> packet and re-encode it in a different form (like a base64ulr string or NI: >>>>> uri) >>>>> >>>>> >>>>>> Then the connectors' ILP-packet-related behavior can all be routing >>>>>> related. >>>>>> >>>>> >>>>> Routing requires looking at the condition, expiry and amount. A >>>>> connector's routing logic shouldn't forward a packet if the expiry is too >>>>> low or if the condition is obviously corrupted. >>>>> >>>>> If the protocols were designed correctly as I am proposing then >>>>> another routing decision would be, is the condition that was used in the >>>>> incoming transfer the same as the one used in the ILP packet? >>>>> >>>>> >>>>> >>>>>> This would add a few benefits; two connectors could perform non-ILP >>>>>> conditional transfers between one another (which would be useful for >>>>>> reconciliation and settlement), and could also allow two connectors to use >>>>>> more complex condition types (i.e. signatures for atomic mode) without >>>>>> forcing us to support that in the ILP packet. >>>>>> >>>>> >>>>> You seem to have this backwards. Both of these things are supported if >>>>> the condition and expiry ARE in the ILP packet. Atomic mode is not >>>>> supported in the ILP protocol it is supported in the lower layer transfer >>>>> protocol. The ILP packet just contains the end-to-end condition (always a >>>>> SHA-256 hash) and then the local transfer can have a different condition >>>>> that is derived from the condition in the ILP packet. >>>>> >>>>> >>>>>> It also keeps the integrity of the ILP packet as something lower >>>>>> levels don't modify; the connector has to modify the expiry in order to >>>>>> pass along an ILP payment (they may not modify the expiry if they're using >>>>>> something like atomic mode, but then we have the issue with advanced >>>>>> condition types not being supported in the ILP packet). >>>>>> >>>>> >>>>> I think the expiry should always be the expiry set by the sender. It >>>>> won't be changed. >>>>> >>>>>> >>>>>> In the case where the ledger _does_ care about the condition and >>>>>> fulfillment, the argument in favor of separating >>>>>> condition/fulfillment/expiry from the rest of the packet is similar. >>>>>> Because we don't control the features of all ledgers, we'll need our >>>>>> plugins or ledger adapters to be aware of ILP. This makes it hard to >>>>>> interact with any events that don't involve ILP packets, and impossible to >>>>>> handle features that extend beyond what we support in the ILP packet. We >>>>>> could pass details about non-ILP ledger features (like a crypto condition) >>>>>> in the side data, but in the event of any redundancy we have to check the >>>>>> ledger-supplied info, not the info in the ILP packet. >>>>>> >>>>> >>>>> Comparing the condition in the local transfer and the one in the ILP >>>>> packet should be part of the routing logic. >>>>> >>>>> >>>>>> >>>>>> Basically, condition/fulfillment/expiry are used for accounting local >>>>>> transfers (even if they aren't being "ledger" enforced) in addition to >>>>>> their role as every-hop information. By putting them in the ILP packet, we >>>>>> limit the special features that ledgers can support and make our software >>>>>> abstractions harder to separate cleanly. By putting them in the local >>>>>> transfer alongside the ILP packet but not inside it, we do separate the >>>>>> data a little more, but we have more freedom in what the underlying >>>>>> accounting and ledger logic can do, and our software modules will have more >>>>>> clearly separated domains. >>>>>> >>>>> >>>>> They should be in both the local transfer AND the ILP packet if they >>>>> are needed by the local transfer protocol. This allows the flexibility you >>>>> desire because the local transfer protocol can do ANYTHING including using >>>>> the condition from the ILP packet as-is, not at all or enhanced for >>>>> something like atomic mode. >>>>> >>>>> >>>>> >>>>>> >>>>>> On Tue, Aug 15, 2017 at 10:24 AM, Adrian Hope-Bailie < >>>>>> adrian@hopebailie.com> wrote: >>>>>> >>>>>>> Exactly 👍 >>>>>>> >>>>>>> On Tue, Aug 15, 2017 at 6:52 PM Ben Sharafian <sharafian@ripple.com> >>>>>>> wrote: >>>>>>> >>>>>>>> Ok, I think I have a better idea of what you're saying. >>>>>>>> >>>>>>>> It sounds like you're saying the ILP layer contains all information >>>>>>>> that is common between every hop (destination, destination amount, opaque >>>>>>>> data, condition, fulfillment, expiry). The lower level would then be used >>>>>>>> for all the transfer-local details (source amount, next connector account, >>>>>>>> custom/local data). >>>>>>>> >>>>>>>> If the lower level wanted to do anything related to the every-hop >>>>>>>> payment, i.e. escrow funds until the receipt has been produced, it would >>>>>>>> look into the ILP layer for that information. If the lower level didn't do >>>>>>>> any escrow or expiries that require every-hop details, it would simply >>>>>>>> function as a communication method. >>>>>>>> >>>>>>>> Is that right? >>>>>>>> >>>>>>>> On Tue, Aug 15, 2017 at 6:35 PM, Adrian Hope-Bailie < >>>>>>>> adrian@hopebailie.com> wrote: >>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>> On 15 August 2017 at 16:00, Ben Sharafian <sharafian@ripple.com> >>>>>>>>> wrote: >>>>>>>>> >>>>>>>>>> In that case, the plugin or whatever is doing the accounting is >>>>>>>>>>>>> the ledger. Digital value is always tracked in ledgers, so I think it does >>>>>>>>>>>>> make sense to think of this as the base layer. The reason to abstract the >>>>>>>>>>>>> functionality you expect from the ledger layer is precisely so you can >>>>>>>>>>>>> handle it in different ways, depending on what the underlying systems >>>>>>>>>>>>> provide. >>>>>>>>>>>> >>>>>>>>>>>> I see 3 ways to think of the layer(s) underpinning ILP: >>>>>>>>>>>> >>>>>>>>>>>> 1. The "Ledger Layer" provides both messaging capabilities >>>>>>>>>>>> and some type of HTLA >>>>>>>>>>>> <https://github.com/interledger/rfcs/blob/master/0022-hashed-timelock-agreements/0022-hashed-timelock-agreements.md> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> 1. There are separate plugins for messaging and for >>>>>>>>>>>> transfers and when you peer with someone you have to agree on a plugin for >>>>>>>>>>>> each >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> 1. We standardize the messaging part and say that all goes >>>>>>>>>>>> over IP and then just have more minimal plugins for the on-ledger >>>>>>>>>>>> settlements >>>>>>>>>>>> >>>>>>>>>>>> Number 1 is what we have and I think that still makes the most >>>>>>>>>>>> sense. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> I think you're confusing implementation details and defining of >>>>>>>>>>> interfaces with definition of a protocol stack. The only differences >>>>>>>>>>> between the tree examples you have above is in implementation. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> I had to scroll up after reading this to make sure it was @adrian >>>>>>>>>> talking, because that seems like the opposite of what you were arguing for. >>>>>>>>>> >>>>>>>>> >>>>>>>>> I don't think so. But I think that is part of the problem. We are >>>>>>>>> not all focused on the same thing. I am actually not very interested in CLP >>>>>>>>> at all. It is one of potentially many protocols that may exist below the >>>>>>>>> ILP layer. All we're doing by defining CLP is bootstrapping the network by >>>>>>>>> defining a protocol for everyone to use to get started. >>>>>>>>> >>>>>>>>> In designing the ILP layer properly we should try and forget >>>>>>>>> everything we know about the lower layers other than what features we >>>>>>>>> require of them. >>>>>>>>> >>>>>>>>> There is a misconception that ILP requires the lower layers to >>>>>>>>> support conditional transfers, that is not true. >>>>>>>>> >>>>>>>>> All we actually need from a lower layer protocol is to transfer >>>>>>>>> data back and forth and provide a way to reliably map requests to responses. >>>>>>>>> >>>>>>>>> What ILP provides lower layers is a way to reward your peer for >>>>>>>>> passing on the packet. The Internetworking layer defines a condition, a >>>>>>>>> reward that must be paid to the receiver for the fulfillment and the time >>>>>>>>> allowed to claim this reward. >>>>>>>>> >>>>>>>>> Because of this, within lower-layer protocols that offer the basic >>>>>>>>> request/response features we need, we could add conditional payment >>>>>>>>> semantics that use the condition, expiry and fulfillment provided by ILP. >>>>>>>>> This would allow a node to offer a reward to their next peer to for >>>>>>>>> delivering the packet they send them and to make the local financial >>>>>>>>> transaction contingent on the end-to-end transaction. >>>>>>>>> >>>>>>>>> But crucially, adding that semantic to the lower layer protocol >>>>>>>>> provides nothing extra to the ILP layer. The value is purely derived from >>>>>>>>> the two peers who use that protocol and can now use conditional payments to >>>>>>>>> protect themselves from their peers. >>>>>>>>> >>>>>>>>> >>>>>>>>>> The proposal that you're arguing for is basically asserting that >>>>>>>>>> we're going to be using CLP, because it makes the assumption that the >>>>>>>>>> connectors (who understand ILP) are managing the HTLA logic. >>>>>>>>>> >>>>>>>>> >>>>>>>>> Not at all. I am asserting that it doesn't matter what protocol >>>>>>>>> you use below the ILP layer because it shouldn't matter. All of this talk >>>>>>>>> about ILP being different because money is more important than data is >>>>>>>>> nonsense. >>>>>>>>> >>>>>>>>> The difference between ILP and IP that makes ILP suitable for >>>>>>>>> value transfer and IP not is at the internetworking layer. ILP requires >>>>>>>>> that all packets are either a request or response and that the responses >>>>>>>>> follow the same path as the requests. Further ILP defines a signature >>>>>>>>> scheme that gives the sender a way to be certain the request was received >>>>>>>>> by the receiver. >>>>>>>>> >>>>>>>>> *This could be done entirely without money* but then there would >>>>>>>>> be little incentive to sign the receipt or deliver the signature back to >>>>>>>>> the original sender. >>>>>>>>> >>>>>>>>> So, if you add money then you add economic incentives to the mix. >>>>>>>>> At each hop the sender promises the next upstream peer a payment if they >>>>>>>>> can return the receipt. The net effect is that this can be used to transfer >>>>>>>>> money from the sender to the receiver by simply defining up front the >>>>>>>>> amount that the receiver must get to produce the signature. >>>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>> In the current model, the CLP/trustline model and the direct >>>>>>>>>> ledger model both work without having to treat anything on the ILP layer >>>>>>>>>> differently. We're favoring on-ledger messaging because of our >>>>>>>>>> implementation, yes, but we've been able to switch most all of our plugins >>>>>>>>>> from on-ledger messaging to RPC-based messaging without changing the ILP >>>>>>>>>> layer at all. >>>>>>>>>> >>>>>>>>>> With the ledger-level abstraction, we were able to switch from >>>>>>>>>> our ledger-based mode of thinking to the CLP/trustline based way without >>>>>>>>>> changing anything other than the plugin. Your argument comes from an >>>>>>>>>> assumption of a CLP-style ledger protocol with some underlying ledger, >>>>>>>>>> which we can't assume is always the case. >>>>>>>>>> >>>>>>>>> >>>>>>>>> I'm not sure what any of that proves tbh. These are all >>>>>>>>> implementation concerns. They don't change the fact that the condition, >>>>>>>>> expiry and fulfillment are part of ILP not the lower layer protocols. >>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> From the perspective of the Interledger Protocol the >>>>>>>>>>> implementation of the lower layers is not important, that's the whole point >>>>>>>>>>> of layering. By forcing important aspects of ILP like the condition, >>>>>>>>>>> fulfillment and expiry down into those layers you muddy the waters and we >>>>>>>>>>> now have to standardize those protocols too. Instead we should just be >>>>>>>>>>> defining the functions they must provide and then leave it up to >>>>>>>>>>> implementations to provide those functions. >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> I don't agree with this point; the condition and fulfillment have >>>>>>>>>> actual meaning to the ledger layer. >>>>>>>>>> >>>>>>>>> >>>>>>>>> NO THEY DON'T! They have meaning to SOME ledgers that implement >>>>>>>>> SOME lower layer protocols, IF they choose to use them. >>>>>>>>> >>>>>>>>> Excuse the shouting but this is the crux of the issue. We need to >>>>>>>>> all agree that it is entirely possible for a transfer to be done that >>>>>>>>> doesn't use the condition and fulfillment and that if this was in the >>>>>>>>> middle of a 10-hop ILP payment it would have no effect on the sender and >>>>>>>>> receiver. >>>>>>>>> >>>>>>>>>> >>>>>>>>>> You've said that the ledger often doesn't care about fulfillment >>>>>>>>>> and condition, but the ledger _layer_'s (where transfers are done) role is >>>>>>>>>> to take in condition and fulfillment and make a transfer which satisfies >>>>>>>>>> its HTLA. >>>>>>>>>> >>>>>>>>> >>>>>>>>> No, the ledger's role is to keep a tab of net financial positions >>>>>>>>> between two peers. It MAY use conditions and fulfillments that it pulls >>>>>>>>> from the ILP layer to help it do that in a way both peers agree on. >>>>>>>>> >>>>>>>>> Note that a "layer" doesn't have a role. I think there is some >>>>>>>>> confusion about the difference between layering the protocol and >>>>>>>>> abstracting functionality into different components. >>>>>>>>> >>>>>>>>> >>>>>>>>>> If the ledger layer has to look into the ILP packet to do so, >>>>>>>>>> that is a blatant breaking of layering. >>>>>>>>>> >>>>>>>>> >>>>>>>>> Not at all! The module acting at the layers *below* the >>>>>>>>> internetworking layer shouldn't modify anything inside the packets of the >>>>>>>>> higher layers but they can definitely inspect them and adjust their >>>>>>>>> behavior based on what they to find. >>>>>>>>> >>>>>>>>> In fact the prevalence of this is the subject of a lot of debate >>>>>>>>> at the IETF currently because endpoints are often encrypting their payloads >>>>>>>>> and in some cases this makes it difficult for middle-boxes to be effective >>>>>>>>> at their jobs. >>>>>>>>> >>>>>>>>> By putting the condition, fulfillment, and expiry on the ledger >>>>>>>>>> layer, we leave it open for any ledger type to work, rather than forcing >>>>>>>>>> all ledger-layer software to understand ILP. >>>>>>>>>> >>>>>>>>> >>>>>>>>> Actually you do the opposite. You make it a requirement of every >>>>>>>>> protocol below the ILP layer to define a way to carry these data elements >>>>>>>>> and encode and decode them, even if they don't use them >>>>>>>>> >>>>>>>>> Ledger layer components don't have to understand ILP unless they >>>>>>>>> choose to re-use the condition for their own local transfer. Ledgers >>>>>>>>> themselves *never* have to understand ILP. >>>>>>>>> >>>>>>>>> Remember a ledger layer protocol could use a completely different >>>>>>>>> conditional payments scheme, like atomic mode ILP, where it takes the >>>>>>>>> end-to-end condition and creates a new compound condition that depends on >>>>>>>>> the fulfillment and some notary signature. >>>>>>>>> >>>>>>>>> There will be a component in a connector's stack that must pass >>>>>>>>> the ILP packet to the next peer. If it does this using a transfer protocol >>>>>>>>> that uses conditional transfers and wants to use the same condition as the >>>>>>>>> ILP packet then it must decode the packet. >>>>>>>>> >>>>>>>>> But, it will likely do something with that condition before >>>>>>>>> sending the transfer to the ledger like encoding it differently or >>>>>>>>> rehashing it (lightning?) so that it's in the form expected by the ledger. >>>>>>>>> >>>>>>>>> That's an implementation decision of the lower layer protocol used >>>>>>>>> between those two peers. >>>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>> I agree that Interledger defines how conditions, fulfillments, >>>>>>>>>> and expiries should be chained together, but it makes no assertions about >>>>>>>>>> their data format. >>>>>>>>>> >>>>>>>>> >>>>>>>>> ILP doesn't define how anything is chained together. From the >>>>>>>>> perspective of ILP the condition and fulfillment are end-to-end data. They >>>>>>>>> are agreed by the two endpoints who don't care how they get from Alice to >>>>>>>>> Bob and back. >>>>>>>>> >>>>>>>>> The design of ILP is such that it facilitates the design of lower >>>>>>>>> level protocols that can be used to carry the ILP packets across multiple >>>>>>>>> hops (networks) using economic incentives such that the sender pays enough >>>>>>>>> for the first hop to ensure that all nodes in between can extract the fee >>>>>>>>> they want and the receiver will still get the amount they expected.. >>>>>>>>> >>>>>>>>> >>>>>>>>> >>>>>>>>>> ILP says you should send your outgoing transfer with the same >>>>>>>>>> condition as the incoming one, and a lower expiry. >>>>>>>>>> >>>>>>>>> >>>>>>>>> No it doesn't. An internetworking protocol can't prescribe that >>>>>>>>> kind of thing to lower level protocols. An incoming and outgoing transfer >>>>>>>>> could be sent using completely different protocols and the financial >>>>>>>>> agreement with the peers on those two routes could be vastly different too. >>>>>>>>> >>>>>>>>> The only service ILP requires of lower level protocols is that >>>>>>>>> they can map a response to an original request. This requirement is okay >>>>>>>>> because it is isolated to a single route/link at a time not a requirement >>>>>>>>> that crosses the inter-network boundary that ILP crosses. >>>>>>>>> >>>>>>>>> >>>>>>>>>> But because ILP allows for many different types of ledgers, it >>>>>>>>>> doesn't make sense to assert how these are encoded. >>>>>>>>>> >>>>>>>>> >>>>>>>>> By putting them in the ILP packet you do the opposite. You make no >>>>>>>>> assertions about how they are encoded if they are used at lower layers, or >>>>>>>>> how they may be combined with other conditions or even used to derive new >>>>>>>>> conditions. >>>>>>>>> >>>>>>>>>> >>>>>>>>>> IP doesn't tell you how to encode an ethernet packet. It doesn't >>>>>>>>>> even know whether it's going over a computer or a hand-written letter >>>>>>>>>> carried by a pigeon. IP takes for granted that you can send data over one >>>>>>>>>> connection by putting it in a lower level. >>>>>>>>>> >>>>>>>>> >>>>>>>>> Correct, but if a link layer protocol wanted to look into the IP >>>>>>>>> packet headers of a packet it wants to transfer and use some data from >>>>>>>>> there in its internal logic (or even reuse data in it's own frame) that >>>>>>>>> would be totally fine. >>>>>>>>> >>>>>>>>> >>>>>>>>>> Even though IP tells you how to chain these connections together, >>>>>>>>>> it doesn't have to put the things it's chaining on the internetworking >>>>>>>>>> level. >>>>>>>>>> >>>>>>>>> >>>>>>>>> IP doesn't tell you how to chain things together. IP simply >>>>>>>>> defines the end-to end data envelope and address space. Because of this >>>>>>>>> nodes that implement the multiple lower layer protocols are able to push IP >>>>>>>>> packets down a link and expect the node on the other side to understand the >>>>>>>>> headers and route it onward on another link. >>>>>>>>> >>>>>>>>> Everything needed by the IP module to decide what to do with the >>>>>>>>> packet is in the IP packet headers. i.e. Has it exceeded a TTL? Is there a >>>>>>>>> route for this destination? Is it corrupted (checksum fails)? But also, >>>>>>>>> everything that is needed by the endpoint (like the source address) is also >>>>>>>>> in there. >>>>>>>>> >>>>>>>>> There is no dependency on nodes to be good citizens and always >>>>>>>>> pass certain other data from the lower layers into the next link. That >>>>>>>>> would be breaking the layering. >>>>>>>>> >>>>>>>>> >>>>>>>>>> IP also assumes that if you get some incoming data on a >>>>>>>>>> connection you can copy it and send it out on the next connection. Because >>>>>>>>>> you can already send data over a connection, all IP adds is the missing >>>>>>>>>> piece: a packet that tells you where to go. >>>>>>>>>> >>>>>>>>>> With ILP, we assume that there is a way to prepare a conditional >>>>>>>>>> transfer, expire a conditional transfer, and fulfill a conditional >>>>>>>>>> transfer. >>>>>>>>>> >>>>>>>>> >>>>>>>>> No we don't! We assume that if we deliver the packet as intended >>>>>>>>> we'll get back a response packet with a signature that matches the >>>>>>>>> condition in the packet. So, if we have an agreement with someone that they >>>>>>>>> will pay us when we present that signature then we are prepared to enter a >>>>>>>>> similar agreement with the next peer because we expect that signature to >>>>>>>>> come all the way back along the interledger layer route.. >>>>>>>>> >>>>>>>>> >>>>>>>>>> We also assume that if you get an incoming transfer you can >>>>>>>>>> create an outgoing transfer with the same condition. The abstraction we >>>>>>>>>> made means that conditions and fulfillments are already carried in the >>>>>>>>>> lower levels. >>>>>>>>>> >>>>>>>>> >>>>>>>>> That is a bad assumption that comes from the broken layering. What >>>>>>>>> if my outgoing link doesn't support conditional transfers? So now where do >>>>>>>>> I put the condition? >>>>>>>>> >>>>>>>>>> >>>>>>>>>> >>>>>>>>>> We could have assumed that no ledgers ever support conditional >>>>>>>>>> transfers, and said the only thing ILP gets from lower levels is the >>>>>>>>>> ability to send a transfer. But if we want to support the case where any of >>>>>>>>>> them do, we have to keep the conditions and fulfillments in the layer where >>>>>>>>>> they're actually used. >>>>>>>>>> >>>>>>>>> >>>>>>>>> I don't follow that logic at all. If we want to support the case >>>>>>>>> where any of them do then we must ensure the condition and expiry are >>>>>>>>> always carried in a consistent place at the internetworking layer so that >>>>>>>>> if they do want to use them they know where to find them. >>>>>>>>> >>>>>>>>> >>>>>>>>>> >>>>>>>>>> On Tue, Aug 15, 2017 at 12:04 PM, Adrian Hope-Bailie < >>>>>>>>>> adrian@hopebailie.com> wrote: >>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> On 14 August 2017 at 22:03, Evan Schwartz <evan@ripple.com> >>>>>>>>>>> wrote: >>>>>>>>>>> >>>>>>>>>>>> I think this thread is going to get extremely unwieldy but here >>>>>>>>>>>> goes: >>>>>>>>>>>> >>>>>>>>>>>> > - All interledger layer messages should be ILP packets >>>>>>>>>>>> (including fulfillments) and be capable of carrying higher layer protocol >>>>>>>>>>>> payloads. >>>>>>>>>>>> >>>>>>>>>>>> Interledger has higher requirements than ILP for the lowest >>>>>>>>>>>> layer, specifically because we are carrying money and not just data. One of >>>>>>>>>>>> the requirements is being able to transmit a 32-byte fulfillment back along >>>>>>>>>>>> the same path that carried the payment originally. If we expect this of the >>>>>>>>>>>> lower layer, I don't see a point in putting the fulfillment into an ILP >>>>>>>>>>>> packet and transmitting it as Interledger data along the same path. All >>>>>>>>>>>> ledger-layer protocols will need to interpret the fulfillment passed in >>>>>>>>>>>> their protocol, not the one passed through the Interledger layer. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> This is not correct. There is no requirement on ledger layer >>>>>>>>>>> protocols to transmit or understand the fulfillment. You are looking at >>>>>>>>>>> this through the lens of existing implementations from the bottom up >>>>>>>>>>> instead of starting at the interledger layer. >>>>>>>>>>> >>>>>>>>>>> The primary function of the condition and fulfillment is as a >>>>>>>>>>> signed end-to-end receipt. If the sender agrees a condition with a receiver >>>>>>>>>>> and then gets back the valid fulfillment they don't care what happened in >>>>>>>>>>> the middle. The receiver has signed a receipt saying they have their money. >>>>>>>>>>> >>>>>>>>>>> The value of using a standard for the receipt and signature is >>>>>>>>>>> that each transfer along the way CAN re-use it. One the one hand you can >>>>>>>>>>> have a transfer between two peers that have zero trust and the ledger they >>>>>>>>>>> use supports conditional payments completely. On the other extreme you can >>>>>>>>>>> have two peers that have a full trust and ignore the condition and >>>>>>>>>>> fulfillment completely. >>>>>>>>>>> >>>>>>>>>>> The ledger layer protocols carry ILP packets. Payment requests >>>>>>>>>>> and either fulfillment or error responses. If a ledger layer protocol wants >>>>>>>>>>> to use the condition and fulfillment for their own operations they can >>>>>>>>>>> extract these from the ILP packets and use them. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> > - While it may make sense to split the interledger payment >>>>>>>>>>>> and interledger quoting protocols into new higher level protocols that >>>>>>>>>>>> seems like an unnecessary abstraction. Instead the packet definitions >>>>>>>>>>>> should just have some consistency and probably a common base/header. >>>>>>>>>>>> >>>>>>>>>>>> The current protocols effectively have this header but it isn't >>>>>>>>>>>> separated out. There are two fields in the request header: type and >>>>>>>>>>>> destination address. There is one field in the response header: type. I >>>>>>>>>>>> don't think it makes that much of a big difference to separate these fields >>>>>>>>>>>> if all of the fields in that packet need to be interpreted together (for >>>>>>>>>>>> example, you can't understand a quote request if you strip off the >>>>>>>>>>>> destination address). >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> I agree that we don't HAVE to explicitly separate them out but I >>>>>>>>>>> think ti would make it clearer how the stack is architected if there was a >>>>>>>>>>> header that was consistent across all packets. Currently the only thing >>>>>>>>>>> that is consitent across all ILP packets is that they are defined int he >>>>>>>>>>> same file. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> > - We should define two base ILP packet types: request and >>>>>>>>>>>> response. >>>>>>>>>>>> >>>>>>>>>>>> Unless this adds some substantive benefit or new fields I don't >>>>>>>>>>>> think it's worth breaking all of the formats we have just to rearrange >>>>>>>>>>>> things. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> The goal of this exercise is to tease out the best design and >>>>>>>>>>> ignore the cost of change until we can compare the results with the current >>>>>>>>>>> design. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> > - ILP is not about ledgers, it is about trustlines between >>>>>>>>>>>> nodes/hosts. >>>>>>>>>>>> >>>>>>>>>>>> A ledger is any system that tracks accounts and balances. When >>>>>>>>>>>> you use a trustline all of your messages still need to go through an >>>>>>>>>>>> accounting system (such as the plugin in the JS implementation) and then on >>>>>>>>>>>> to the other program logic. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> As above, this is incorrect. There is no requirement for "all >>>>>>>>>>> messages to go through an accounting system". >>>>>>>>>>> >>>>>>>>>>> Since designing the first implementation of 5-bells ledger we >>>>>>>>>>> have assumed that passing the ILP packet MUST be done by the ledger because >>>>>>>>>>> that is how we implemented it. But that is not true. It is perfectly valid >>>>>>>>>>> for the passing of an ILP packet from one peer to another to be simply an >>>>>>>>>>> exchange of data. >>>>>>>>>>> >>>>>>>>>>> The receiving peer makes a decision about whether or not to >>>>>>>>>>> forward the packet based on the current financial position they have with >>>>>>>>>>> the sending peer. >>>>>>>>>>> >>>>>>>>>>> It is convenient if the ledger that records the net positions of >>>>>>>>>>> the peers also forwards the messaging and even better if it natively >>>>>>>>>>> supports conditional payments and can use the condition and the fulfillment >>>>>>>>>>> from the ILP packet for those but that's all it is, convenient. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> In that case, the plugin or whatever is doing the accounting is >>>>>>>>>>>> the ledger. Digital value is always tracked in ledgers, so I think it does >>>>>>>>>>>> make sense to think of this as the base layer. The reason to abstract the >>>>>>>>>>>> functionality you expect from the ledger layer is precisely so you can >>>>>>>>>>>> handle it in different ways, depending on what the underlying systems >>>>>>>>>>>> provide. >>>>>>>>>>>> >>>>>>>>>>>> I see 3 ways to think of the layer(s) underpinning ILP: >>>>>>>>>>>> >>>>>>>>>>>> 1. The "Ledger Layer" provides both messaging capabilities >>>>>>>>>>>> and some type of HTLA >>>>>>>>>>>> <https://github.com/interledger/rfcs/blob/master/0022-hashed-timelock-agreements/0022-hashed-timelock-agreements.md> >>>>>>>>>>>> 2. There are separate plugins for messaging and for >>>>>>>>>>>> transfers and when you peer with someone you have to agree on a plugin for >>>>>>>>>>>> each >>>>>>>>>>>> 3. We standardize the messaging part and say that all goes >>>>>>>>>>>> over IP and then just have more minimal plugins for the on-ledger >>>>>>>>>>>> settlements >>>>>>>>>>>> >>>>>>>>>>>> Number 1 is what we have and I think that still makes the most >>>>>>>>>>>> sense. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> I think you're confusing implementation details and defining of >>>>>>>>>>> interfaces with definition of a protocol stack. The only differences >>>>>>>>>>> between the tree examples you have above is in implementation. >>>>>>>>>>> >>>>>>>>>>> From the perspective of the Interledger Protocol the >>>>>>>>>>> implementation of the lower layers is not important, that's the whole point >>>>>>>>>>> of layering. By forcing important aspects of ILP like the condition, >>>>>>>>>>> fulfillment and expiry down into those layers you muddy the waters and we >>>>>>>>>>> now have to standardize those protocols too. Instead we should just be >>>>>>>>>>> defining the functions they must provide and then leave it up to >>>>>>>>>>> implementations to provide those functions. >>>>>>>>>>> >>>>>>>>>>> I know we want to define a standard to bootstrap the system >>>>>>>>>>> (CLP) but that's misleading us into thinking it's an essential part of the >>>>>>>>>>> stack. It's perfectly valid for two peers to not use CLP and still be part >>>>>>>>>>> of the Interledger. >>>>>>>>>>> >>>>>>>>>>> That said, you raise an interesting consideration about the >>>>>>>>>>> layers below ILP and actually I think it makes sense to split these. >>>>>>>>>>> >>>>>>>>>>> We keep trying to force messaging through the ledger layer and >>>>>>>>>>> actually that's the wrong place to put it if we can split the ledger layer >>>>>>>>>>> into a messaging layer and a ledger layer. That way we can stop trying to >>>>>>>>>>> think of all HLTAs as ledgers. >>>>>>>>>>> >>>>>>>>>>> A thought, why not use sub-layers as is common in other stacks: >>>>>>>>>>> >>>>>>>>>>> 1. Link layer: Layer upon which two peers that have a direct >>>>>>>>>>> link, or participate in the same payment network, communicate >>>>>>>>>>> 2. Transfer/ ledger: Layer on which financial positions between >>>>>>>>>>> two peers are recorded >>>>>>>>>>> >>>>>>>>>>> This reflects the already emerging HTLA model and many of our >>>>>>>>>>> existing plugins and ledger integrations. >>>>>>>>>>> Link Layer: XRP Paychan, Lightning >>>>>>>>>>> Ledger Layer: XRP Ledger, Bitcoin >>>>>>>>>>> >>>>>>>>>>> This doesn't prevent us from defining a standard binary protocol >>>>>>>>>>> that defines all of the operations for both layers (like CLP) but I see >>>>>>>>>>> value in distinguishing between these two. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> > - The protocol should differentiate between the operation of >>>>>>>>>>>> preparing a transfer on a ledger and the operation of passing an ILP packet >>>>>>>>>>>> from one peer to another. >>>>>>>>>>>> >>>>>>>>>>>> The protocol assumes your conditional transfer is underpinned >>>>>>>>>>>> by some HTLA >>>>>>>>>>>> <https://github.com/interledger/rfcs/blob/master/0022-hashed-timelock-agreements/0022-hashed-timelock-agreements.md>. >>>>>>>>>>>> It doesn't care whether that's on-ledger or not. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> What do you mean when you say "the protocol"? In my statement I >>>>>>>>>>> am referring to ILP. >>>>>>>>>>> My point above being that ILP expects ILP packets to be passed >>>>>>>>>>> from peer to peer but has no expectations about transfers. >>>>>>>>>>> >>>>>>>>>>> It's perfectly legal (from an ILP perspective) for two peers to >>>>>>>>>>> exchange ILP packets with no transfers. Clearly if a node routes a packet >>>>>>>>>>> on and has no incoming transfer it's going to lose money but that's a >>>>>>>>>>> consideration for that node. It doesn't affect anyone else in the chain. >>>>>>>>>>> >>>>>>>>>>> ILP doesn't assume anything about transfers at all, let alone >>>>>>>>>>> conditional transfers. It provides useful semantics for conditional >>>>>>>>>>> transfers to be used by two peers to transact as part of a larger ILP >>>>>>>>>>> payment. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> > - The condition and timeout should be included in the ILP >>>>>>>>>>>> payment packet. >>>>>>>>>>>> >>>>>>>>>>>> I strongly disagree with this. We had this debate a year ago >>>>>>>>>>>> and I was on your side but was convinced that this is not a good idea. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Yes, I recall this and I'm sorry I didn't push harder on this >>>>>>>>>>> point. Unfortunately I think the decision to pull it out of the packet is >>>>>>>>>>> mostly driven by how our prototypes were implemented rather than good >>>>>>>>>>> architecture. >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> The layer below ILP must be capable of doing conditional >>>>>>>>>>>> transfers based on sha256 hashlocks with 32-byte preimages. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> This is not true and I think it would be useful for us to agree >>>>>>>>>>> on this as this seems to be the argument I am coming up against most often. >>>>>>>>>>> The peers participating in a transfer that is part of an ILP payment may >>>>>>>>>>> wish to use conditional transfers as a way to enforce their agreement but >>>>>>>>>>> this is not a requirement of the protocol. >>>>>>>>>>> >>>>>>>>>>> The agreement between any two peers is: "I will pay you X if you >>>>>>>>>>> can provide a receipt that Y was paid Z before T". >>>>>>>>>>> ILP provides a standard for expressing this agreement so that >>>>>>>>>>> these can be chained together BUT it is not a requirement that every >>>>>>>>>>> agreement in the chain uses the condition, and fulfillment provided at the >>>>>>>>>>> ILP layer. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> As a result, the original condition and the corresponding >>>>>>>>>>>> preimage MUST be expressed in that layer. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> As I have shown above, this is not true. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Then the question is whether we should also include it in the >>>>>>>>>>>> packet that is forwarded. What ultimately convinced me is the following: >>>>>>>>>>>> All connectors MUST ignore the condition if it is in the packet, because >>>>>>>>>>>> they are only guaranteed their money back if they use the same condition >>>>>>>>>>>> from the incoming transfer they got. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> Here is where the layering is being corrupted. >>>>>>>>>>> >>>>>>>>>>> All connectors MUST inspect the condition in the ILP packet as >>>>>>>>>>> part of their decision to route the packet or not. >>>>>>>>>>> When the local transfer module of the connectors stack passes >>>>>>>>>>> the ILP packet up to the ILP module it should indicate the properties of >>>>>>>>>>> the incoming transfer that carried the packet. >>>>>>>>>>> This is essential firstly so that the routing logic in the ILP >>>>>>>>>>> module can record the incoming transfer identifier so it is able to use the >>>>>>>>>>> correct response id when it passes back the fulfillment or error. >>>>>>>>>>> The other properties that the ILP module should look at are the >>>>>>>>>>> condition and expiry on the incoming transfer. >>>>>>>>>>> >>>>>>>>>>> If the incoming route uses conditional transfers and these are >>>>>>>>>>> supposed to match the condition and expiry in the ILP packet then the ILP >>>>>>>>>>> module should compare them and reject the packet if: >>>>>>>>>>> a) the conditions don't match OR >>>>>>>>>>> b) the expiry is too short >>>>>>>>>>> >>>>>>>>>>> We should still discuss if the expiry should be set by the >>>>>>>>>>> sender and left unchanged or used like a TTL and decremented by each node. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> Also, the receiver will need to take out the condition in order >>>>>>>>>>>> to hash the packet for PSK or IPR. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> This is completely normal. Zeroing a checksum field in a header >>>>>>>>>>> before calculating the checksum is VERY common precisely because it's long >>>>>>>>>>> been accepted that the right place to put that data is in the headers and >>>>>>>>>>> the work of zero'ing it out to calculate the checksum (or signature in our >>>>>>>>>>> case) is not material. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> So basically, no one wants the condition in there. It feels >>>>>>>>>>>> like it ought to be in there, but literally none of the parties want the >>>>>>>>>>>> extra 32 bytes in there. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> "Nobody wants it there" is a terrible reason to abandon the >>>>>>>>>>> correct design. The whole purpose of a good architecture is you accept that >>>>>>>>>>> there may be cases in future that haven't been considered now so designing >>>>>>>>>>> just for the known cases is a bad idea. >>>>>>>>>>> >>>>>>>>>>> Good architecture is not the same as optimization. Taking stuff >>>>>>>>>>> out (even when it feels wrong) to save a few bytes is a good sign that it's >>>>>>>>>>> a bad idea. >>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> The reason the timeout should not be in there is that there >>>>>>>>>>>> isn't a single timeout for the payment. There are multiple separate >>>>>>>>>>>> timeouts for each of the bilateral transfers. Those must go in the >>>>>>>>>>>> individual transfers and there is no sensible value to put in the >>>>>>>>>>>> Interledger packet. >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>>> As above, this is somewhat equivalent to the TTL in an IP >>>>>>>>>>> packet. I'm open to discussing if it should be a fixed value set by the >>>>>>>>>>> sender where each node uses their own value but has the sender-defined >>>>>>>>>>> value as a reference or it is actually decremented at each hop. >>>>>>>>>>> >>>>>>>>>>> Either way, this is part of ILP not the ledger layer just like >>>>>>>>>>> the condition and fulfillment. It may be used by the ledger layer but >>>>>>>>>>> that's implementation specific. It belongs in the ILP packet. >>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>>> >>>>>>>>>>> >>>>>>>>>> >>>>>>>>> >>>>>>>> -- >>>>>>> Sent from a mobile device, please excuse any typos >>>>>>> >>>>>> >>>>>> >>>>> >>>> >>> >> >
Received on Friday, 18 August 2017 21:39:39 UTC