Fork Choice: The Rule Is the Highest Certificate, and On This Deployment There Is One Database Behind All Four Validators

The question

A participant sees two candidate histories. Which one does it build on?

Every chain needs an answer and the answers differ. Some take the longest chain, some the one with the most work behind it, and protocols of this family take the one with the most recent proof that a quorum agreed.

The rule here

Build on the block named by the highest certificate you have seen.

When a proposer starts a block, its parent is the block that certificate points at, falling back to the last committed block when there is no certificate yet.

And the lock does the other half. A participant will not vote for a proposal that conflicts with what it has already locked, so fork choice picks the branch and the lock stops you abandoning one you have effectively committed to.

What a stranger can actually verify, and it is rare

Walk the canonical chain and check that each block's parent hash equals the previous block's hash.

Fifteen consecutive links were checked. All fifteen matched. And the head pointer's hash equals the newest block's hash.

This is one of only two things on this read surface that a stranger can confirm end to end, the other being that a block's transaction digest matches its own transaction list. Neither needs an account, a key, or any trust in us.

Use the canonical sequence rather than the height to do it. Height on this chain is not one value per block, and walking heights skips two blocks in three.

And here is what fork choice is actually doing on this deployment

We looked on the machine.

each validator directory holds only keys and a configuration file, sixteen kilobytes apiece a single database directory of a hundred and seventy-nine megabytes serves all of them

Four validators, one process, one store. There is no second copy of the chain for a fork choice to choose between.

So the rule is implemented and the situation it exists for cannot arise here. A protocol mechanism running where its precondition is absent is not evidence that it works, and this page would rather say that than imply a test has happened.

Although the code expects divergence anyway, and once paid for it

The idle heartbeat's stated purposes include bounding how long engines can stay divergent, which tells you the authors consider engine divergence a real state rather than a theoretical one.

And the ledger carries a repair for exactly that. The head pointer is deliberately monotone, and the comment says why: a lagging engine's backfill re-appended an early block, dragged the head pointer backwards past blocks another engine had already canonicalized, and a restart that trusted the pointer then orphaned them.

Blocks were lost. The fix is a monotone pointer plus a forward scan that heals a lagging head, and the comment concedes that a read-then-write interleave can still lose one advance for a tick, which the next pass repairs.

That is a much more useful thing to publish than a diagram of the rule. The mechanism has been tested by an incident, and the incident is written down where the fix lives.

Sharing a store is not the same as agreeing

Four engines writing one database do not corroborate each other. They can only agree, which is why safety cannot be checked here at all and why the head-pointer race above was possible in the first place.

The property fork choice is supposed to deliver, convergence between parties with independent views, has no independent views to converge.

What you can check yourself

solidus_canonHead, then solidus_getBlockBySeq downward, comparing each block's parent_hash with the previous block's hash

They should match at every step, and the head's hash should equal the newest block's. If you walk heights instead, you will see breaks that are not breaks, because two blocks in three are not addressable that way.

Keep reading

Fork Choice: The Rule Is the Highest Certificate, and On This Deployment There Is One Database Behind All Four Validators · Solidus