Skip to content

Versioned state for on-chain upgrades #233

@Stebalien

Description

@Stebalien

Currently, every time an on-chain data structure changes, a state migration needs to be run to migrate all state from the old format to the new format.

  1. As the state-tree grows, this becomes more and more time consuming and difficult.
  2. In a future world with a VM, it would be nice to perform upgrades through normal chain mechanisms. But there's no way this can happen if all state needs to be migrated up-front (won't happen in a single block time).

There's a pretty simple solution: version the state. However, there are two options:

  1. Version entire actor states.
  2. Version each object separately (e.g., each sector info).

Versioned Actor State

This is the cleanest solution as migrations are atomic. Unfortunately, this would still force us to eventually migrate the entire actor's state as a whole, and that can get pretty expensive (e.g., if we need to migrate all sector infos).

Implementation wise, we'd:

  1. Keep some version and/or a schema CID inside the actor's metadata.
  2. If the actor's state version/schema differs from the expected version/schema, require that some client submit a "migrate" message to the actor to migrate the state.

Versioned Objects

At the cost of one extra byte per object (where our smallest objects are ~100bytes), we can prepend a version field to every object. Then:

  1. If the version matches, decode the object.
  2. If the version doesn't match, decode with the previous version's decode logic then apply a transform to to the state.

The downside is:

  1. A bit of extra on-chain work when reading old state.
  2. Extra complexity for tools reading on-chain state (they'll need to support historical versions and will need to implement the migration logic).

The upside is that state never actually needs to be migrated. It'll just be transformed on read. Assuming these transforms are light weight (which is the usual case), this should add very little overhead.

Unfortunately, if we change the HAMT/AMT implementations, this solution won't be enough as HAMTs/AMTs are composed of multiple objects. However:

  1. We can, in most cases, make HAMTs and AMTs more flexible in what they consider to be a valid structure. This would allow us to slowly migrate them piece by piece.
  2. We don't change these too frequently.

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