-
Notifications
You must be signed in to change notification settings - Fork 36
Minigeth Rebase
This page now lives on the Cannon wiki
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.
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.
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 thatl2minigeth
is rebased on top of. -
l2geth-base
Meant to track the upstream (L1) geth commit thatl2geth-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:
-
l2geth-head
←l2minigeth
"The" diff, which shows the changes minigeth makes to the L2 execution engine. -
l1minigeth-base
←l1minigeth
The original L1 minigeth diff. -
l1minigeth-base
←l2geth-base
Shows the changes to L1 geth in between it being forked for L1 minigeth and the current base for L2 minigeth. -
l2geth-base
←l1geth-head
Shows the changes to upstream L1 geth since the L2 execution engine was last rebased on top of it (assuming the branches are up to date)!