- From: Andrew Bransford Brown <andrewbb@gmail.com>
- Date: Fri, 18 Aug 2017 16:10:43 -0400
- To: Adrian Hope-Bailie <adrian@hopebailie.com>
- Cc: Ben Sharafian <sharafian@ripple.com>, Evan Schwartz <evan@ripple.com>, Interledger Community Group <public-interledger@w3.org>, Interledger Mailing List - IETF <ledger@ietf.org>
- Message-ID: <CAPS+YFK0iVK=srHeKf+d9YFqF6JXfbFpA58NuJVWHY8nZ-qFJQ@mail.gmail.com>
If the human species survives, they'll say humans nearly went extinct, because some liked to keep secrets (top secret, secret, classified). On Thu, Aug 17, 2017 at 1: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 20:11:09 UTC