feat: re-fork cometbft-bera onto the v0.40.x line - #63
Draft
fridrik01 wants to merge 3 commits into
Draft
Conversation
|
The latest Buf updates on your PR. Results from workflow Protobuf Lint / lint (pull_request).
|
fridrik01
force-pushed
the
refork-cometbft-bera-to-0.40
branch
from
August 21, 2026 16:11
4679819 to
3d10c38
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR moves the Berachain CometBFT re-fork from upstream v0.39.x to upstream v0.40.x. It establishes the new
bera-v0.40.xline, which starts from the pristine upstream tagv0.40.0and carries the same Berachain changes that the v0.39 re-fork (#51) carried. The v0.39 re-fork was still a draft and never reached testnet or mainnet, so this PR replaces it rather than building on it. Thebera-v0.39.xbranch was not merged here. Everything was recreated on top ofv0.40.0, so the branch keeps clean upstream ancestry.The goal is unchanged from #51. A
bera-v1.xnetwork can move to this binary with a rolling restart and no state migration, because the consensus sign bytes, hashes, wire format and on-disk state are byte identical tobera-v1.x. The difference this time is that the claim is backed by committed tests (see Testing) instead of an out-of-tree harness.Why v0.40
Upstream supports two release lines at a time, and v0.40 is now the newer of the two. Since the v0.39 re-fork had not been deployed anywhere yet, starting the Berachain line on v0.40.0 costs nothing today and gives us the longest runway before the next forced move. It also means the first upstream sync merges we do will be small v0.40.x patch releases rather than a jump from v0.39 to v0.40.
What is in it
The Berachain feature set is exactly the one described in #51, ported without behavior changes:
has_proposal_block_partat 10, wholecommitat 11).SignBytesrequest and compressed BLS public key support.MaxVotesCountcap on gossiped commits, race-freeCommit.String, vote gossip skipping a whole-commit LastCommit).On top of that, three small additions that came out of testing against a real bera-v1.x binary. All three are additive and wire compatible:
ValidatorUpdateunderstands both public key encodings. bera-v1.x writespub_key_bytespluspub_key_type, upstream writespub_key. FinalizeBlock responses are persisted in the state store and read back during crash recovery and for/block_results, so the node now reads either form and writes both. This keeps the store readable in both directions of a rolling upgrade.ubuntu-latestinstead of the upstream depot runners, the same fix that was applied tobera-v0.39.x.How this was built
The eight commits of #51 were cherry-picked one at a time onto
v0.40.0. Most of them applied cleanly. Conflicts came up in a handful of files where upstream moved between v0.39.4 and v0.40.0, and they were resolved by hand:state/execution.go. Upstream added a per-block validator set cache and turned thebuildLastCommitInfoFromStorehelpers into methods onBlockExecutor. The port keeps upstream's methods and threadsFeatureParamsandNextProposerAddressthrough them.types/params.goandcrypto/encoding/codec.go. Upstream added the ml-dsa-65 and secp256k1eth key types. They are kept, next to the synchrony and feature params from the port.privval/retry_signer_client.go. Upstream made retries abortable on close. The portedSignBytesfollows the same pattern.version/version.go,CHANGELOG.md, one test file.A file-by-file comparison with the #51 tree, after subtracting everything upstream changed between v0.39.4 and v0.40.0, leaves only the three additions above. In other words, the Berachain payload is the same diff as before, re-based by hand.
How to review
The bulk of the diff is the same code that was reviewed in #51, and the same split applies. The generated
.pb.gofiles,crypto/bls12381,verifyAggregatedCommit,MakeBLSCommit,IsTimelyand most ofconsensus/state.goare faithful ports and can be skimmed.Worth a closer look:
state/execution.gois the largest one.consensus/msgs.goandproto/tendermint/consensus/wal.protofor the WAL receive time.types/protobuf.go(PubKeyFromValidatorUpdate,NormalizeValidatorUpdates) andstate/store.gofor the validator update encoding.test/compat/, which is new. Start with its README.Upstream changes between v0.39.4 and v0.40.0
Every upstream commit in that range was checked for interaction with the port. The ones that matter:
MedianTimeno longer counts nil precommits (upstream marks this state-breaking). It does not change anything here.MedianTimeis only used on the BFT Time path, and this fork forces PBTS, exactly as bera-v1.x does.MaxSignatureSizegrew to fit ml-dsa-65 signatures, which shrinks the maximum tx bytes a proposer offers by a few kilobytes per validator. It is a local sizing value, not part of any hash or validation, and beacon-kit sets the block size to 100 MB, so it has no practical effect. Noted for completeness.keys.proto, and the privval noise listener. All defaults or additive.signVote. Vote extensions are disabled on Berachain.Compatibility with bera-v1.x
Two cosmetic differences remain and are asserted as such by the tests. The consensus params JSON written by this fork carries an empty
authorityobject that bera-v1.x ignores, andValidatorUpdate.pub_keyis a non-nullable message here so an unset key still encodes as an empty field that bera-v1.x skips.Testing
Unit tests and lint pass with and without
-tags bls12381, including-raceon the consensus, types, state and privval packages.make proto-genreproduces the committed generated files.New in this PR, under
test/compat/:vectors_test.goreplays a fixed set of inputs through this fork and compares every output byte for byte with vectors produced by the bera-v1.x code. It covers vote and proposal sign bytes and BLS signatures, aggregated and individual commits and their hashes, block and header hashes, consensus params, validator sets, evidence, the persisted state, the ABCI responses, every consensus p2p message, the WAL entries, and the genesis and key files. It runs in CI.gen-v1x/is the generator. It is a separate Go module pinned to the bera-v1.x head, so the vectors can be regenerated from scratch at any time. Its-verifymode does the reverse check, decoding and verifying what this fork produces with bera-v1.x code.rolling_upgrade.shstarts real nodes. Phase A runs one validator on bera-v1.x, then bera-v0.40.x, then bera-v1.x, then bera-v0.40.x, all on the same data directory. Phase B runs four BLS validators and moves them one at a time from bera-v1.x to bera-v0.40.x, restarts an upgraded node mid-soak, lets a node on each version block-sync the blocks it missed from mixed peers, sends a transaction through the upgraded network, rolls one node back to bera-v1.x and forward again. At every stage it checks that all validators signed every block, that both versions proposed, that commits stayed aggregated with round 0, that block hashes agree on every node, and that the logs are free of codec errors.All of the above passed locally against the bera-v1.x head. The remaining step before testnet is the same devnet rolling upgrade exercise that was planned for #51, with beacon-kit built against this branch.
test/compatis meant to stay in the tree after the upgrade, and its pieces have different lifetimes:gen-v1x/only exists to regenerate the vectors from the bera-v1.x code and to run the reverse check. It pins a bera-v1.x commit, so it is the one piece with a maintenance cost. It can be removed once bera-v1.x is retired from the network.rolling_upgrade.shtakes the two binaries as parameters, so after this upgrade it becomes a generic "previous release versus next release" check. Every futurebera-v0.40.xrelease is a rolling upgrade on mainnet, and the script proves data-dir reuse in both directions, a mixed validator set, block-sync across versions and rollback in a few minutes. A follow-up can rename the variables and drop the bera-v1.x defaults.Base and upstream syncing
The
bera-v0.40.xline is created from the upstream tag, as before:Future upstream releases are adopted by merging the release tag into
bera-v0.40.xthrough a normal PR. Using the next patch release as the example:Sync PRs must be merged with a merge commit, never squashed. Squashing breaks the shared ancestry with upstream, so every later sync re-conflicts on changes we already took. Merging rather than rebasing also keeps the branch append-only, so open PRs, clones and go module consumers survive a sync, and each conflict is resolved once inside a reviewed PR.
The Berachain changes stay easy to inspect.
git diff v0.40.0 bera-v0.40.xshows everything we maintain on top of the latest upstream tag, and thetest/compatvectors test fails if a sync ever touches the consensus bytes.Urgent upstream fixes can be cherry-picked between releases, and the next sync merge supersedes them.