What should positive / negative balances represent?

Let’s say that ILP nodes keep track of “account” records for each of their customers and peers.

From the perspective of Alice’s node, if the Bob account has a balance of 100, does/should that mean that Alice owes Bob 100 or that Bob owes Alice 100 units?

Also, if Bob queries the API of Alice’s node to check his balance, should Alice’s node report her view of Bob’s balance or should it be negated?

cc @sappenin @adrianhopebailie @matdehaast

6 Likes

From the perspective of Alice’s node, if the Bob account has a balance of 100, does/should that mean that Alice owes Bob 100 or that Bob owes Alice 100 units?

IMO, Alice owes Bob 100 units. In other words, the Connector should always view a positive balance as a “liability” account, meaning: “the account holder has 100 units with me but those units are not mine, they are theirs.”

Conversely, from the perspective of Alice’s node, if the Bob account has a balance of -100, then this should be treated as a negative liability, or I guess in accounting terms a “receivable.” In other words, “Bob owes Alice 100 units.” In this scenario, Alice has basically made a loan to Bob.

…if Bob queries the API of Alice’s node to check his balance, should Alice’s node report her view of Bob’s balance or should it be negated?

As a matter of good API design, Alice’s node should report whatever would be most helpful for Bob. In this case, I think that would be Bob’s view of Bob’s balance. Essentially, Bob is the primary consumer of this API (for his account at least) so good Connector API design should optimize for Bob’s experience, and when Bob queries for his balance, he’s asking, “how much value do I have on deposit at you, Alice?”


Here’s some of my thought process to arrive at this:

  • Imagine Bob were to swipe a payment-card at some terminal that allowed him to pay Alice’s connector account 100 units. In ILP, we have historically called this a sendMoney or a settlement operation, and after such an operation, when Bob queries Alice’s API, he should get a response back that shows 100 units. From Bob’s perspective, it means he has 100 units sitting at “Alice” that are his. By using ILP packets, Bob can instruct Alice to take some of those 100 units and send them to others, in order to facilitate an ILP value-transfer chain.
  • For example, when Bob sends an ILP Prepare packet to Alice with an amount of 1 unit and addressed to Charlie, Bob is basically saying, “*Please take 1 unit out of my account and give it to Charlie.” If Bob has units in his account to give to Charlie, then Alice should happily oblige. However, if Bob has no units in his account, then Alice has a decision to make: should she allow Bob’s account to go negative, in which case Bob will owe her 1 unit. This would create a debt position between Alice and Bob, and if Bob doesn’t pay back, then Alice might be sad.

Speaking from the perspective of a Connector, this means the following should hold:

  1. An incoming ILP Prepare decreases the balance of the account the Connector is tracking.
  2. An outgoing ILP Prepare increases the balance of the account the Connector is tracking.
  3. Receiving a settlement payment for a particular account increases the balance.
  4. Sending a settlement payment for a particular account decreases the balance.
  5. From an accounting perspective, a Connector should view the value tracked by the balance tracker as a “liability.” In other words, a positive balance is actually value owed to the account holder.

Note that this is exactly the inverse of the JS ILP Connector. I’d be curious to hear from others who have experience with that implementation.

1 Like

Here’s my model of this, and how it’s currently implemented in ilp-sdk and the Ethereum and Lightning plugins (but not the connector balance middleware).

“Payable Balance” (Outgoing Balance)

  • Amount owed by us to our peer for packets we’ve sent to them and were returned fulfilled
    • Positive amount indicates we’re indebted to the peer and need to pay them for packets they’ve already forwarded and returned fulfilled
    • Negative amount indicates we’ve prefunded the peer and have as much credit available to send packets that the peer should forward
  • Changes
    • Outgoing settlements to the peer decrease the amount we owe to them
    • Outgoing PREPARE packets to the peer increase the amount we owe to them, but only after we receive a FULFILL packet
  • Effects
    • Determines when outgoing settlements to peer occur and for how much

“Receivable Balance” (Incoming Balance)

  • Amount owed to us by our peer for packets from them we’ve forwarded
    • Positive amount indicates our peer is indebted to us for packets we’ve already forwarded and have not yet returned a REJECT
    • Negative amount indicates our peer has prefunded us and has as much credit available to send packets that we should forward
  • Changes
    • Incoming settlements from the peer decrease the amount they owe to us
    • Incoming PREPARE packets from the peer immediately increase the amount they owe to us, unless we respond with a REJECT (e.g. we decline to forward it, or it’s later rejected upstream, which decreases the amount they owe us by the same amount).
  • Effects
    • Determines if an incoming PREPARE is forwarded/cleared

Problems with a single balance

The current balance model in ilp-connector works great for net settlement in which both peers extend credit to one another, but introduces problems when one peer prefunds, and the other extends no credit.

  • Suppose Alice prefunds Bob 200 units. Later, Bob forwards a PREPARE to Alice for 100 units, and Alice returns the FULFILL (also Bob has a settleTo and settleThreshold of 0, which I think is reasonable for a open server). The ilp-connector balance middleware will then send a settlement to Alice for 300 units, which would then trigger Alice to prefund another 200 units.
  • The problem with this is more frequent and more capital intensive settlements, which is particularly bad for plugins based on unidirectional payment channels, since liquidity will be exhausted far faster than it needs to be.
  • The essence of it: there’s no way to differentiate between them owing you money for packets they send to you that you return fulfilled, and you owing them money for packets you send to them that they return fulfilled.

In this model, if a peer prefunds money to you and later wants to get it back, they must fulfill packets to themselves. Alice may prefund as much as she wants to Bob, but only ILP packets create an obligation for Bob to payout any of that sum.

However, if both peers extend credit, net settlement is likely preferred, since this model may exhaust liquidity faster.

I’d like to think more about how to support both models (I think it only requires changes to the settleTo logic in order to work), but I think generalizing it to two separate balances is necessary to fix issues with accounting relationships where one peer doesn’t extend any credit.


The rationale beyond branding them “payable balance” and “receivable balance” and using these particular positive/negative interpretations is to correspond to accounts payable and accounts receivable in GAAP.

Accounts payable: “money owed by a business to its suppliers shown as a liability on a company’s balance sheet” or “an accounting entry that represents a company’s obligation to pay off a short-term debt to its creditors or suppliers”

Accounts receivable: “the balance of money due to a firm for goods or services delivered or used but not yet paid for by customers” or “amounts of money owed by customers to another entity for goods or services delivered or used on credit but not yet paid for by clients”

The thing I’m not entirely sure about is how prepayment is traditionally accounted for: does the account balance go negative, or is there an entirely different account?

3 Likes

You must create a current asset account on your balance sheet to reflect the balance of the future benefit you receive as a result of your prepayment.

This is really helpful. Thanks all for weighing in on this!

After speaking with some folks that know a lot more about accounting than I, it seems like we should:

  • have separate Payable and Receivable balances like @kincaid suggests
  • separate out the pending Prepare packets that haven’t been resolved yet
  • account for pre-payment as a negative Receivable balance

Here’s a modified version of what @kincaid suggested with the pending packet amounts split out:

Balances to track:

  • Payable Balance (amount I owe to counterparty)
  • Receivable Balance (amount counterparty owes me)
  • Pending Outgoing Prepares (amount I would owe to counterparty if in-flight transactions are executed)
  • Pending Incoming Prepares (amount the counterparty would owe me if in-flight transactions are executed)

Thresholds to track:

  • Credit Limit (Receivable Balance + Pending Incoming Prepares - Payable Balance)
  • Settlement threshold (Payable Balance)
  • Netting trigger (when Receivable Balance and Payable Balance are positive)
Action Effect
Receive Incoming Prepare + Pending Incoming Prepares
Send Outgoing Prepare + Pending Outgoing Prepares
Receive Fulfill for Outgoing Prepare - Pending Outgoing Prepares, + Payable Balance
Send Fulfill for Incoming Prepare - Pending Incoming Prepares, + Receivable Balance
Receive Reject for Outgoing Prepare - Pending Outgoing Prepares
Send Reject for Incoming Prepare - Pending Incoming Prepares
Receive Incoming Settlement - Receivable Balance
Send Outgoing Settlement - Payable Balance
Internal Netting - Receivable Balance, - Payable Balance

(Note that an earlier version of this post used the term “Buy Order” for “Pending Outgoing Prepares” and “Sell Order” for “Pending Incoming Prepares” because those are more common accounting concepts. However, the order terminology is too easily confused with exchange / currency trading orders.)

Netting

I think we can enable the two balances to be netted out without causing the pre-payment refund problem described above in the following way (described in rusty-pseudocode):

if payable_balance > 0 && receivable_balance > 0 {
  let amount_to_net = min(payable_balance, receivable_balance);
  payable_balance = payable_balance - amount_to_net;
  receivable_balance = receivable_balance - amount_to_net;
}

Let me know if you think there’s something I’m overlooking but it seems like this should work.

2 Likes

I am going to play devil’s advocate here. I want to preface my comments by asking “What is the underlaying issue we are trying to solve by creating more than a single balance?”. This is to ensure we are actually solving a real problem we face rather than doing it for the sake of doing it.

Reply to @kincaid

In the current single balance architecture the correct way to handle this would be for Bob to know he only accepts pre-funded accounts and thus would set settleTo=-200 and settleThreshold=-200. This would ensure the issue you describe would not occur. I don’t agree that these would be zero if you are accepting prefunded peers.

How is this resolved by using a two balance approach? As far as I can see regardless of how balance is tracked, you would still need a mechanism to receiving your prefunded amount back which will be the net amount anyway.

I agree entirely there is currently no way to differentiate! Having gone through the mental and excel modelling of the various cases. I am trying to work out why we need to differentiate. Ultimately we are managing a net liquidity line between to parties. The operative term being NET.

Reply to @emschwartz

What benefit do we get from tracking the extra pending balances? In my opinion we should be optimistic about packets being fulfilled that we are forwarding and do the corrective entries for when they are rejected (As is currently done). As ultimately we are going to have far more successful packets than not.

I don’t think this is correct for a pre-funded model as in a pre-funded model you would never let your receivables get into a positive balance. As a positive receivable represents a credit has been extended to your counter-party. Though I could be mistaken on the intent of the code.

Overall Thoughts
I do somehow believe that a two balance approach of receivables and payables is the correct way to do this. For the life of me I can’t find a good reason why though. That is the disjoint I am struggling with.
Ultimately we are balancing the liquidity lines between two parties based on a net. In which case we only care about the net. Then why go through all the effort of tracking multiple balances?

Two high-level points:

  1. We’re solving the current balance middleware spitting back the money you prefunded, which is undesirable.
  2. I think accurately domain modeling this is very beneficial. In my case, it simplified my mental model a lot, which makes things much easier to debug and implement.

In the current single balance architecture the correct way to handle this would be for Bob to know he only accepts pre-funded accounts and thus would set settleTo=-200 and settleThreshold=-200 . This would ensure the issue you describe would not occur. I don’t agree that these would be zero if you are accepting prefunded peers.

But the point is that Alice should be able to prefund any amount, and Alice and Bob shouldn’t have to coordinate their balance configuration in order for this to work. If Bob’s configured that way, and suppose Alice prefunds 600 units, then Bob forwards a 100 unit PREPARE to Alice and she returns the FULFILL, Bob will send a settlement to Alice for 300 units (which is undesirable: the settlement should be for 100 units, only the amount Bob owes Alice for the packet sent to her).

(Furthermore, Alice would also need to configure her max balance to correspond to Bob’s settleTo/settleThreshold, requiring some degree of coordination. For manually configured peers, this is fine, but for open servers, I’d much prefer everything to happen seamlessly by just assuming it’s 0).

I would also point out that ilp-plugin-xrp-asym-server effectively has the same behavior as a settleTo/settleThreshold of 0, so it’s not just our implementation.

How is this resolved by using a two balance approach? As far as I can see regardless of how balance is tracked, you would still need a mechanism to receiving your prefunded amount back which will be the net amount anyway.

I was just clarifying how you could get the prefunded amount back in the proposed model, and not that it solves any problem. (In the current balance middleware that isn’t a problem, because as outlined, it’ll just spit it back to you!)

I agree entirely there is currently no way to differentiate! Having gone through the mental and excel modelling of the various cases. I am trying to work out why we need to differentiate. Ultimately we are managing a net liquidity line between to parties. The operative term being NET .

I don’t think this is correct for a pre-funded model as in a pre-funded model you would never let your receivables get into a positive balance. As a positive receivable represents a credit has been extended to your counter-party. Though I could be mistaken on the intent of the code.

For prefunded peers, there would be no netting, in order to resolve the spitting back money issue. Since the netting requires the balances to be positive, the netting would only occur for peers that extend credit to one another (which is what we want).

I would caveat that @emschwartz and I want to think more about the netting behavior (I think we’re almost there, but we haven’t quite cracked it yet). One weird case with this model: suppose a connector extends me no credit. Then, it sends a packet to me for 50 units, which I fulfill (my payableBalance on the connector is now +50 units). Also suppose, the connector doesn’t settle right away. If I send a packet to the connector for up to 50 units, should the connector forward it? We’ve been trying to think about how to make that work, while still fixing the prefunding issue.

Let’s keep reminding ourselves that the purpose of discussing these designs is to ensure we standardize where necessary but we should also leave as much as possible up to implementors.

Standardization is required for interoperability. In this case I was tempted to say this issue is not something we need to standardize but @kincaid’s last paragraph made me realise this is not entirely true, even if we have no API or interface for exchanging this data between peers.

As a connector it is important for me to know my peer’s view of my balance. If I view this from a net perspective and the peer manages separate payable and receivable balances then I may think I can send packets via my peer but actually I can’t.

So we do need to standardize this, even if there is no interface between peers for getting/setting balances it’s important that peers track them in a similar way.

The next question then, as always, is whether we favour simplicity or flexibility and importantly understanding exactly what compromises we make in whatever design we choose.

When we favour simplicity we will always be making compromises and we should be very clear on what those are before we make them.

In this case simplicity is a single balance and flexibility is two balances. It seems that the compromise for simplicity is a lack of support for certain prepaid use cases.

In contrast, it seems that the compromise when using multiple balances is that we need to provide a way for a peer to request a “transfer” from their payable balance into their receivable balance.

Without giving an opinion yet on which I think is a preferable compromise, can we agree that:

  1. We do need to standardize this
  2. Those are our options and the relative compromises that each presents.

I’d put it slightly differently and say that we need to standardize:

  • Whether nodes MUST / SHOULD / MAY net balances (this can happen whether the balance is tracked as a single number that represents the net or two that are automatically netted against one another)
  • If there is a way to query your “balance” on the peer’s system, what the number you get back represents
  • If there is a way to explicitly request a settlement or transfer payable balance to receivable balance

I disagree. Saying anything but a “MUST” is pointless because (as I explained above) any variance will mean nodes are not interoperable.

The behaviour of a connector depends on it knowing how its peer is tracking its balances. (See the example @kincaid cites above)

We need to standardize how nodes track balances, not just for the sake of being able to answer queries but for the sake of behaving predictably.

As an illustration, imagine a test case where you send a pre-funding settlement to a connector, then send it some packets, then receive some packets, then send it some more packets.

Unless you know how that connector tracks balances you can’t predict if the tests will pass. The packets you send at the end may be fulfilled or rejected depending on if the connector tracks net or split balances.

If you can’t write predictable tests then you know that it’s possible to produce implementations that are not interoperable and the spec is not tight enough.

If we answer the above first then deciding on this is easy right?

Not sure how we could return payable and receivable balances from nodes that only track a net…

Also not sure why you’d only return a net if you have payable and receivable available and the caller can trivially do the netting themselves.

Again, if we make a decision on how balances are tracked it will follow whether we need this or not.

As I explained, I think it’s dangerous to simply look at the list of things we need to standardise without considering the compromises we’ll make in selecting different solutions.

So, I’ll assert again, I think a connector MUST track balances in a particular way and this must be a normative requirement for all connectors. What remains to decide is, should this be net or split between payable and receivable.

Whether or not everyone is required to implement the conclusion of this discussion, I am certainly planning to implement it.

After talking with @sappenin and @kincaid briefly I’m back to thinking we can make this work with Receivable and Payable balances. If we don’t keep track of the pending amounts separately, we just need to be very careful about when we apply changes to the balances.

The specific features we want to enable are:

  • Automatic settlement (triggering settlement when one party owes the other party more than a configured threshold amount)
  • Automatic netting (I should be able to spend from money you owe me, whether you owe it to me because I fulfilled packets you sent to me or because I sent a settlement to you)
  • Pre-funding (I may want to send you a settlement before I send packets through you to cover packets I will send)
  • Minimal bilateral communication about limits and thresholds (we would like to avoid having to discuss the specific limits and thresholds we’re configuring our systems with)

This is the table of actions and effects:

Action Effect Check Limit / Threshold
Receive Incoming Prepare if Receivable + Prepare Amount <= Max Receivable { + Receivable } else if Payable >= Prepare Amount { - Payable Balance } Limit: Receivable + Prepare Amount - Payable <= Max Receivable
Send Outgoing Prepare No effect
Receive Fulfill for Outgoing Prepare + Payable Balance Net if Payable > 0 and Receivable > 0; Settle if Payable >= Settle Threshold
Send Fulfill for Incoming Prepare No effect
Receive Reject for Outgoing Prepare No effect
Send Reject for Incoming Prepare + Payable Balance Net if Payable > 0 and Receivable > 0, Settle if Payable >= Settle Threshold
Receive Incoming Settlement - Receivable Balance
(Before) Send Outgoing Settlement - Payable Balance
Internal Netting - Receivable Balance, - Payable Balance

@matdehaast I think that two balances enables pre-funding while keeping the communication about the thresholds to a minimum and avoiding the settling back and forth forever problem @kincaid described.

2 Likes

I also quite like the split balance tracking, even if it’s just simpler to reason about. But, if we standardize on that, we do need to solve for a few additional complexities so that connectors behave in a predictable way.

I like the breakdown you’ve put together but have a few questions:

Automatic settlement: Does this get triggered based on a net amount or just the Payable amount?

Simplicity suggests just the Payable amount but…

One of the goals of a good settlement architecture is to do settlement as little as possible because, in general, a settlement transaction costs more than a payment transaction so the more payments you can make per settlement the better.

On that basis we probably want to explicitly rebalance the accounts by making a transfer from the Receivables account into the Payables account in preference to actually settling with the peer.

  1. What triggers this to happen? Can it be invoked by the peer?
  2. Should the node only do this internal rebalancing if the Receivables balance is high enough to settle Payables back to the “SettleTo” balance?
  3. Should there be a standard for notifying the peer that the accounts have been rebalanced?

Automatic netting: The “Effect” you have defined for Receive Incoming Prepare suggests that netting is applied ad-hoc as part of processing a packet. Is that the intent?

If so then I’m back in the same boat as @matdehaast and wondering what value tracking the two balances adds if the observed effect for a peer is a net balance and they have no control over when netting happens or even visibility into when it happens?

Send Reject for Incoming Prepare: You’ve listed the effect of this as + Payable Balance instead of - Receivable Balance. Why?

It has the interesting side-effect that a peer can force a transfer from its Receivable balance to its Payable balance by simply sending an unfulfillable packet. Possibly a nice feature of the design but I’d want to call it out explicitly.

Minimal bilateral communication: Why is this as a feature you explicitly want to enable? It seems like an unnecessary constraint.

1 Like

Thanks for this Evan. I am going to present some case studies to show where there are still open questions to the model described above. In all the cases below Alice is prefunding an account with Bob
and the balances of receivable and payable will be from Bob’s perspective.

Case 1

  1. Alice prefunds 200 units with Bob.
    • Receivable: -200
    • Payable: 0
  2. Bob fulfils a packet towards Alice for 100 units
    • Receivable: -200
    • Payable: 100

I would assume that settlement would need to occur now but using the Limit and Threshold of:

No settlement would occur. I think it should be

Also what is the settlement amount? I would assume it would be only what is contained within the payable balance and hence be 100 units.

Case 2

  1. Alice prefunds 200 units with Bob.
    • Receivable: -200
    • Payable: 0
  2. Bob fulfils a packet towards Alice for 100 units
    • Receivable: -200
    • Payable: 100
  3. Alice sends a ILP prepare through Bob for 300 units
    • Receivable: -200
    • Payable: -200

Now the payable balance has ended up in a credit.

This above limit would ensure Alice could not send any more packets. The better way is to consume all the receivable balance first, till it is exhausted ,and then consume the payable balance. Which would result in the balance after the transaction looking like

  • Receivable: 0
  • Payable: 0

Case 3

  1. Alice prefunds 200 units with Bob.
    • Receivable: -200
    • Payable: 0
  2. Alice increases prefund to 400 units to help deal with a large transaction
    • Receivable: -400
    • Payable: 0
  3. Alice does transaction and ends with her prefund still at 400 units. Now she wants to decrease her prefunded amount back to a minimum of 200 units. What does Alice do to allow this?

Case 4

  1. Alice prefunds 200 units with Bob.
    • Receivable: -200
    • Payable: 0
  2. Alice receives a fulfilled packet for 200 units
    • Receivable: -200
    • Payable: 200
  3. Alice receives another fulfilled packet for 200 units
    • Receivable: -200
    • Payable: 400

But Alice does not want to extend so much credit to Bob. She could reject the packets but I feel there needs to be a mechanism for Bob to understand what amount of credit Alice is willing to allow. this could potentially be dynamic based on the need to receive larger payments at a higher throughput.

Further if it is a large payment coming through. Bob is going to be attempting to settle with every packet in the model described by @kincaid, where you set the settlementThreshold to 0. Seems inefficient.

Open Questions Generally:

  • How do we deal with cashing out/reducing the prefunded amount?
  • How to deal with counterparty agreement on credit lines. ie How does Alice notify Bob of her tolerable credit limits.

From my assessment the open questions and issues are resolved by having the ability to dynamically configure (or at least notify) your counterparty of your acceptable risk to be able to configure these on the fly.

Interestingly the ability for Bob to specify his credit allowance to Alice is a negative (ie needs prefunding) and Alice being able to specify her tolerable credit she wants to extend Bob are the same issue. What brings me back to the point above that setting or at least informing your counterparty of what you will tolerate seems reasonable. The question is how do you encapsulate that nicely.

For what it’s worth, I think the model I described in the last post may be functionally equivalent to tracking a net balance and keeping a separate count of prepaid funds. It’s possible that tracking the net balance and prepaid funds would more clearly model the behavior we want (assuming we don’t want prepaid funds to be sent back as a settlement).

That sounds like what I described as netting, no? If both the Receivables and Payables are greater than zero, you can net instead of settle the Payables.

Yes. I didn’t originally implement it that way but then found it strange that if you forward Prepares to me that are then fulfilled, I can’t send an equal value of Prepares back to you even though you owe me that money.

Fair point. This may be an argument for thinking of it as a net balance with a separate tracker for prepaid funds.

Good question. I originally had it as + Payable Balance OR - Receivable Balance, because the original Prepare might have come from either one (and you don’t want to have to remember which one). If you put it back into the Receivable Balance, it could have come from Payable, and the Receivable won’t be “settled back” so there’s no way to get that money aside from sending ILP packets.

Also good question. The settling back and forth forever problem is a non-issue if the peers communicate about what their limits and thresholds will be beforehand. For example, if my settleTo is -500, we won’t have a problem if you set your settleThreshold > 500. I think it’s better to reduce the amount of communication and coordination the peers need in order to set themselves up properly, and we want to build the system such that misconfigurations still don’t cause problems like the settling back and forth forever.

Just to be clear, Net if Payable > 0 and Receivable > 0 is a separate check from Settle if Payable >= Settle Threshold. So in your first example, settlement would occur if the Settle Threshold is <= 100.

The settlement amount would be Payable Balance - settleTo

Agreed, though I don’t think that has to do with the limit but rather how the “Effect” of the packet is applied

Not currently supported. If the prefund amounts stay small, I’m not sure we need to support refunds. You can always send an ILP packet to another account (or maybe even to the same account, if the connector lets you do that).

If that’s the case, then she wouldn’t have fulfilled the packet. From Alice’s perspective, let’s say the Max Receivable is 300. When Bob sends the first packets through for 200, that brings the Receivable up to 200. When he tries to Prepare another 200 it should fail. (The way the limit is described above, you could argue that it would succeed if the Prefunding caused Alice’s Prepared Balance to go negative. Maybe that check is wrong or Prefunding shouldn’t be tracked on Alice’s side?)

If you don’t want to settle for every fulfilled packet, don’t set the settlementThreshold to 0. If you do, you should know that that’ll be the effect.

I think we should try to make it work such that they don’t need to agree. I admit that it may be difficult or impossible (for example, if your Settle Threshold is higher than the peer’s Max Receivable they’ll start rejecting packets before you initiate settlement).

I get that. I’m trying to understand why you think that :slight_smile:

It seems to me that a lot of what we’re trying to solve would go away if we allow a peer to request that the settleTo and settlementThreshold be set to a specific value.

It would lie with the peer to decide if they accept and the conservative approach would simply be to not accept any of these requests. Nodes that do this will simply be less desirable as peers because it will be hard to have a tightly managed credit relationship with them.

So, from the perspective of a peer lets just express a single net balance and let implementations track this how ever they wish?

With the caveat that we should let a peer request a change to the settlementThreshold and settleTo to allow for efficient pre-paid scenarios.

So, the use case we are trying to solve might work like this:

  1. Alice peers with Bob
  2. Alice does a query and gets back: balance=0, settleThreshold=0, settleTo=0, minBalance=0, maxBalance=Infinity. (i.e. Bob offers no credit to Alice)
  3. Alice wants to prepay her clearing account so she sends a 200 settlement to Bob.
  4. Bob adjusts her balance, settleTo and settleThreshold to 200.
  5. If Bob decides that he doesn’t want to settle every incoming payment to Alice he adjusts her settleThreshold up to a delta above settleTo that makes sense given his cost of settlement.
  6. Alice does a query and gets back: balance=200, settleThreshold=300, settleTo=200, minBalance=0, maxBalance=Infinity.
  7. Alice sends some packets and her balance goes down. But she also receives some payments and her balance goes up to 270.
  8. Alice doesn’t want her credit to Bob to exceed 250 so she requests that he adjust her settleThreshold to 250. Bob agrees and performs a settlement of 70 to Alice to take her balance back to 200.
  9. Alice decides she wants to close her account so she requests that her settleTo and settleThreshold are set to 0. Bob makes these changes (as they are both still above 0) and settles Alice 200.

Slightly improved version of the above:

  1. Alice peers with Bob
  2. Alice does a query and gets back: balance=0, settleThreshold=100, settleTo=0, minBalance=0, maxBalance=Infinity.
    (i.e. Bob offers no credit to Alice and only does settlement when the payable amount exceeds 100)
  3. Alice wants to prepay her clearing account in order to send payments so she sends a 200 settlement to Bob.
  4. Bob adjusts her balance and settleTo to 200. He adjusts her settleThreshold up to a delta above settleTo that makes sense given his cost of settlement (i.e. previously 100 so now 300).
  5. Alice does a query and gets back: balance=200, settleThreshold=300, settleTo=200, minBalance=0, maxBalance=Infinity.
  6. Alice sends some packets and her balance goes down. But she also receives some payments and her balance goes up to 270.
  7. Alice doesn’t want her credit to Bob to exceed 250 so she requests that he adjust her settleThreshold to 250. Bob declines because settlements in increments of less than 100 are not worth it for him. He responds with an error and says that to have a settleThreshold of 250 Alice would need a settleTo of 150. (Or he might accept and automatically adjusts her settleTo to 150).
  8. Alice requests a settleThreshold of 250 and a settleTo of 150.
  9. Bob agrees and performs a settlement of 120 to Alice to take her balance to 150.
  10. Alice decides she wants to close her account so she requests that her settleTo and settleThreshold are set to 0. Bob makes these changes (as they are both still above 0) and settles Alice 200.

Just to clarify what you’re proposing, how would these queries / requests be sent? Is this part of an HTTP API that all nodes MUST implement (independent of the transport they use for ILP packets)? Or would they be sent in ILP packets with a special ILP address that peers MUST support?

@matdehaast and I were just debating that! I think we could use either. HTTP is easier for new implementations but I think ILP packets are better because we already have the channel.

So let’s say:

Alice does a query = Alice sends a packet to peer.settlement.config with an empty payload and gets back balance=200, settleThreshold=300, settleTo=200, minBalance=0, maxBalance=Infinity in the fulfillment

Alice requests that Bob adjust her settleThreshold to 250 = Alice sends a packet to peer.settlement.config a payload of settleThreshold=250

Improvement:

Alice requests that Bob adjust her settleThreshold to 250 = Alice sends a packet to peer.settlement.config a payload of settleThreshold=250 and gets back balance=200, settleThreshold=250, settleTo=150, minBalance=0, maxBalance=Infinity

Another nice thing about this (as @matdehaast points out) is that you could charge for config changes :slight_smile:

To be determined is the encoding of this data. OER?

1 Like

How does Alice’s implementation know when to send these packets?