Re: [Ledger] An attempt to clean up the protocol architecture

>
> 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