Skip to content
zsfelfoldi edited this page May 13, 2015 · 11 revisions

A proposal for helper mechanisms and contracts for the Ethereum Light Client Protocol

by Zsolt Felfoldi

zsfelfoldi@gmail.com

  • Majority consensus vs. correctness of execution

In a network where both full nodes and light clients exist, in some aspects they take up opposite roles. Full nodes can easily trust the blocks they process. They instantly notice attempted fraud, even if all the other nodes are conspiring to put an incorrect state transition into the consensus. But other participants (light nodes) cannot know enough about either their peers or the blocks themselves, which places them in an inherently handicapped situation. At the same time, they are much cheaper to run while running a full node gets more expensive with increases in network size and traffic, so the chance of the majority of full nodes getting into one hand increases. Light clients cannot just trust a consensus block also automatically being a correct block. They should be able to check individual state transitions and raise an alarm if they find something wrong.

In order to avoid disproportionate concentration of power, full nodes should provide services to "weaker" participants by signing certain certificates about block correctness and consensus (and having stakes placed in a contract that gives them reputation). These certificates are created in exchange for some form of efficient micro-payment (not discussed here). After buying reputation, creating each certificate will cost the full nodes practically nothing as long as they do not try to cheat. If they do, they lose their expensive reputation.

  • The Somewhat Trusted Keys list (STK)

In general, full nodes are the ones stating that a block is correct (by signing Block Certificates, BCs), while light nodes are signaling if a state transition is incorrect (by signing Transaction Alarms, TAs). If there is ever a contradiction, it should be well documented which transition's correctness is in dispute so that anyone can check it for themselves and decide whom to blacklist. If the worst thing that can happen to a key is getting blacklisted and ignored, then creating a new key with some initial trust has to cost some resources. And those resources together with the acquired reputation should not be transferable to another key. The simplest form of this is a "proof of burning money", a contract (KeyRegistry) that remembers if someone paid a sum to it but never gives that money to anyone else. This is called the value of the key. Light clients should register their keys with a small amount that is comparable to the inconvenience that they could cause to others with a false alarm. Full nodes make much stronger statements on a regular basis, so the sum and the potential punishment for trying to lie should also be higher. Acceptable sums for each role can be determined by the clients themselves.

When bootstrapping, a client can create a list of keys with enough value (we call it the Somewhat Trusted Keys list or STK), then regularly check for contradictions in statements submitted to a contract called DisputeRegistry and remove those from this list who ever signed something that was not true. This list can also be obtained from other nodes which the user can trust for some reason, in order to reduce bootstrap time.

In order to incentivize blacklisted keys to destroy their reputation entry in the state (which is worthless anyways, but still has to be checked by bootstrapping nodes), a small portion of their money can be refunded upon removal.

  • Block Certificates and Transaction Alarms

A signed BC that references a block header states that the signer certifies that it is a valid block and all state transitions starting from the end state of the previous block until the end state of the referenced block are correct. A signed TA that references a block header and contains a transation index states that the referenced state at the end of that transaction does not match the previous state with the transaction applied. BCs are created frequently (for every block by every full node) but usually do not need to be sent to the DisputeRegistry contract, only if there is also a TA that disputes its validity (when they reference the same block header). In fact, none of them will be accepted alone while at least one conflicting pair for the same block hash is not already presented. DisputeRegistry stores them in a way that they are searchable both by block header hash and by signer key. This way it can be efficiently determined if a key is in conflict with another key so that if both of them are still in the client's STK list, the wrong one can be removed.

  • Recursive Promises of Availability (RPAs)

In order for the clients to be able to know they are getting an honest service, it should also be ensured that no one can get away with signing a BC for a fake block that contains a hash with an unavailable preimage and therefore its incorrectness cannot be proven by showing the wrong state transition. For this reason we use Recursive Promises of Availability (RPAs) that are an extension of single Promises of Availability (PAs) that are also going to be used by Swarm for user data storage. For details see:

https://github.com/ethereum/go-ethereum/wiki/Swarm-Contract

A signed single (non-recursive) PA ensures that someone is motivated to keep some content (represented by a hash) available for at least a specified amount of time. If a PA is presented to the PreimageRegistry contract, someone should upload the preimage of that hash to the contract, otherwise the signer of the PA (and any other signers of the same PA whose signature is presented) gets punished. RPAs also contain a simple format descriptor which selects an algorithm (in our case only a small set of pre-defined routines is needed) that specifies which fields of the preimage binary should be considered hash references and which format descriptors apply to those. This way a single RPA referencing a block header and a few format descriptor functions can ensure the availability of the entire block togerher with the intermediate states referenced in the transaction receipts and also the final state of the previous block. For a detailed description of RPA types necessary for Ethereum blocks, see:

https://github.com/zsfelfoldi/go-ethereum/wiki/RPA-types

Technically the BC should act as a RPA too, although a RPA that is not a BC should be possible to create as this is a universally useful service that can be used by other services like Swarm-based DAPPs to ensure storage of user data.

A work-in-progress version of the RPA contract can be found here: https://github.com/zsfelfoldi/ethapps/blob/master/rpa.sol

  • Chain Commitments (CCs)

Together with BCs and POAs, a third type of insurance is also needed in order to avoid misleading clients into wrong forks of the chain. Full nodes have the most power over the consensus, so they can be absolutely sure which one is the consensus block for a given block number. For this reason, they should sign Chain Commitments (CCs) that say "the hash of block header #N is H". These are usually signed at a later time than BCs, when absolute consensus is reached. If a CC is posted to the KeyRegistry contract on any other chain (where the hash of block header #N is not H), the signer key is automatically disqualified and all its value is lost. Basically, we excpect full nodes to voluntarily destroy themselves in any alternative chains, ensuring that clients can trust a CC signed by someone inside the STK list with a high value.

Clone this wiki locally