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

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

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.

>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. 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. If the ledger layer has to look into the ILP
packet to do so, that is a blatant breaking of layering. 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.

I agree that Interledger defines how conditions, fulfillments, and expiries
should be chained together, but it makes no assertions about their data
format. ILP says you should send your outgoing transfer with the same
condition as the incoming one, and a lower expiry. But because ILP allows
for many different types of ledgers, it doesn't make sense to assert how
these are encoded.

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

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.

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

Received on Tuesday, 15 August 2017 14:07:53 UTC