Skip to content
This repository has been archived by the owner on Jan 24, 2024. It is now read-only.

Minigeth Rebase

norswap edited this page May 18, 2022 · 4 revisions

This page now lives on the Cannon wiki


Table of Contents

Context & Overview

Minigeth, as delivered by geohot, is a modified subset of upstream go-ethereum (aka geth), which will be compiled to MIPS to fit the needs of Cannon (cf. high-level overview. Minigeth was included in the Cannon repository itself.

Going forward, we needed to make changes to Minigeth because (a) we need to keep up with upstream geth changes, and (b) Cannon as-delivered implements fault proofs for the L1 chain, but we need fault proofs for the L2 chain, meaning Minigeth must be modified to be a proper L2 validator.

In particular, our L2 design splits the validation logic between a rollup driver (implemented in the optimistic-specs repo) and an execution engine (implemented in the reference-optmistic-geth repo.

The execution engine is itself implemented by a minimal diff on top of geth. Whenever we want to update geth, we can rebase our changes on top of the latest geth version.

So the changeset of L2 minigeth compared to L1 geth will include:

  • minigeth-specific changes (deleting a lot of geth, changing some parts)
  • L2 execution engine changes on top of geth
  • rollup driver logic

We determined that, for ease of maintenance, it was ideal for Minigeth to live in its own repository and to have its own changes implemented on top of the execution engine, meaning we can rebase the minigeth changeset on top of the execution engine whenever the execution engine is updated.

minigeth  ==[changes on top of]==>  L2 execution engine  ==[changes on top of]==>  L1 geth

Note that as the "main" branches of minigeth and the execution engine are periodically being rebase on top of their respective upstreams, history will be rewritten.

Schematic overview of how to update to a more recent version of geth (e.g. new Ethereum hardfork):

cd l2-execution-engine
git rebase l1geth/new-geth-version
go test # build & verify
git push -f
cd ../minigeth
git rebase l2-execution-engine/main
go build # verify
git push -f
cd ../cannon/minigeth
git fetch && git reset --hard origin/main
cd ..
make mrproper && make build && make test
git add minigeth
git commit -m "update minigeth version"
git push

Note that all names in this example are symbolic, actual names used for branches etc will differ.

Minigeth Rebasing Guidance & Tricks

The "L1 minigeth diff" (i.e. the changes between L1 minigeth and upstream geth) has been structured as a series of commits targetting specific directories.

For instance, here's the current list of commit messages:

effe110 add README and main.go
cc8f725 add preimage oracle
a56f8d8 modify files in the trie directory
52c4bdd remove files in trie directory
f79c60b delete files in rpc directory
40321e9 modify rlp/unsafe.go
bab3f95 delete files in rlp directory
d81a451 delete files in params directory
e3162b8 modify log/logger.go
bfdf1ad delete files in log directory
128c502 modify metrics/metrics.go
fc68062 delete files in metrics directory
a0609d8 delete files in ethdb directory
4427f69 modify and add files in crypto directory
621d53f delete files in crypto directory
421a68d modify and add files in core directory
af95984 delete files in core directory
b676fd5 add consensus/ethash/fake_ethash.go
c2a0f92 remove files in the consensus directory
6a0196b delete files in common directory
e585cc4 remove unused top-level directories and files

Each commit either deletes, adds, or modify files. Things were structured in this way to make rebases less overwhelming, as it is only necessary to consider changes in a single directory at a time.

This is not perfect either — sometimes logical changes that we need to account for will be split between multiple directories and between deletions/modification/additions/.

However, this is a practice choice, as the overwhelming majority of conflicts encountered during such a rebase will be that upstream geth modified some files that were modified in minigeth.

Another issue with this is that the original history of minigeth isn't preserved in the new repository (but can still be consulted in the Cannon repo). While it may be possible to work some git magic to import it, this is not desirable as it would multiple the amount of changes to the same files, making rebases all the more difficult.

Here are two useful commands to be used when performing such a rebase and encountering conflicts:

  • git status -s | grep -v "^D "
    This selects changed files that are not simple deletions (since the biggest chunk of changes will be unconflicted deletions).
  • git rm $(git status -s | grep -v "^D " | grep "^UD " | cut -c 4-)
    This command instructs git to resolve all "UD" conflicts (file we delete but was changed in upstream geth) by deleting the conflicted file.

Minigeth Branches

We've set up a couple branches in the minigeth repo, which mostly act as dynamic bookmarks to track and compare various things.

  • l2minigeth
    The default branch, meant to track the current minigeth implementation for L2 and to be referred to by a submodule in the Cannon repo.
  • l1minigeth
    The original minigeth implementation as delivered by geohot, for L1 fault proofs. This is not meant to change.
  • l1minigeth-base
    The v1.10.8 geth release, on which the original minigeth implementation is based. Not meant to change.
  • l2geth-head
    Meant to track the upstream default branch of the L2 execution engine. This should however always point to the commit that l2minigeth is rebased on top of.
  • l2geth-base
    Meant to track the upstream (L1) geth commit that l2geth-head builds on.
  • l1geth-head
    Meant to the track the upstream L1 geth default branch. This is probably the least useful branch, since L2 minigeth builds on the L2 execution engine and not the L1 upstream directly.

Note that a lot of these branches are meant to track some upstream, but they require manual intervention to update.

In particular, since we want to maintain l2minigeth as a rebase on top of l2geth-head, it might be frequent that the upstream L2 execution engine has been updated, but these two branches haven't been yet.

If we reprise our diagram from above:

minigeth  ==[changes on top of]==>  L2 execution engine  ==[changes on top of]==>  L1 geth
branch: l2minigeth                  branch: l2geth-head                            branch: l2geth-base

Additionally, here are some useful diffs: