Skip to content

State root checkpointing #45

@lrettig

Description

@lrettig

This question has come up a few times but I don't think we've reached consensus on it yet so I'm opening an issue to discuss it.

In Ethereum and many similar blockchains, each block includes a single "state root," which is the root of a Merkle tree (or trie) that contains all account state after that block is processed. This means that if a node runs all of the transactions in a block through the STF and arrives at a different state, it will immediately reject that block. It's worth pointing out that this isn't purely academic or theoretical, as it's happened in Ethereum several times - often due to a bug in one implementation of the VM.

We don't have something like this in the current Spacemesh design and it's an issue. For sake of argument, imagine that there are multiple Spacemesh implementations and that a bug in one of them (inside or outside the VM) causes some subset of nodes to incorrectly calculate the balance after a transaction. Every node will still think it's in sync (because it has the same layer, block, and tx data), the network will not fork, and there will be no indication of any issue here unless and until the accountholder in question tries to "double spend" some portion of those funds that are in question (i.e., that some nodes think they have, others think they don't have). This could take a long time, or it may never happen.

I propose introducing a frequent "state root checkpoint" so that issues of this sort are immediately detected. (How to deal with them once they're detected is interesting but it's a separate question that has more to do with social governance than with research so I won't go into it here.)

Here are three proposals for how we might achieve this, in order from least complex and least desirable to most complex and most desirable:

  1. Extend the ATX to include a state root checkpoint - i.e., the ATX indicates a specific layer (probably the end of the previous epoch) and the node's view of the state root after including all transactions in that layer. This would give us a once-per-epoch checkpoint. Nodes that detect ATXs with state roots that they consider invalid could fork away from those miners, or quit entirely - both of which are better than the status quo behavior IMHO.

  2. Extend each block to include a state root checkpoint, which indicates the node's view of the state root as of the previous layer. A node could reject blocks (as syntactically invalid) if they disagree with the node's observed state root.

  3. Similar to (2.) but include two state root checkpoints in each block. The first, as in (2.), is the state root as of the previous layer. The second is the state root after applying the transactions in this block as if it were the only block in the current layer (i.e., directly on top of the state as of the previous layer). This would most closely mimic the behavior in Ethereum: a node could independently verify that applying the transactions in each block produces the expected result, and would provide block-level granularity when something goes wrong, i.e, we could immediately detect the offending block.

Keen to hear thoughts. CC @noamnelke, @tal-m, @avive, @YaronWittenstein

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions