Skip to content

Instantly share code, notes, and snippets.

@karalabe
Last active September 20, 2023 15:34
Show Gist options
  • Save karalabe/184125637d587a16fe038f99a6daefea to your computer and use it in GitHub Desktop.
Save karalabe/184125637d587a16fe038f99a6daefea to your computer and use it in GitHub Desktop.
Light Server 2.0

With LES essentially murdered by the merge, the current rewrite should prompt some reevaliation of base invariants - and IMO - a full rewrite with the lessons learnt. The ideas below are only that - ideas - but I tried to summarise some things we might want to consider to do better and hopefully reach a deployable light infrastructure.

First up, what are the goals of the light client? IMO we grossly overshot with LES on the goal department. We wanted to basically do everything that's doable with the provable primitives, without taking into consideration any other practical constraints. With a rewrite, we should rethink these:

  • Nobody wants to run a light server because it a places an undue burden on top of full nodes.
    • Current light clients promise too many features, too much data availability. Full nodes by default unindex transactions older than a year because tracking them is just immensely expensive. That is acceptable for a full node, since everyone can configure their own to use whatever limit suits them, but light clients assume the data will be available. Currently we either need to force full nodes to index everything and bear the costs (nobody wants to run them); or we need to make light clients way too smart for their own good as to where to get historical data from.
    • My proposed solution is to force light clients to only ever provide a strict subset of a full node's data. E.g. light servers should only provide access to tx indices at most T time old, where T should be the minimum possible that is still useful. One proposition is a couple weeks another is a very aggressive last 128 blocks. We need to debate what exactly people should use LES for, but definitely not digging up past transaction data.
  • Nobody wants to run a light server because it is too unstable.
    • LES has an insanely complex flow control mechanism. Also it only works in theory, but in practice it's impossible to even debug, let alont put in production. Part of the problem is that LES tries to be too smart for its own good. It attempts to do extremely precise cost measurements for requests and it tries to be both extremely fair across peers as well as max out available light server capacity. These all make things complicated beyond the point of resonable levels of functionality.
    • My proposal is - still - to replace it with a very simplified and well understood flow control mechanism: token buckets. LES is super complicated because so few people run servers, it had to push out every last drop of performance of them to remain functional. Rather than that, we should aim for simple and stable where we can rather have LES served by every geth node. IMHO total capacity of a node should be set low enough that a node operator does not notice that it's even running; and measurements should be something simple (e.g. tokens used == proof items); not some "actual work done because some cache was half warm and we shaved 23.6ns off trie node N". We should use our server count as a feature in serving "dumb" clients vs. trying to be optimal and misserving smart clients.
  • LES wanted to be too much: both a client for sending txs once in a blue moon as well as a stateless full node.
    • The requirements for the two are different. The former needs little data rarely in between. The latter needs a lot of data constantly. Because of convoluting the two, LES always has this strange notion of wanting to be P2P, except it's not, but still complicating everything because it wants to become P2P at some point.
    • My proposal is to restrict light clients to be just that, light clients, not stateless full nodes. We should commit to simply not caring about P2P at all at the LES layer and rather fully commit to a client-server architecture. Taking it a step forward, my proposal is to get rid of devp2p at this layer fully and switch to an HTTP API server. This would remove an immense amount of peer shuffling complexity from LES; and it would also instatly enable a lot of elegant web2 composability when it comes to authentication, proxying, etc. The availaibility and address of the servers can still be announced via the DHT and ENRs and indexed by our DNS discovery.
  • But what about sybil protection and quality of service and whatnot.
    • IMO we're at the wrong level to think about these problems. Our goal should not be to design the perfect protocol that does not work, rather to have one that is resilient against attacks, but instead of "forbidding" bad behavior, it raises the level of friction to do it. There will always be malicious entities who figure out how to work around protocol limits: instead of making everththing brittle to play a game a whack'a'mole, we should make it work well out of the box and make it not perfectly useful to run abusive use cases.
    • My proposal here is to introduce some small friction points that are not too relevant to normal light client usage, but which can be enough to prevent very sophisticated users from relying on it. This is an open ended question, but by say not providing access to the latest block, rather to HEAD-1, -3(?) it all of a sudden is not that relevant for anyone wanting extremely precise timing guarantees. As a normie, seeing a 12s old state should be still ok, but for a power user it might not be. Win! To discourage hammering nodes, we could have a slight delay in responding to requests? As long as the stock client behaves reasonably and a power client cannot abuse things too usefully, we should be golden. As for the couple use cases that might slip though, we'll just foot the bill. As long as everything is simple and robust enough to run on all nodes, we have a lot of capacity to spare.
@web3d3v
Copy link

web3d3v commented May 28, 2023

In for a penny in for a pound

Since my arguments seem fall on deaf ears, let me try to make it one last time via real world example.

Say you want build a wallet that embodies crypto ideals to the maximum extent technically possible. Does not ever collect any user data at all. Allows you to use popular dapps via smart contracts directly, avoiding their frontend (& analytics)

  • Moment you have to run your own servers you have failed.

    • Someone has to pay for them, likely will need setup legal entity. You as a developer are now subject to laws in all the jurisdictions. You can’t just publish open source on GitHub / IPFS and just let anyone run it
    • VPS can be ordered to shut down the server
    • List of ip addresses that interact with your servers can be collected by spying eyees
  • We should build this stuff for most adversarial environment imaginable.

    • US has travel rule, if you receive more than $10k worth of crypto. You have to fill a form that needs to include vast amount of senders private info including social security. If you don’t, you are committing felony! EU came up with cockamamie concept of self hosted wallets ?! Requires collection of personal data from users. Goodbye pseudoanonymity.

I don’t think Joe Lubin wanted to cut off service for Tornado Cash. Nor do I think Hayden Adams wants collect copious amounts of user data on Uniswap front end. They have no choice as they are subjects to regulations in their jurisdictions. Just run a full node makes your dapp / app exponentially less censorship resistant.

There are whole classes of use cases, dapps that can be built if LES is reliable and readily available. It boggles my mind that I can’t seem to get this point across. Abundant LES increases real wold censorship dramatically. Allowing use cases we can’t event think of right now.

Therefore I think goal should be providing as much historical data as possible while only increasing computation requirement to run full node by sensible number (10%~20%).

@web3d3v
Copy link

web3d3v commented May 28, 2023

Third time the charm (best version of the argument)

Having spoken to some researchers and protocol devs. I think I can articulate better version of my argument.

Having hundred or none blocks of historical data vs having three months ideally, hell even a month, is zero to one discontinuity when it comes to building UX for consumer applications.

That’s why I care about this so much, as thats where I spent most of my time. From UX prospective having even month worth of historical blocks means dapp / app no longer needs to rely on RPC provider service.

I have not checked but I don’t think Infura provides services for Iran or North Korea. I am not interested in running servers for those countries in the least. These may be extreme examples but I think it is shortsighted to think that regulation for crypto will not continue to get tougher, making it harder to build products that live up to the ideals.

Reliable, usable LES with some historical data means large number of dapps need not use RPC providers or run servers. It is much easier to go after any one company. But if state read / write & some history is provided by LES it increases practical, real world censorship resistance. For small teams especially. Open source code can just be left on github or ipfs be run by anyone out of the box.

Final point. Why not have at least a month, ideally three, six if you are feeling generous :-D. If impact on running full node is negligible ? And could unlock use cases we can’t even think of today!

(Apologies for spamming here, I just wanted to make sure I articulate most persuasive version of the argument I can think of)

@yorickdowne
Copy link

@web3d3v Your "a month" is covered in this proposal, quote "My proposed solution is to force light clients to only ever provide a strict subset of a full node's data. E.g. light servers should only provide access to tx indices at most T time old, where T should be the minimum possible that is still useful. One proposition is a couple weeks another is a very aggressive last 128 blocks. We need to debate what exactly people should use LES for, but definitely not digging up past transaction data."

From here, give concrete examples of use cases that use 1 week old data, 2 weeks old data, 1 month old data, in a user-facing dApp. You spend most of your time there; many of us don't. So educate people on what these use cases are. Something like a swap or bridge clearly doesn't care, but there are other use cases no doubt. What kind of dApp does care, and in which way precisely?

@web3d3v
Copy link

web3d3v commented Jun 7, 2023

@yorickdowne @karalabe

Example use cases:

  • Mobile or browser wallet transaction history retrieval. Ideally 6 months. But even a month would do. To show recent transactions. User could be presented with button for earlier transaction history (Navigate Etherscan, use centralized server API etc). This would enable wallets without any reliance on RPC endpoints provider, or servers of any kind aside from to LES nodes (a platonic ideal in my humble opinion)

  • Decentralized NFT platform showing last few times NFT was bought or sold. Again there can be UI/UX for redirecting to etherscan for older transactions

  • Dex showing X months of swaps for given address, pool creations etc

  • On chains games may need some transaction history

There will no doubt be use-cases we can't imagine today. Greater the historical data availability, more dapps will be able to get away with not using RPC endpoints providers.

If it is just a week worth of blocks. Most dapps / apps won't bother and stick to centralized RPC provider. If it is month(s), it would be worth for most wallets and dapps to leverage LES. Accessing the network in actually censorship resistant way.

@shazow
Copy link

shazow commented Aug 9, 2023

Hi friends, just a quick note from the perspective of Vipnode if we're giving LES another shot: If it's not a lot of work, it could be valuable to include a node origin signature on LES responses (maybe by the enode key? or something else) so that incorrect responses can be traced back and properly proven/attributed.

More specifically, if we're designing some kind of higher-level incentive system for serving LES, my desired approach was to have LES-servers to have a bond that can be slashed if they misbehave.

Also this would help with MITM scenarios ("dummy" proxy LES servers that just mooch off other LES servers).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment