Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do we address small ledgers/currencies? #132

Closed
emschwartz opened this issue Dec 14, 2016 · 21 comments
Closed

How do we address small ledgers/currencies? #132

emschwartz opened this issue Dec 14, 2016 · 21 comments
Assignees

Comments

@emschwartz
Copy link
Member

Given our hierarchical address format and the assumption that the "Tier 1" connectors will need to limit the sizes of their routing tables, how are we going to address small ledgers or currencies?

If the small ledger uses the same currency as a larger one, this might be covered by the "subledger" concept (plus maybe some amount of source routing tags if there are fees collected in between the larger ledger and the small one).

What I don't see is how you make local currencies or ledgers discoverable using the current approach. If the Tier 1 connectors don't store routes to these smaller ledgers, it seems like that group could intentionally or unintentionally exclude smaller players.

This makes me wonder whether we should take some inspiration from IPFS' multiaddr concept.

@justmoon
Copy link
Member

I used to think that the issue of custom currencies would be addressed by TRTs (#77).

One change I'd make to TRTs right now is to take out the curve. It's simpler and probably totally fine in practice just to recurse quoting all the way to the last connector.


That said, due to quote recursion, there is an even simpler way to accommodate custom currencies which doesn't even require us to add any extra features (like TRTs).

Key idea: The number of tier 1 systems doesn't necessarily have to be limited.

In the IP world, it's limited more because of the size of IP address space than because of the size of routing tables. Prefixes pretty much allow you to have an arbitrary number of tier 1s as long as they share some prefix.

Right now, we use ledger prefixes like us.usd.nexus.. But suppose we add one more layer of indirection, so my (USD) ledger prefix is actually us.usd.nexus.main.. Next, I tell my peers to route anything with prefix us.usd.nexus.* to me. Then I can turn around and peer with people who want to create custom currencies. I'll assign them prefixes starting with us.usd.nexus., e.g. us.usd.nexus.bobcustom. Nobody's routing table (but mine) would have to grow, but those custom currencies would now be tier 1.

In this scenario, I wouldn't face a trust issue because I can set up my peering relationship with us.usd.nexus.bobcustom. such that I only accept routes for their ledger prefix (and below) from them.

This does lead to a bit more rigid routing structure, but I think that's fine. We can come up with more and more efficient routing in the future, securely detect shortcuts, etc. But for an MVP, we can live without that.


This makes me wonder whether we should take some inspiration from IPFS' multiaddr concept.

I don't see the rationale for adding a layer of indirection - ILP addresses are already schema-less, so if you wanted to come up with some class of address that has special meaning, just choose a prefix, e.g. bitcoin. Whether everyone understands your special prefix is another matter, but there is no reason you'd need bitcoin: over bitcoin..

(You can make an argument for saying that ILP addresses should just be URIs so that the identifiers inside and outside ILP are the same. But imo there is a very strong counter argument in that URIs aren't designed to be "liquidity-local" identifiers, i.e. ledgers with common liquidity wouldn't have much of a tendency to have common prefixes. So it wouldn't work nearly as well as a purpose-built address space.)


Some assumptions I'm making:

  • We don't know if custom currencies will be a common thing, but I'm happy to assume they will be and to try to accommodate them because it seems as though we can do so without adding significant complexity to the protocol.

  • Custom currencies are either going to be well-known (and be tier 1) or they're not going to be super-liquid. Long-distance payments will tend to go through common currencies, not custom ones. If a custom currency becomes very popular, it would certainly also become tier 1 before long.

@emschwartz
Copy link
Member Author

emschwartz commented Jan 4, 2017

I think that the separation between the "routing prefix" and the "ledger address" that you propose addresses my concern about being able to route to lesser-known ledgers.

Am I right in thinking that the idea behind separating the technical specification of the address / protocol from the recommended connector behavior and address selection methods is to provide flexibility to change the connector behavior and address selection later?

That might be a good idea but I will say that it makes understanding this standard more complicated. It also means that you can't assume that much about the layout of ledgers and accounts from looking at an address, because different parts are mixed together.

Also, if all connectors end up being implemented with whatever behavior we say is the "norm" at the start, will there really be that much flexibility to change it later?


Just to make sure we are on the same page, this is my understanding of the current addressing scheme:

Technical Specification:
The address must be a string matching the regex ^[a-zA-Z0-9._~-]+$. ILP makes no stipulations about how the addresses may be structured, so you cannot necessarily infer anything about the setup of ledgers and accounts from looking at an address. Dots have no special meaning as far as "ILP" is concerned.

Recommended Connector Behavior (Initially)
For the purposes of this explanation, let's say the connector in question is on the ledgers a.b.m. and a.b.x., and its accounts are a.b.m.n and a.b.x.y, respectively.

Connectors should keep routing tables that store: 1) ILP address prefixes (e.g. a.b.c.), 2) the next connector account (e.g. a.b.x.z), and 3) a liquidity curve, if it is known.

To handle a quote request (e.g. that comes in on ledger a.b.m. and is destined for a.b.c.d.e) the connector should:

  1. Check its routing table to find the longest prefix that matches the quote's address (e.g. a.b.c.).
  2. If the routing table entry has a liquidity curve, the connector can respond immediately to the quote request. The connector calculates the amount by combining its rate (to the ledger a.b.x) with the curve it got from the next connector (a.b.x.z).
  3. If the routing table entry does not have a liquidity curve but only a next connector account (e.g. a.b.x.z), the connector should send a quote request to the next connector.
  4. If there is no routing table entry, the connector should check whether one of the ledgers it has an account on has an address that appears in the quote address (e.g. a.b.c.d.). If so, the connector can respond immediately to the quote request using its rate from the quote's source ledger to that ledger (e.g. the rate to deliver to a.b.c.d.).
  5. If none of the above, respond with an error. (Would it make any sense to ask other connectors in the hopes that they might know better?)

To handle a payment (e.g. sending 10 units to a.b.c.d.e), the connector should:

  1. Check its routing table to find the longest prefix that matches the quote's address (e.g. a.b.c).
  2. If the routing table has an entry for a matching prefix, the connector should take the next connector address from the routing table entry and prepare a transfer to it. The connector uses its rate from the payment's source ledger to the ledger of the next connector to determine the amount of the transfer they will prepare.
  3. If there is no routing table entry, the connector should check whether one of the ledgers it has an account on has a prefix that appears in the quote address (e.g. a.b.c.d.). If so, the connector looks at the destinationAmount specified in the ILP packet and prepares a transfer to deliver that exact amount. The ledger-specific code (plugins) will need to handle translating the ILP address (a.b.c.d.e or a.b.c.d.e.f...z) into an account on the local ledger. Note this means that ledger plugins will specify a separator so that they know to deliver to the right local account (e.g. e) even if the address does not end with the identifier for the local account.
  4. If none of the above, reject the incoming transfer with an error.

Recommended Address Selection Method (Initally)

1-4 apply to ledger addresses. 5-7 apply to accounts and subledgers.

  1. An address should start with a prefix corresponding to a well-known grouping of connectors. I like @sharafian's term "neighborhood" for this. This could be something like us.usd, bitcoin, or ilpearlyadopters.
  2. An address may have any number of sub-neighborhoods in the first part of the prefix. For example, us.usd.banks.creditunions..
  3. Neighborhood prefixes should not contain the address of an actual ledger. If they do, connectors on that ledger may get confused and mistakenly think the address points to an account on that ledger rather than a nearby ledger.
  4. An address should contain a ledger identifier that is well-known and unique in the chosen neighborhood. For example, us.usd.banks.creditunions.sffirecu.. The neighborhood (or sub-neighborhood) is appropriately chosen if it is reasonable to expect that all connectors that identify themselves as part of that group will add the routes to the ledger in question to their routing tables. If they do not, a different sub-neighborhood should be chosen.
  5. To use a ledger as a routing landmark for others, the ledger should have a separate "routing prefix" from its "ledger address". In this example, the SF Fire Credit Union should set its routing prefix to us.usd.banks.creditunions.sffirecu. and its ledger address to us.usd.banks.creditunions.sffirecu.main.. Its connector would broadcast to other connectors the a) the fact that it can route to us.usd.banks.creditunions.sffirecu. (without a liquidity curve, because that is not an actual ledger) and b) the liquidity curve to us.usd.banks.creditunions.sffirecu.main..
  6. An address should contain an account identifier that the ledger plugin of a connector on that ledger can use to identify the local account they should send to: us.usd.banks.creditunions.sffirecu.main.12345
  7. To support the concept of "subledgering", a ledger plugin must specify a separator it will use to separate the account identifier from the subledger information. This should be standardized on the level of individual ledgers. Using dots (.) is recommended but not required.
  8. Any number of subledgers or subaccounts may be included after the account/subledger separator: us.usd.banks.creditunions.sffirecu.main.12345.personal.car.054c57e4-deb5-4cce-9ded-68cd5fd831a2.

For the record, here are some of my key ideas on this topic:

  • There are multiple reasons why a "root ledger" for a currency would be relatively unknown. The currency could be newly created. It could be relevant only amongst some community or area. Or maybe it is a competitive asset that the global oligarchy of connectors and ledgers collaborate to try to exclude. Lack of space in the routing table is not the only reason to remove or ignore new entries.
  • Connectors between root ledgers (e.g. Bitcoin) and smaller ledgers that use the same currency (e.g. a cryptocurrency exchange) may want to set an exchange rate between the larger ledger and the smaller ledger. The exchange's ledger would not fit the current definition of a "subledger" because the rate would not be 1-to-1. This is not an uncommon behavior. The same would apply to banks. Furthermore, if a ledger is denominated in the same asset as a bigger one but the smaller one is much less trustworthy, connectors would definitely want to set their own rates between the two.
  • Well-known ledgers are good landmarks to use in determining your address. It would make sense to be able to call a ledger crypto.bitcoin.altcoin even if the altcoin is its own asset. If you could, that ledger would only need to be concerned about setting its address properly, rather than trying to make sure it appears in the routing tables of all the connectors in the crypto "neighborhood".
  • It is better to make stipulations about how addresses should be interpreted than assumptions about what routes and ledgers connectors will choose to put in their routing tables. I find the "Tier 1-3" terminology problematic because I think it conflates asset issuance with being well-known, and it makes assumptions about the contents of connectors' routing tables.

@sharafian
Copy link

sharafian commented Jan 4, 2017

A few questions/comments:

  1. In the steps you outline for quoting and payments, you say that a connector should check if any of the ledger prefixes of the connector's accounts match the destination after failing to find the destination in the connector's routing table. As it works now, the connector puts the ledgers that it has accounts on into the routing table (accompanied by liquidity curves), and treats those "delivery" routes as ordinary routing table entries.

If none of the above, respond with an error. (Would it make any sense to ask other connectors in the hopes that they might know better?)

  1. You can accomplish the above step by adding a default route (an entry in the routing table with a prefix of ''.

  2. Having the dot separator be "official but unofficial" just leads to potential exploits. For example, let's say us.usd.cornelius.main.'s separator for subaccounts is _. Some program might try to generate payments to us.usd.cornelius.main.alice.abc, which would actually look for the account alice.abc instead of alice. In the worst case, if optimistic payments are being sent, an attacker could squat on that account and receive payments instead of alice. If we had one standard separator, these issues would not be as likely to appear.

  3. If the sub-account separator is not a ., that also means anything which programmatically generates sub-accounts (like the ILP receiver) needs to look it up or ask for it as configuration. It seems strange to request ledger metadata in order to parse an ILP address.

  4. Should we have a recommended value for the segment between ledger prefix and routing prefix (e.g. main., in the case of us.usd.nexus.main.)?

  5. Is there a standard way to convert between ledger prefix and routing prefix? Can there be multiple segments between the ledger prefix and the routing prefix? e.g. bitcoin.main.accounts. instead of bitcoin.main, where bitcoin. is the routing prefix. Do you need the main part to be separated at all, or can you have bitcoin. as the routing prefix and bitcoinledger. as the ledger prefix?

  6. Should a subledger have a distinct routing prefix and ledger prefix? e.g. Should I create us.usd.nexus.main.sharafian.main.subaccount, or just use us.usd.nexus.main.sharafian.subaccount?

(An additional note: We should really have some terminology for the "anatomy" of an ILP address, e.g. the routing prefix, the ledger prefix, the part between those two, and the sub-account stuff afterwards, the portion of the address where delivery occurs, etc.)

@emschwartz
Copy link
Member Author

emschwartz commented Jan 4, 2017

I really like the recommendation of putting everything in the routing table 👍 (1+2)

  1. Having the dot separator be "official but unofficial" just leads to potential exploits.

I think trying to figure out someone else's address without asking them is always a bad idea. Even for non-interactive protocols you should probably have some communication (or out of band address discovery) before you start shooting payments off into the blue.

  1. Should we have a recommended value for the segment between ledger prefix and routing prefix (e.g. main., in the case of us.usd.nexus.main.)?

I don't see the purpose in this. Does anyone aside from the person setting up the ledger/address care about what that's called?

  1. Can there be multiple segments between the ledger prefix and the routing prefix?

I don't see why not. You could set it up however you want.

Do you need the main part to be separated at all, or can you have bitcoin. as the routing prefix and bitcoinledger. as the ledger prefix?

This would mean that those advertising that they are connectors to bitcoin. would not appear to be suitable routes to bitcoinledger.. That doesn't seem like a good outcome.

  1. Should a subledger have a distinct routing prefix and ledger prefix?

If routes are short-lived and addresses are thought of as temporary, you could wait until you really need this structure before setting it up. You could always probably add segments to your address later.

We should really have some terminology for the "anatomy" of an ILP address

How about:

  • ILP Address: neighborhood.subneighborhoods.ledgergroup.ledger.account.subledger.subsubledger
  • Ledger Prefix: neighborhood.subneighborhoods.ledgergroup.ledger.
  • Routing Prefix: neighborhood.subneighborhoods.ledgergroup.
  • Neighborhood Prefix: neighborhood.subneighborhoods.

Note that all prefixes should end with .'s (by convention, not technical rule)

@sharafian
Copy link

For 3, I'm referring to the receiver not knowing their own address. If the receiver is running some software that takes the receiver's ILP address and appends subledger info (like the ILP receiver's payment identifier), the receiver's own software would have to look up the sub-account separator from the receiver's ledger metadata (that's a new field we'd need in there). If almost all ledgers used . as the sub-account separator, then many implementations may not correctly look up the actual sub-account separator. In the few edge cases where the sub-account separator isn't _, it would cause serious issues.

@emschwartz
Copy link
Member Author

Note that the sub-account separator would be decided by the ledger plugin so that could just be a constant exported by the plugin. That said, I wouldn't mind making the . "convention" a bit stronger than a "convention"

@sharafian
Copy link

Agreed. I think that even if it's a constant, it's a little strange, and mixing separators in an ILP address doesn't seem to have any benefit.

@justmoon
Copy link
Member

Also, if all connectors end up being implemented with whatever behavior we say is the "norm" at the start, will there really be that much flexibility to change it later?

Yes, certainly - the routing protocols used on the internet went through several iteration and continue to evolve today.

There are some simple things where we can (and must) make decisions that will be difficult to change. For instance, the way that routing tables and quoting work. Even the smallest connector will have to have a routing table (think of your router at home which pretty much just contains a local route for your local network and a default route using your ISP as a gateway - but that's still a little routing table) and will have to quote. In other words, those functions will be everywhere and very sticky over time. Fortunately, they are also pretty simple. Our current implementation is already more or less correct, which some minor tweaks and syntactic improvements.

However, how those routing tables get populated can get very, very complex. @momerath42 and I have more or less abandoned least-cost routing in favor of a mixed cost metric biased towards shorter routes instead of cheaper routes. Cheap, but long routes are hard to trust and converge slowly. HLP (a BGP successor proposed in a 2005 paper) actually sets a hard limit (4) on the maximum number of peer-to-peer routing hops for this very reason. Notably, they looked at real Internet routes and found that the number of peering hops is at most 2 for 99% of routes and <= 1 for 90% of routes. (A peering link would be any tier-1 to tier-1 connection, not counting any hops to get to tier-1.)

On the Internet, routing protocols are still rapidly evolving and policies and practices are changing constantly. Our work on ILP interdomain routing so far is suggesting that it will be an ongoing effort for us as well.

Having the dot separator be "official but unofficial" just leads to potential exploits. For example, let's say us.usd.cornelius.main.'s separator for subaccounts is _. Some program might try to generate payments to us.usd.cornelius.main.alice.abc, which would actually look for the account alice.abc instead of alice. In the worst case, if optimistic payments are being sent, an attacker could squat on that account and receive payments instead of alice. If we had one standard separator, these issues would not be as likely to appear.

Totally agree - I wasn't seriously suggesting that people should use different separators. Obviously, we should pick a separator and stick with it.

I use the separator example when I'm explaining prefix routing, because in that context it's important to understand that the separator doesn't matter. You could have any separator or none at all, prefix routing tables still work. But this illustrative example took on somewhat of a life of its own. :)

That might be a good idea but I will say that it makes understanding this standard more complicated.

That's because you're looking at it from your perspective instead of the users'. You're trying to understand the whole thing, so it seems easier to explain it all in one go.

But in practice, the vast majority of ILP users will understand (and care about) only a tiny fraction of how ILP works. In particular, most won't know or care about how ILP addresses are chosen or how inter-domain routing works.

How much did you know or care about BGP before you started working on ILP?

Sure, to really understand all of ILP, I need to learn everything, but when writing our most fundamental standards documents, we should think about how we can abstract away advanced topics that the average user doesn't need to know - like how ILP addresses are assigned and how routing tables are populated. That should be in an RFC somewhere, but it shouldn't be in the ILP RFC any more than the IP Allocation Guidelines (RFC 1466) should have been part of the Internet Protocol (RFC 791)

The other issue is that many of these advanced topics won't have a single answer across the whole system. Different protocols may be in use in different places and certainly different procedures. So we should think about which topics that applies to and exclude those topics from the more general specs.

Should we have a recommended value for the segment between ledger prefix and routing prefix (e.g. main., in the case of us.usd.nexus.main.)?

Agreed, unless...

...maybe we can still get rid of the need for that segment.

<crazy-theory-time>

Suppose my ledger is us.nexus and I'm homing your ledger at us.nexus.bencoin.

What if we add a ignore_curve_for_quoting flag to routes where I can specify whether the cost curve from my route advertisement should be used for quoting or not. If I set this flag to true, then people will still evaluate and compare routes to us.nexus. using the cost curves to that destination, which is fine. But when somebody actually tries to send to us.nexus.bencoin.whoop, they'll look at their routing table, see that ignore_curve_for_quoting=true and send quote requests that will eventually reach my connector. My connector is connected to yours using the routing protocol (although I have set a policy that only allows you to advertise routes starting with us.nexus.bencoin.. That means that I have us.nexus.bencoin. in my table, will forward the quote request to you and you'll answer it.

This does require that the last connector before reaching us.nexus. is my main connector, but note that this is the case both in IP, where generally peering happens between two routers, and ILP Kit, where peering happens using a trustline.

The only case where this breaks is if this payment is coming in from another connector on us.nexus.. This problem is related to the fact that a ledger is essentially a set of trustlines with a dumb connector in the middle. If, instead of using a dumb connector, we used the actual us.nexus. connector, then this would work. This is kind of a subtle change, but with huge implications. Essentially we'd be getting rid of the concept of a ledger and just have connectors and trustlines. It would also mean that us.nexus. isn't really referring to the ledger, but actually to the connector hidden at the center of it. Which in turn means that prefixes refer to connectors. Which in turn means that we might not need peer.xyx. addresses anymore. Also, "Interledger" would become somewhat of a misnomer. :)

Initially, this idea seemed a very theoretical exercise. But it's actually making more and more sense... Getting rid of peer addresses and main segments seem like real benefits.

</crazy-theory-time>

ILP Address: neighborhood.subneighborhoods.ledgergroup.ledger.account.subledger.subsubledger

Here's my suggestion:

  • neighborhood [0..n] - Any segments used for grouping ledgers together.
  • ledger [1] - Name of a specific ledger.
  • subledger [0..n] - Names of subledgers.
  • accountgroup [0..n] - Any segments used to group accounts on the ledger.
  • account [1] - Name of a specific account.
  • interaction [0..n] - Any segments used to identify a specific interaction, e.g. IPR UUID.

So, the minimal address would be acme.bob. And a complex example would be us.fed.ach.0.acmebank.swx0a0.acmecorp.sales.199.cdfa5e16-e759-4ba3-88f6-8b9dc83c1868.2, which might break down as:

  • Neighborhoods: us, fed, ach, 0, acmebank
  • Ledger: swx0a0
  • Subledger: acmecorp
  • Account group: sales
  • Account: 199
  • Interaction: cdfa5e16-e759-4ba3-88f6-8b9dc83c1868, 2

@emschwartz
Copy link
Member Author

emschwartz commented Jan 13, 2017

👍 about separating the technical addressing standard from the convention, and about having the convention specify the period as the separator.

That's because you're looking at it from your perspective instead of the users'

The perspective I'm trying to adopt is that of the developer who wants to wrap their head around what ILP is to determine whether they think it is a good idea and something they want to support or work on. I know that most users won't understand all the details, but I'd like to limit the number of places we give hand-wavey "it's complicated but you don't need to understand the details" explanations.

Also, "Interledger" would become somewhat of a misnomer. :)

"Do not try and understand the Interledger. That's impossible. Instead... only try to realize the truth."
"What truth?"
"There is no ledger."
"There is no ledger?"
"Then you'll see, that it is not ledgers that are connected, it is only your trust with others."

What if we add a ignore_curve_for_quoting flag to routes where I can specify whether the cost curve from my route advertisement should be used for quoting or not.

This might work for quotes, but how would you handle the actual payments? The delivery feature would mean you would try to deliver the final amount if your ledger prefix matches.

subledger [0..n] - Names of subledgers.
accountgroup [0..n] - Any segments used to group accounts on the ledger.

Isn't a subledger the same as an account group?

Interaction: cdfa5e16-e759-4ba3-88f6-8b9dc83c1868, 2

There's an argument to be made that these should go into protocol-specific headers rather than into the ILP address. In some protocols you might want to encrypt those details, and they only matter to the end applications anyway.

@emschwartz
Copy link
Member Author

The address convention could also include a version at the beginning. This would even be backwards compatible if the connectors that had updated were connected to one another, because the version would be part of the prefix and even connectors using the older scheme would properly forward packets to the updated ones.

@justmoon
Copy link
Member

There's an argument to be made that these should go into protocol-specific headers rather than into the ILP address.

My argument against that is that the address should specify the ultimate destination and the transaction ID is a part of that. In TCP/IP ports are separate, but that distinction is really coming apart at the seams:

  • IP and port are often represented together, e.g. 127.0.0.1:80
  • DNS could benefit from being able to specify ports - so that you could run many HTTPS servers on one host for instance
  • NAT uses ports as extra IP addresses

Having them handled separately does make one thing easier: If you have somebody's HTTP server and you want their FTP server, you can just change out the port. However, that is actually an anti-pattern: What if my FTP server is actually running on a different host? Rather than trying to make guesses at the low level, you should use a higher level mapping service like DNS to discover the true host and port values.

Isn't a subledger the same as an account group?

A subledger is a different physical system, e.g. a separate database on a separate hard drive. An account group is just a logical grouping of accounts within one physical ledger.

At least that's what I'm proposing it could be.

This might work for quotes, but how would you handle the actual payments? The delivery feature would mean you would try to deliver the final amount if your ledger prefix matches.

No, you'd only deliver the final amount if the route was local. This route wouldn't be local, you would have received it from another connector.

As a reminder: To determine how much money to forward, connectors could just use their internal rate. If they want to optimize their revenue and/or success rate beyond that, they can use cached quoting information, request a new quote or use other metrics to estimate whether they can get away with a bigger cut.

The address convention could also include a version at the beginning.

Good idea!

Rather than having one global version I'd suggest that we just define the first thing in the address to be the address allocation scheme used, e.g. peer, crypto. Then you have an implicit ability to version per allocation scheme, e.g. peer2

So, updating my example from earlier:

ILP Address: allocationscheme.neighborhood.subneighborhoods.ledgergroup.ledger.account.subledger.subsubledger

Here's my suggestion:

  • allocationscheme [1] - Address allocation scheme; always g for general allocation scheme
  • neighborhood [0..n] - Any segments used for grouping ledgers together.
  • ledger [1] - Name of a specific ledger.
  • subledger [0..n] - Names of subledgers.
  • accountgroup [0..n] - Any segments used to group accounts on the ledger.
  • account [1] - Name of a specific account.
  • interaction [0..n] - Any segments used to identify a specific interaction, e.g. IPR UUID.

So, the minimal address would be g.acme.bob. And a complex example would be g.us.fed.ach.0.acmebank.swx0a0.acmecorp.sales.199.cdfa5e16-e759-4ba3-88f6-8b9dc83c1868.2, which might break down as:

  • Allocation scheme: g
  • Neighborhoods: us, fed, ach, 0, acmebank
  • Ledger: swx0a0
  • Subledger: acmecorp
  • Account group: sales
  • Account: 199
  • Interaction: cdfa5e16-e759-4ba3-88f6-8b9dc83c1868, 2

@emschwartz
Copy link
Member Author

My argument against that is that the address should specify the ultimate destination and the transaction ID is a part of that. In TCP/IP ports are separate, but that distinction is really coming apart at the seams

Good points, 👍

A subledger is a different physical system, e.g. a separate database on a separate hard drive. An account group is just a logical grouping of accounts within one physical ledger.

I don't think the address scheme necessarily says anything about whether components are running on one system or multiple. You could one machine running multiple logical ILP ledgers with different currencies or multiple machines hosting subledgers. I think what differentiates a subledger is that it breaks out the balance of a single account into some groups, all denoted in the same currency.

I don't think we should distinguish between subledgers and account groups, because a ledger is just a group of accounts. We do need to distinguish between a ledger and a subledger, because this tells you something about the asset type.

Rather than having one global version I'd suggest that we just define the first thing in the address to be the address allocation scheme used

👍

No, you'd only deliver the final amount if the route was local. This route wouldn't be local, you would have received it from another connector.

I think that makes sense, but I don't think I'll feel completely confident I'm on the same page until we agree on a full, step-by-step write-up like what I started above.

allocationscheme.neighborhood.subneighborhoods.ledgergroup.ledger.account.subledger.subsubledger

Does the subledger follow the account or is the account referencing an account on the subsubledger? Your suggestion seems to switch between the two. Is it ...ledger.account.subledger..., ...ledger.subledger.subsubledger.account... or ...ledger.subledger.subsubledger.account.subledger.subsubledger...?

@michielbdejong
Copy link
Contributor

I haven't read the whole discussion yet, but to answer the initial problem statement:

What I don't see is how you make local currencies or ledgers discoverable using the current approach. If the Tier 1 connectors don't store routes to these smaller ledgers, it seems like that group could intentionally or unintentionally exclude smaller players.

A connector could specialize in routing to small ledgers/currencies. Other connectors could have it as a low-priority catch-all for the empty prefix.

This "connector for the unroutables" could advertise with "Having trouble being discovered? Announce yourself through us!" And once they become famous for having a huge routing table and delivering even to the most remote ledger, more and more other connectors could use it as a last resort when all other (cheaper/faster) routes fail.

@justmoon
Copy link
Member

justmoon commented Feb 8, 2017

Responding to @sharafian's example: us.nexus.main.sharafian.main.subaccount

That strikes me as pretty ugly and the whole main thing is a bit of a hack. I've been thinking about it a bit more and I think we can do better with the following two features:

Connectors should accept route advertisements from us.nexus.bob if all advertised routes start with us.nexus.bob. even if us.nexus.bob is not a trusted peer.

Ledger should allow broadcasting a message (such as a route broadcast) to all users on the ledger who are listening to such global broadcasts.

Both features carry DoS potential which could be mitigated using micropayments.

What this does is make it very easy to create subledgers with other currencies. Say I'm us.nexus.bob and I want to create Bobcoin. All I need to do is run a connector and have it start broadcasting routes for us.nexus.bob. and all neighboring connectors will add me to their routing tables and start requesting quotes instead of just delivering into my account.

This is safe, because you still can't send bogus routes like a full-on trusted peer can. Route broadcasts are local messages and ledger messages are authenticated, so when someone sees that us.nexus.bob is sending a route for us.nexus.bob., they know it's legitimate and when they see that us.nexus.evilevelyn is sending a route for us.nexus.bob., they know it's bogus.

Note that the broadcast feature would be ledger-local. Some ledgers may not (be able to) support it and that's fine. They can still use the main hack or just not support subledgers with custom currencies.

And we wouldn't need addresses where every other segment is main... 🔁

@sharafian
Copy link

@justmoon I think that only applies to the subledger case, but not the 'addressing a small ledger in terms of a larger ledger' use case, which I think is going to be just as important.

@sharafian sharafian reopened this Feb 8, 2017
@sharafian
Copy link

whoops

@justmoon
Copy link
Member

justmoon commented Feb 9, 2017

@sharafian

@justmoon I think that only applies to the subledger case, but not the 'addressing a small ledger in terms of a larger ledger' use case, which I think is going to be just as important.

I'm not talking about subledgers - I'm talking about ledgers with different currencies.

@sharafian
Copy link

Sorry, by subledger I meant a ledger that's addressed in terms of an account

@mDuo13
Copy link
Collaborator

mDuo13 commented Feb 11, 2017

I'm still struggling to understand this. Does this make sense?

Suppose g.us.acme. is the address of ACME Ledger, and Red Connector has an account on ACME Ledger so it's in Red's routing table as a local route. Red Connector's ledger plugin can conclude that g.us.acme.blue is the account blue on ACME Ledger.

The owner of blue on ACME Ledger can message Red Connector and say, "Hey, I'm a connector too, check these routes out." The routes it passes along can use addresses like g.us.acme.blue.waygate.zerp. with the address of its connector (g.us.acme.blue.) as the forwarding address, where Waygate is another ledger that Blue Connector is connected to. Then Red Connector can decide to honor these, so instead of preparing transfers directly to the blue account on the ACME ledger, it'll forward them through the Blue Connector.

Let's assume that Waygate is an exchange that happens to deal in a rare coin called Zerp, among other currencies; g.us.acme.blue.waygate.zerp. refers to the Zerp ledger at Waygate. It would not be surprising if Waygate had other addresses, too; the exact same ledger might be addressed by g.crypto.waygate.zerp. also.

If this is in fact the scenario from #132, there are a couple clarifications that I think are in order:

  1. When would someone use the former address instead of the latter? Like, supposing Bob is a user of Waygate's Zerp ledger, he could report his address as g.us.acme.blue.waygate.zerp.bob instead of g.crypto.waygate.zerp.bob, but why would he?

    I think the first answer to this question is that Bob wouldn't make that decision, but Waygate would. Maybe Waygate isn't popular or well-known enough to be listed in most routing tables in the g.crypto. space, so it picks another address that's relative to a better-known ledger like ACME.

    A problem with doing this is that Waygate has to trust Blue Connector; if Blue Connector fails to direct the routes correctly, all payments to Waygate customers through the blue address would end up failing. I think this makes sense in the case where Blue Connector is owned and operated by Waygate, but not in many other scenarios.

    I'm also wondering what happens if Waygate grows in size and prestige so that more people would be willing to list it in their routing tables under g.crypto. now. It seems like there could be an in-between stage where some people have g.crypto.waygate. in their top-level routing table but others don't. In that case, it's hard for Waygate to decide which address to use.

    Another possible answer is that Bob reports both addresses or more. The IPR format only has one address, but I could totally envision a similar high-level protocol that allows you to report multiple ILP addresses where you'd accept payment. This would make sense for multiple reasons, the most relevant to the current discussion being that Receivers could advertise multiple destination addresses so that senders could pick whichever one has the cheapest/easiest route from where they're starting.

  2. In the case of g.us.acme.blue.waygate.zerp. addresses, does that guarantee that any payments to Waygate customers go through Blue Connector unless they're originating from the Waygate ledger? If so, is that a problem?

  3. Imagine that ACME's ledger allows special notifications or other behavior triggered by the "interactions" section of the address, so something like this could be a valid address used for the account blue on ACME Ledger: g.us.acme.blue.invoice.d496b1e8-88bb-436a-8803-26a8b340109f. It seems like this could lead to situations that are legitimately ambiguous, if the "interactions" portion happened to overlap with the same prefix used by Blue Connector for routing to Waygate. Is there a way to avoid this?

@emschwartz
Copy link
Member Author

he could report his address as g.us.acme.blue.waygate.zerp.bob instead of g.crypto.waygate.zerp.bob, but why would he?

Technically the receiver (or the server acting on their behalf) is the one that decides what address to advertise. They can get the address from their ledger plugin, which can get it from the ledger, have it hardcoded (e.g. in the case of Bitcoin), or something else. You would want to broadcast whatever address is most easily discovered by others.

if Blue Connector fails to direct the routes correctly, all payments to Waygate customers through the blue address would end up failing

It would not be a good idea to address your ledger in terms of a connector that won't rebroadcast your routes, unless quote requests always end up being relayed across the whole chain. In that case, as long as the quote request gets to you it would be okay.

I could totally envision a similar high-level protocol that allows you to report multiple ILP addresses where you'd accept payment

This is definitely possible. We just haven't built such a protocol yet. We did decide though that the lowest level protocols should not support multihoming, because that makes them much more complicated. If a higher level protocol wanted to let you express multiple addresses for the same account and let the sender choose which one to use, that would be totally fine.

In the case of g.us.acme.blue.waygate.zerp. addresses, does that guarantee that any payments to Waygate customers go through Blue Connector unless they're originating from the Waygate ledger? If so, is that a problem?

It doesn't guarantee it but it's quite likely. If the smaller connectors are peered with other connectors they could broadcast shortcut routes that go through them, which their peers could choose to honor. If you address yourself in terms of a larger ledger though, I think you're probably going to assume that most payments will be routed through that path and you're okay with that.

It seems like this could lead to situations that are legitimately ambiguous, if the "interactions" portion happened to overlap with the same prefix used by Blue Connector for routing to Waygate.

Right now the ILP client includes a Receiver ID in the address that has the Transport Protocol it's using and a random unlikely to collide with other receivers (e.g. ilpdemo.blue.bob.~ipr.ZfiUdFj-tVw.22e315dc-3f99-4f89-9914-1987ceaa906d). This would also make it highly unlikely that it would collide with another account.

@emschwartz
Copy link
Member Author

Addressed by #154

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

7 participants