Freeton Wiki
Advertisement

Slashing conditions are conditions under which a validator’s stake is seized due to their incorrect behaviour.

Byzantine Generals’ Problem and Byzantine Fault Tolerance (BFT)[]

Blockchain is a decentralized ledger that is not controlled by a central authority, which is a good opportunity for bad actors to cause some faults in the system. Byzantine Fault Tolerance helps to solve this problem.

Byzantine Fault is a computer system condition where elements may fail and it is quite difficult to understand where these elements have failed or not. Byzantine Faults are considered the most severe and difficult to deal with.

Byzantine Generals’ Problem is a term created to describe a situation when more than two actors of the system must agree on what strategy they are going to use to avoid failure of the whole system, but the problem is that some of these actors may be betrayers. What algorithm will be used to achieve consensus depends on the value of the majority decisions, which means that there must be at least ⅔ honest actors for the algorithm to reach consensus. If there are more than ⅓ betrayers, reaching consensus is failed.

Byzantine Fault Tolerance is the property of the system that can withstand the class of failures that belong to the Byzantine Generals’ Problem. It means that the BFT system continues to work even if some nodes work incorrectly or act maliciously. Byzantine Failures are considered the most difficult class of failures among the failure modes. Byzantine Failures imply no restrictions about how a node should behave, for example, an invalid node can generate any arbitrary data as if it is a valid one.

Minimal slashing conditions are the main component of a Byzantine-fault-tolerant, safe-under-asynchrony, and crypto economically safe consensus algorithm.

Economic Finality[]

The Casper protocol is taken as an example. The main purpose of this protocol is to reach “economic finality”, which can be defined as follows:

A block B1 is economically finalized, with crypto-economic security margin $X, if a client has proof that either (i) B1 is going to be part of the canonical chain forever, or (ii) those actors that caused B1 to get reverted are guaranteed to be economically penalized by an amount equal to at least $X.

Validators must submit their deposits to take part in the process of achieving economic finality, and if they violate some slashing conditions, their deposits are taken away.

A slashing condition might look like this:

If a validator sends a signed message of the form

["PREPARE", epoch, HASH1, epoch_source1]

and a signed message of the form

["PREPARE", epoch, HASH2, epoch_source2]

where HASH1 != HASH2 or epoch_source1 != epoch_source2, but the epoch value is the same in both messages, then that validator’s deposit is slashed (ie. deleted).

Honest validators follow slashing conditions set by the protocol and they are not supposed to violate any of these conditions. For example, any honest validator must not send a PREPARE message in the same epoch twice. “PREPARE” and “COMMIT” are terms that come from traditional Byzantine fault-tolerant consensus theory and represent the first and the second rounds of agreement, respectively.

Finality Condition[]

Finality condition helps a client to define that some particular hash gets finalized.

Example of the sole finality condition in the current version of Casper:

A HASH is finalized if, for some particular epoch number, there exists a set of signed messages of the form

["COMMIT", epoch, HASH]

and if you add up the deposited balances of the validators that created these signed messages then you get an amount that is more than ⅔ of the total deposited balances of the current active validator set.

To put it simply, “⅔ of validators committed the hash in some particular epoch”, or “the hash has ⅔ commits in some particular epoch”.

The slashing conditions must meet two conditions:

  1. Accountable safety: if two hashes in conflict get finalized, in this case, it must be provably true that some slashing condition was triggered by ⅓ of validators at a minimum. The ⅓ ratio is taken from the traditional Byzantine fault-tolerance theory and is used to lead the total level of fault tolerance to the maximum.
  2. Plausible liveness: if at least ⅓ of validators didn’t trigger any slashing condition, then there must be a set of messages that can be sent by ⅔ of validators which finalize some new hash without violating some slashing condition.

Accountable safety is closely connected with economic finality: if two hashes in conflict get finalized, then there appears mathematical proof that a big set of validators violated some slashing condition, and evidence of this can be presented to the blockchain and validators get panelized if the deposits haven’t been withdrawn yet.

Plausible liveness implies that the algorithm in no way can stop working and finalizing anything at all.

Accountable Safety and Plausible Liveness Algorithms[]

To demonstrate the meaning of accountable safety and plausible liveness, below there are two algorithms, one which satisfies safety but not liveness, and one which satisfies liveness but not safety.

Algorithm 1: every validator has exactly one opportunity to send a message of the form ["COMMIT", HASH]. If ⅔ of validators send a COMMIT for the same hash, that hash is finalized. Sending two COMMIT messages violates a slashing condition.

There is very obvious proof that this algorithm is safe: if HASH1 and HASH2 both get finalized, then that means that each one has ⅔ commits, and so there must be ⅓ overlap, so ⅓ of validators get slashed. But it is not plausibly live: if ½ commit A and ½ commit B, then ⅙ of validators must voluntarily slash themselves to finalize a hash.

Algorithm 2

Algorithm 2: every validator has exactly one opportunity to send a message of the form ["COMMIT", HASH, epoch]. If ⅔ of validators send a COMMIT for the same hash with the same epoch number, that hash is finalized. Sending two COMMIT messages with different hashes with the same epoch number violates a slashing condition.

This gets around the problem in the previous algorithm, as if during one epoch we get a 50/50 situation then we can simply try again in the next epoch. But this introduces a safety flaw: two different hashes can get finalized in different epochs.

Epoch

It turns out that it is possible to get both at the same time, but this is not easy and requires 4 slashing conditions, plus 1000 lines of code to formally prove that it works.

The slashing conditions are:

[COMMIT_REQ] If a validator sends a signed message of the form

["COMMIT", epoch, HASH]

then unless, for some specific value epoch_source, with -1 <= epoch_source < epoch, messages of the form

["PREPARE", epoch, HASH, epoch_source]

have been signed and broadcasted by ⅔ of validators, then that validator’s deposit is slashed.

Simply put, sending a commit requires seeing ⅔ prepares.

[PREPARE_REQ] If a validator sends a signed message of the form

["PREPARE", epoch, HASH, epoch_source]

where epoch_source != -1, then unless, for some specific value epoch_source_source, with -1 <= epoch_source_source < epoch_source, messages of the form ["PREPARE", epoch_source, ANCESTOR_HASH, epoch_source_source], where ANCESTOR_HASH is the (epoch — epoch_source) — degree ancestor of HASH, have been signed and broadcasted by ⅔ of validators, then that validator’s deposit is slashed.

If a prepare in some epoch is made pointing to some particular previous epoch, then ⅔ prepares must have been seen in that epoch, and those prepares must point to the same previous epoch (for instance, ⅔ prepares in epoch 41 pointing to epoch 35 are okay, ⅔ prepares in epoch 41 with half pointing to epoch 35 and a half pointing to 37 are not; ⅚ prepares in epoch 41 with ⅘ of them pointing to epoch 35 is also fine, because ⅘ of ⅚ is 2/3, and you can just ignore the other ⅙).

By “n-th degree ancestor”, an ancestor in the blockchain hash-chaining sense of the term is meant, where, for example, Ethereum block 3017225 is the 15th-degree ancestor of Ethereum block 3017240. It is important to note that a block may only have one parent, and so only one n-th degree ancestor for any specific value of n.

[PREPARE_COMMIT_CONSISTENCY] If a validator sends a signed message of the form:

["COMMIT", epoch1, HASH1]

and a prepare of the form

["PREPARE", epoch2, HASH2, epoch_source]

where epoch_source < epoch1 < epoch2, then, irrespective of whether or not HASH1 ?= HASH2, the validator is slashed.

If a commit is made during some epoch, then ⅔ prepares must have been seen during that epoch, and so any future prepares that will be done should better be referencing that epoch or something newer.

[NO_DBL_PREPARE] If a validator sends a signed message of the form

["PREPARE", epoch, HASH1, epoch_source1] and a signed message of the form

["PREPARE", epoch, HASH2, epoch_source2]

where HASH1 != HASH2 or epoch_source1 != epoch_source2, but the epoch value is the same in both messages, then the validator is slashed.

Can’t prepare twice in a single epoch.

With these four slashing conditions, it turns out that both accountable safety and plausible liveness hold.

It is important to mention that with the above rules two different hashes can get finalized — if two hashes are both parts of the same history then they can both get finalized, and an ever-growing chain where more and more hashes at the end of the chain get finalized is exactly what we want.

Hash conflicting

So, there exists a pool of active validators, which anyone can join, with some delay, by submitting a deposit, and which any participant can leave and then, after some much higher delay, withdraw their funds), and these validators have the right to sign and send messages of the form

["PREPARE", epoch, HASH, epoch_source]

["COMMIT", epoch, HASH]

If there are enough COMMIT messages for some HASH during some particular epoch, then that HASH is finalized. Hashes are chained to each other, with each hash pointing to some previous hash, and an ever-growing chain of hashes is expected to be seen with newer and newer hashes in the chain getting finalized as time goes on. Economic rewards are added for validators to send the PREPARE and COMMIT messages so that enough messages get sent in time for finalization to happen.

Any Byzantine-fault-tolerant consensus algorithm that has the “live under synchrony, safe under asynchrony” property of PBFT can be taken, and converted into a set of slashing conditions that give accountable safety and plausible liveness. However, this algorithm should use hashes and signatures for cryptography. If it uses threshold signatures, there can be a problem, as a unity of ⅔ bad nodes can fake any other participant’s signature.

Proposal Mechanism[]

It is important to mention that plausible liveness is not equal to actual liveness as plausible liveness implies that theoretically something can always get finalized, but there can be such a situation that due to some circumstances nothing gets finalized. Proposal mechanism is what helps to reach liveness.

A proposal mechanism is a mechanism that proposes hashes that the rest of the machinery with the help of PREPARE and COMMIT messages then tries to finalize. However this mechanism may sometimes fail, and that’s why the slashing conditions control that there aren't any safety failures and the protocol can continue finalizing as soon as the proposal mechanism starts working properly.

The proposal mechanism and the rest of the algorithm are closely connected in traditional Byzantine-fault-tolerant consensus algorithms. In Practical Byzantine Fault Tolerance, every view which means the same as epoch belongs to one validator, and this validator can propose everything they want. Though the validator may act incorrectly as, for example, propose nothing, propose invalid hashes or propose multiple hashes, the other elements of the PBFT machinery guarantee that such actions are not disastrous, and the algorithm just moves to the next epoch. Slashing conditions can be combined here with different types of proposal mechanisms, as long as they satisfy a few conditions.

First, only one hash per epoch can be proposed by the proposal mechanism, and this hash must be valid.

Second, the hashes must form a chain; that is, a hash submitted for epoch N must have a parent that was submitted for epoch N-1, a 2nd-degree ancestor that was submitted for epoch N-2, etc.

Third, this must be hashes that can be finalized by validators without the slashing conditions preventing them from it. For instance, in epoch 0 the proposal mechanism proposes a hash HASH0, then in epoch 1 the proposal mechanism proposes a hash HASH1, which is a direct child of HASH0, and for some reason, neither of these hashes reach enough prepares to get any commits. After that, as there is some temporary fault, the proposal mechanism proposes another hash HASH0' for epoch 0, and this gets ⅔ prepares and ½ commits.

Proposal mechanism

Now, the proposal mechanism can act in two ways. The first way is to propose HASH2, which is a direct child of HASH1, then HASH3, which is a direct child of HASH2, and so on. However, the slashing conditions guarantee that none of these hashes could get committed if 1/6 of validators are not slashed.

The other way, which is a correct one, is to propose HASH1', which is a direct child of HASH0', and it is should be expected that this hash may never get finalized because probably its competitor HASH1 already got more than ⅓ prepares and so HASH1' can’t get the ⅔ that it needs, and then propose HASH2', which is a direct child of HASH1'. HASH2' can get committed, and the mechanism can then continue proposing new hashes, each of which is a child of the previous hash.

According to the mentioned slashing rules, such a type of fault as a finality-reverting fork is very expensive to develop. However, such faults as, for example, finalizing an invalid hash or finalizing a hash that represents a chain that has some data unavailable are not a problem to create. One of the easiest ways to solve this problem is to be a full node which means downloading and validating all blocks so that invalid hashes are ignored. This way implies absolute cryptoeconomic security.

Economic Finality and Light Clients[]

There exist two approaches to make finality work for light clients.

The first approach implies changing a type of message to another one that nodes can send (["ATTEST", HASH, epoch]), and if this message is submitted into a chain where the given hash is the hash at that epoch, the validators are rewarded, but if it is not, in this case, the validators are penalized with heavy fines. That’s why validators should send the message if they are sure that a given hash is part of the canonical chain that clients see and this hash will always be part of it. Validators should validate a blockchain up to the hash and make sure that this hash has ⅔ commits.

The second approach is to make cryptoeconomic techniques available for light clients so that they can verify data availability and validity with great effectiveness with the help of some weak honest minority assumptions. A combination of erasure codes and interactive verification are going to be among these techniques.

The second approach is closely connected with sharding as it doesn’t require the validators to be a full node, and sharding implies developing a blockchain where no one is a full node, whereas the first approach obliges the validators to be a full node.

References[]

  1. Understanding Blockchain Fundamentals, Part 1: Byzantine Fault Tolerance
  2. Minimal Slashing Conditions

ru:Минимальные_Условия_для_Сокращения

Advertisement