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

OK, I think in that case we're mostly disagreeing over where the
condition/fulfillment/expiry actually go in the data. The reason I don't
agree with your position is based on which parties I think should be aware
of ILP. I'll hold off on arguments about which current implementations this
would break.

There are a lot of cases where the ledger isn't going to care about the
condition and fulfillment of an individual interledger payment. In this
situation, transfers would be sent directly between two connectors. The
connectors would still keep track of the balance between them (you could
contrive a situation where this doesn't happen, but I think we can say
tracking the balance is going to be the norm). 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.
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.

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. Then the connectors'
ILP-packet-related behavior can all be routing related. 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. 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).

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.

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.

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 Wednesday, 16 August 2017 09:23:20 UTC