ULC is a new option in LES that doesn't break compatibility with the LES protocol, but does significantly reduce the time and resources required to sync with the main Ethereum chain.
The main idea is about reducing the amount of messages and doing less client side validation.
2^63-1
ExtraData
fieldThe main improvement of ULC is that a client doesn't need to verify the seal of a block and can skip this step at all.
Ethereum light
clients (actually fast
and light
) have slow-but-light PoW verification. Full
clients have fast-but-heavy PoW verification. The main difference is that full
clients generate all the data needed to verify every block in an epoch, but light clients calculate many values on-the-fly (see Verify step
).
The detailed algorithm can be found on the Ethereum wiki.
The verification has 2 steps: init caches and verify. Let's describe them in detail.
All numbers below are given for the Epoch 232 (a current epoch at 12 Nov 2018)
Some parts of this step can be run in parallel.
All numbers and the algorithm steps are from geth code
It runs once per epoch: epochLength = 30000 blocks ~ each 3.5 days = twice per week
It needs to generate a verification matrix of pseudo-random values (called cache
).
Calculate seedHash in epochNumber steps = 232 sha3 operations
Calculate the initial cache in: cacheSize/64 steps = 51641792/64 = 806900 sha3 operations
. CacheSize
can be taken from table cacheSizes
, for epoch=232
it equals 51641792
.
At the end of the day
For example, for epoch 232 (a current epoch at 12 Nov 2018)
This is theoretical lower bound. The Ethash Design Rationale mentions that "a light client should become fully operational and be able to verify blocks within 40 seconds in Javascript".
Light mode seal verification doesn't store the entire dataset for block verification, but generates necessary items on-the-fly. For a single block it runs the hashimotoLight
algorithm which takes:
More details about FNV32-1 hash function can be found here.
This is the difference between ULC and LES clients for each block. Because the CHT is generated once per 32767 blocks, the total difference is
This is the theoretical lower bound. As noted in the Ethash Design Rationale, a single block verification step should take '0.1 seconds in Python'
. In practice it takes ~200ms
in Geth.
So ULC saves 807133*O(sha3)
at init stage, which happens each epoch and [256O(sha3) + 65664O(fnv) ; 8.388.352O(sha3) + 2.151.612.288O(fnv)] for each block while syncing. Because the difficulty of block verification grows linearly, the total difficulty of syncing N blocks grows as
Trusted LES servers are needed only to send announcements (in Geth code it has name announce(block hash, TD, number)
) to LES(ULC) clients. All announcements should be signed. Trusted servers don't know whether they have been chosen as trusted or not by any given client. Such servers can be started with an onlyAnnounce
flag, which ensures that the LES server operates under the rule "only send announcements to my peers, do not process any other requests".
LES servers - usual LES servers, a header chain is synchronised with them. Helps to prevent attacks on trusted servers.
has some CHT root at the start; has a CHTs "chain", that can be synced from LES servers; CHT chain allows to request any historical information (block, transaction, receipt) from LES server
trusts announcements received from N Trusted LES servers. Announcements should be signed by Trusted LES servers. There should be at least M identical announcements to trust.
Asks for announcements with the biggest TD
ULC client starts CHT sync before syncing header chain. ULC client requests newer CHTs from LES servers.
requests headers from untrusted LES server, starting from the highest block is known to latest CHT + 1
up to latest block number known from trusted announce
ULC client validates:
6.1. announcements checking are there M the same announcements from N received from Trusted LES servers
6.2. validates headers, as usual, LES client except VerifySeal. ULC doesn't run VerifySeal
at all.
doesn't validate CHT. If we get incorrect CHT, it'll be clear later after receiving block headers.
Prevented because it is already prevented in a classic LES model and we only download headers with trusted announcements.
Even less possible than in LES model because it's needed to attack at least M servers.
Possible. ULC makes it much less possible by hiding what nodes are trusted for each user. A user doesn't send any unusual for LES information to LES servers trusted or untrusted. Any trusted for a user LES server doesn't know that it has been chosen by the user to be trusted LES server.
Prevented because all announcements must be signed by according LES server.
There're 2 kinds of security guarantees:
The very mechanism of blockchain synchronisation of the ULC is the same as that of the LES. Therefore, comparing the security guarantees of ULC with full, fast and LES does not make sense. It is more important to compare the guarantees of a private RPC server or Infura with ULC.
If the probability of failure* or hacking Infura or RPC server is taken as P, then with the ULC consensus M/N trusted LES nodes, the probability of its failure can be considered as Bernoulli process:
*Failure - in the sense of Bezianteene failure so that it can be either node crush or malicious actions. Such a failure for a trusted LES node can be sending fake announcements. So trusted LES node can try to "switch" a user to a malicious chain.
For example, let's calculate the failure probability
Let's take several values of the LES server failure probability and see what the probability of ULC breakage of the client is:
|
|–-|–-|–-|–-|–-|–-|–-|–-|–-|–-|–-|
| ~
So ULC drastically increases censorship resistance of an Ethereum client. We can develop a far more reliable system using unreliable nodes.
A few N/M, given
N | M | ~ |
---|---|---|
3 | 2 | |
4 | 2 | |
4 | 3 | |
5 | 2 | |
5 | 3 | |
5 | 4 | |
6 | 2 | |
6 | 3 | |
6 | 4 | |
6 | 5 |
Values 2/3, 3/4, 3/5, 4/5 look like reasonable values to use in ULC client.
N | M | ~ |
---|---|---|
3 | 1 | |
4 | 1 | |
5 | 1 | |
5 | 2 | |
6 | 1 | |
6 | 2 |
ULC clients need a set of trusted LES servers to get the current Chain state. It should be said that only ULC clients knows their own trusted list
, LES servers don't know whether they've been chosen as trusted by some ULC client. The key difference is that ULC clients request and accept only the signed announcements needed to trust some nonce (PoW) without performing their own check.
We're going to provide, predefined in the App, a trusted LES servers list. This also means that an application wanting to use ULC can define their own such trusted list of clients and do load balancing with a simple random choice.
One of the major drawbacks currently, however, is that LES servers can handle only a limited number of clients. At the moment it's
So if we want 3(M) out of 4(N) ULC consensus, in average we have 1000 users online, so we need minimum
It is for this reason that a new option was added in ULC for LES servers: --onlyAnnounce
. This flag ensures LES servers only handle get announce
requests, which increases the possible number of simultaneous users to about ~250 (should be stress tested).
With --onlyAnnounce
the formula looks like:
Users online | N | Server w/o onlyAnnounce |
With onlyAnnounce |
---|---|---|---|
1000 | 4 | 160 | 16 |
1000 | 5 | 200 | 20 |
1000 | 6 | 240 | 24 |
1000 | 7 | 280 | 28 |
5000 | 4 | 800 | 80 |
5000 | 5 | 1000 | 100 |
5000 | 6 | 1200 | 120 |
5000 | 7 | 1400 | 140 |
10000 | 4 | 1600 | 160 |
10000 | 5 | 2000 | 200 |
10000 | 6 | 2400 | 240 |
10000 | 7 | 2800 | 280 |
It's obvious that scaling due to server expansion inside the service is strictly limited. A prerequisite for the operation of ULC at large scales is an increase in the percentage of LES of servers relative to all Ethereum servers.
At the moment there are 15000 nodes. If 30% of them would use the LES server option, more than 300 000 ULC users could be handled simultaneously.
Our beta test showed that ULC sync is ~10x times faster than LES
Status.im is going to start using ULC to achieve greater censorship resistance and enable all possible web3
features for DApps and developers.