mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-23 13:16:42 +00:00
Merge branch 'main' into update-main
This commit is contained in:
commit
16b72db3ba
135 changed files with 3390 additions and 894 deletions
10
.claude/settings.local.json
Normal file
10
.claude/settings.local.json
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"permissions": {
|
||||||
|
"allow": [
|
||||||
|
"Bash(git add:*)",
|
||||||
|
"Bash(git commit:*)",
|
||||||
|
"Bash(git push:*)"
|
||||||
|
],
|
||||||
|
"deny": []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -1,27 +0,0 @@
|
||||||
on:
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
### Note we cannot use cron-triggered builds right now, Gitea seems to have
|
|
||||||
### a few bugs in that area. So this workflow is scheduled using an external
|
|
||||||
### triggering mechanism and workflow_dispatch.
|
|
||||||
#
|
|
||||||
# schedule:
|
|
||||||
# - cron: '0 15 * * *'
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
azure-cleanup:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: 1.24
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: Run cleanup script
|
|
||||||
run: |
|
|
||||||
go run build/ci.go purge -store gethstore/builds -days 14
|
|
||||||
env:
|
|
||||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
|
||||||
|
|
@ -1,46 +0,0 @@
|
||||||
on:
|
|
||||||
push:
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
### Note we cannot use cron-triggered builds right now, Gitea seems to have
|
|
||||||
### a few bugs in that area. So this workflow is scheduled using an external
|
|
||||||
### triggering mechanism and workflow_dispatch.
|
|
||||||
#
|
|
||||||
# schedule:
|
|
||||||
# - cron: '0 16 * * *'
|
|
||||||
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
ppa:
|
|
||||||
name: PPA Upload
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Show environment
|
|
||||||
run: |
|
|
||||||
env
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: 1.24
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: Install deb toolchain
|
|
||||||
run: |
|
|
||||||
apt-get update
|
|
||||||
apt-get -yq --no-install-suggests --no-install-recommends install devscripts debhelper dput fakeroot
|
|
||||||
|
|
||||||
- name: Add launchpad to known_hosts
|
|
||||||
run: |
|
|
||||||
echo '|1|7SiYPr9xl3uctzovOTj4gMwAC1M=|t6ReES75Bo/PxlOPJ6/GsGbTrM0= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA0aKz5UTUndYgIGG7dQBV+HaeuEZJ2xPHo2DS2iSKvUL4xNMSAY4UguNW+pX56nAQmZKIZZ8MaEvSj6zMEDiq6HFfn5JcTlM80UwlnyKe8B8p7Nk06PPQLrnmQt5fh0HmEcZx+JU9TZsfCHPnX7MNz4ELfZE6cFsclClrKim3BHUIGq//t93DllB+h4O9LHjEUsQ1Sr63irDLSutkLJD6RXchjROXkNirlcNVHH/jwLWR5RcYilNX7S5bIkK8NlWPjsn/8Ua5O7I9/YoE97PpO6i73DTGLh5H9JN/SITwCKBkgSDWUt61uPK3Y11Gty7o2lWsBjhBUm2Y38CBsoGmBw==' >> ~/.ssh/known_hosts
|
|
||||||
|
|
||||||
- name: Run ci.go
|
|
||||||
run: |
|
|
||||||
go run build/ci.go debsrc -upload ethereum/ethereum -sftp-user geth-ci -signer "Go Ethereum Linux Builder <geth-ci@ethereum.org>"
|
|
||||||
env:
|
|
||||||
PPA_SIGNING_KEY: ${{ secrets.PPA_SIGNING_KEY }}
|
|
||||||
PPA_SSH_KEY: ${{ secrets.PPA_SSH_KEY }}
|
|
||||||
|
|
@ -1,179 +0,0 @@
|
||||||
on:
|
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- "master"
|
|
||||||
tags:
|
|
||||||
- "v*"
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
linux-intel:
|
|
||||||
name: Linux Build
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: 1.24
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: Install cross toolchain
|
|
||||||
run: |
|
|
||||||
apt-get update
|
|
||||||
apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
|
|
||||||
|
|
||||||
- name: Build (amd64)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go install -static -arch amd64 -dlgo
|
|
||||||
|
|
||||||
- name: Create/upload archive (amd64)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
|
|
||||||
rm -f build/bin/*
|
|
||||||
env:
|
|
||||||
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
|
||||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
|
||||||
|
|
||||||
- name: Build (386)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go install -static -arch 386 -dlgo
|
|
||||||
|
|
||||||
- name: Create/upload archive (386)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
|
|
||||||
rm -f build/bin/*
|
|
||||||
env:
|
|
||||||
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
|
||||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
|
||||||
|
|
||||||
linux-arm:
|
|
||||||
name: Linux Build (arm)
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: 1.24
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: Install cross toolchain
|
|
||||||
run: |
|
|
||||||
apt-get update
|
|
||||||
apt-get -yq --no-install-suggests --no-install-recommends install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
|
|
||||||
ln -s /usr/include/asm-generic /usr/include/asm
|
|
||||||
|
|
||||||
- name: Build (arm64)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go install -static -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
|
|
||||||
|
|
||||||
- name: Create/upload archive (arm64)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
|
|
||||||
rm -fr build/bin/*
|
|
||||||
env:
|
|
||||||
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
|
||||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
|
||||||
|
|
||||||
- name: Run build (arm5)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
|
|
||||||
env:
|
|
||||||
GOARM: "5"
|
|
||||||
|
|
||||||
- name: Create/upload archive (arm5)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
|
|
||||||
env:
|
|
||||||
GOARM: "5"
|
|
||||||
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
|
||||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
|
||||||
|
|
||||||
- name: Run build (arm6)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
|
|
||||||
env:
|
|
||||||
GOARM: "6"
|
|
||||||
|
|
||||||
- name: Create/upload archive (arm6)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
|
|
||||||
rm -fr build/bin/*
|
|
||||||
env:
|
|
||||||
GOARM: "6"
|
|
||||||
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
|
||||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
|
||||||
|
|
||||||
- name: Run build (arm7)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go install -static -dlgo -arch arm -cc arm-linux-gnueabi-gcc
|
|
||||||
env:
|
|
||||||
GOARM: "7"
|
|
||||||
|
|
||||||
- name: Create/upload archive (arm7)
|
|
||||||
run: |
|
|
||||||
go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
|
|
||||||
rm -fr build/bin/*
|
|
||||||
env:
|
|
||||||
GOARM: "7"
|
|
||||||
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
|
||||||
AZURE_BLOBSTORE_TOKEN: ${{ secrets.AZURE_BLOBSTORE_TOKEN }}
|
|
||||||
|
|
||||||
windows:
|
|
||||||
name: Windows Build
|
|
||||||
runs-on: "win-11"
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: 1.24
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
# Note: gcc.exe only works properly if the corresponding bin/ directory is
|
|
||||||
# contained in PATH.
|
|
||||||
|
|
||||||
- name: "Build (amd64)"
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
set PATH=%GETH_MINGW%\bin;%PATH%
|
|
||||||
go run build/ci.go install -dlgo -arch amd64 -cc %GETH_MINGW%\bin\gcc.exe
|
|
||||||
env:
|
|
||||||
GETH_MINGW: 'C:\msys64\mingw64'
|
|
||||||
|
|
||||||
- name: "Build (386)"
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
set PATH=%GETH_MINGW%\bin;%PATH%
|
|
||||||
go run build/ci.go install -dlgo -arch 386 -cc %GETH_MINGW%\bin\gcc.exe
|
|
||||||
env:
|
|
||||||
GETH_MINGW: 'C:\msys64\mingw32'
|
|
||||||
|
|
||||||
docker:
|
|
||||||
name: Docker Image
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v4
|
|
||||||
|
|
||||||
- name: Set up QEMU
|
|
||||||
uses: docker/setup-qemu-action@v3
|
|
||||||
|
|
||||||
- name: Set up Docker Buildx
|
|
||||||
uses: docker/setup-buildx-action@v3
|
|
||||||
|
|
||||||
- name: Set up Go
|
|
||||||
uses: actions/setup-go@v5
|
|
||||||
with:
|
|
||||||
go-version: 1.24
|
|
||||||
cache: false
|
|
||||||
|
|
||||||
- name: Run docker build
|
|
||||||
env:
|
|
||||||
DOCKER_HUB_USERNAME: ${{ secrets.DOCKER_HUB_USERNAME }}
|
|
||||||
DOCKER_HUB_PASSWORD: ${{ secrets.DOCKER_HUB_PASSWORD }}
|
|
||||||
run: |
|
|
||||||
go run build/ci.go dockerx -platform linux/amd64,linux/arm64,linux/riscv64 -upload
|
|
||||||
31
.github/CODEOWNERS
vendored
31
.github/CODEOWNERS
vendored
|
|
@ -1,33 +1,4 @@
|
||||||
# Lines starting with '#' are comments.
|
# Lines starting with '#' are comments.
|
||||||
# Each line is a file pattern followed by one or more owners.
|
# Each line is a file pattern followed by one or more owners.
|
||||||
|
|
||||||
accounts/usbwallet/ @gballet
|
* @calbera
|
||||||
accounts/scwallet/ @gballet
|
|
||||||
accounts/abi/ @gballet @MariusVanDerWijden
|
|
||||||
beacon/engine/ @MariusVanDerWijden @lightclient @fjl
|
|
||||||
beacon/light/ @zsfelfoldi
|
|
||||||
beacon/merkle/ @zsfelfoldi
|
|
||||||
beacon/types/ @zsfelfoldi @fjl
|
|
||||||
beacon/params/ @zsfelfoldi @fjl
|
|
||||||
cmd/evm/ @MariusVanDerWijden @lightclient
|
|
||||||
core/state/ @rjl493456442
|
|
||||||
crypto/ @gballet @jwasinger @fjl
|
|
||||||
core/ @rjl493456442
|
|
||||||
eth/ @rjl493456442
|
|
||||||
eth/catalyst/ @MariusVanDerWijden @lightclient @fjl @jwasinger
|
|
||||||
eth/tracers/ @s1na
|
|
||||||
ethclient/ @fjl
|
|
||||||
ethdb/ @rjl493456442
|
|
||||||
event/ @fjl
|
|
||||||
trie/ @rjl493456442 @gballet
|
|
||||||
triedb/ @rjl493456442
|
|
||||||
core/tracing/ @s1na
|
|
||||||
graphql/ @s1na
|
|
||||||
internal/ethapi/ @fjl @s1na @lightclient
|
|
||||||
internal/era/ @lightclient
|
|
||||||
miner/ @MariusVanDerWijden @fjl @rjl493456442
|
|
||||||
node/ @fjl
|
|
||||||
p2p/ @fjl @zsfelfoldi
|
|
||||||
rlp/ @fjl
|
|
||||||
params/ @fjl @gballet @rjl493456442 @zsfelfoldi
|
|
||||||
rpc/ @fjl
|
|
||||||
|
|
|
||||||
2
.github/CONTRIBUTING.md
vendored
2
.github/CONTRIBUTING.md
vendored
|
|
@ -21,7 +21,7 @@ Please make sure your contributions adhere to our coding guidelines:
|
||||||
(i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
(i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
|
||||||
* Code must be documented adhering to the official Go
|
* Code must be documented adhering to the official Go
|
||||||
[commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
[commentary](https://golang.org/doc/effective_go.html#commentary) guidelines.
|
||||||
* Pull requests need to be based on and opened against the `master` branch.
|
* Pull requests need to be based on and opened against the `main` branch.
|
||||||
* Commit messages should be prefixed with the package(s) they modify.
|
* Commit messages should be prefixed with the package(s) they modify.
|
||||||
* E.g. "eth, rpc: make trace configs optional"
|
* E.g. "eth, rpc: make trace configs optional"
|
||||||
|
|
||||||
|
|
|
||||||
11
.github/dependabot.yml
vendored
Normal file
11
.github/dependabot.yml
vendored
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
# To get started with Dependabot version updates, you'll need to specify which
|
||||||
|
# package ecosystems to update and where the package manifests are located.
|
||||||
|
# Please see the documentation for all configuration options:
|
||||||
|
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||||
|
|
||||||
|
version: 2
|
||||||
|
updates:
|
||||||
|
- package-ecosystem: "gomod" # See documentation for possible values
|
||||||
|
directory: "/" # Location of package manifests
|
||||||
|
schedule:
|
||||||
|
interval: "weekly"
|
||||||
BIN
.github/meta/bera-geth.png
vendored
Normal file
BIN
.github/meta/bera-geth.png
vendored
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
2
.github/no-response.yml
vendored
2
.github/no-response.yml
vendored
|
|
@ -1,5 +1,5 @@
|
||||||
# Number of days of inactivity before an Issue is closed for lack of response
|
# Number of days of inactivity before an Issue is closed for lack of response
|
||||||
daysUntilClose: 30
|
daysUntilClose: 366
|
||||||
# Label requiring a response
|
# Label requiring a response
|
||||||
responseRequiredLabel: "need:more-information"
|
responseRequiredLabel: "need:more-information"
|
||||||
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
|
# Comment to post when closing an Issue for lack of response. Set to `false` to disable
|
||||||
|
|
|
||||||
106
.github/workflows/BACKPORT_README.md
vendored
Normal file
106
.github/workflows/BACKPORT_README.md
vendored
Normal file
|
|
@ -0,0 +1,106 @@
|
||||||
|
# Backport Workflow Documentation
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
This repository uses an automated backport workflow to cherry-pick merged pull requests from the `main` branch to release branches. The workflow is powered by the [korthout/backport-action](https://github.com/marketplace/actions/backport-merged-pull-requests-to-selected-branches).
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
### Automatic Backporting via Labels
|
||||||
|
|
||||||
|
1. **Add a backport label** to your pull request before or after merging:
|
||||||
|
- Label format: `backport/{version}`
|
||||||
|
- Examples: `backport/v1.0.0`, `backport/v2.3.1`, `backport/1.0`
|
||||||
|
|
||||||
|
2. **When the PR is merged to main**, the workflow automatically:
|
||||||
|
- Detects all `backport/*` labels
|
||||||
|
- Transforms them to target `release/{version}` branches
|
||||||
|
- Creates new pull requests with cherry-picked commits to each target branch
|
||||||
|
|
||||||
|
3. **Target branches** must exist:
|
||||||
|
- For label `backport/v1.0.0` → targets branch `release/v1.0.0`
|
||||||
|
- For label `backport/2.0` → targets branch `release/2.0`
|
||||||
|
- The release branch must already exist in the repository
|
||||||
|
|
||||||
|
### Manual Backporting via Comments
|
||||||
|
|
||||||
|
You can also trigger backports manually by commenting on a merged PR:
|
||||||
|
- Comment `/backport` on any merged pull request
|
||||||
|
- The workflow will look for backport labels and create the appropriate PRs
|
||||||
|
|
||||||
|
## Example Workflow
|
||||||
|
|
||||||
|
1. Create a pull request to `main` with your changes
|
||||||
|
2. Add label: `backport/v1.2.3`
|
||||||
|
3. Get the PR reviewed and merged
|
||||||
|
4. The bot automatically:
|
||||||
|
- Creates a new branch: `backport-{PR-number}-to-release-v1.2.3`
|
||||||
|
- Cherry-picks the commits from your merged PR
|
||||||
|
- Opens a new PR from that branch to `release/v1.2.3`
|
||||||
|
- Adds labels: `backport`, `automated`
|
||||||
|
- Assigns the original PR author
|
||||||
|
|
||||||
|
## Handling Multiple Backports
|
||||||
|
|
||||||
|
You can backport to multiple release branches by adding multiple labels:
|
||||||
|
- `backport/v1.0.0` - backports to `release/v1.0.0`
|
||||||
|
- `backport/v2.0.0` - backports to `release/v2.0.0`
|
||||||
|
- `backport/v3.0.0` - backports to `release/v3.0.0`
|
||||||
|
|
||||||
|
Each label will create a separate backport PR.
|
||||||
|
|
||||||
|
## Conflict Resolution
|
||||||
|
|
||||||
|
When cherry-pick conflicts occur:
|
||||||
|
1. The bot creates a **draft PR** with the conflicts committed
|
||||||
|
2. The draft PR includes instructions on how to resolve the conflicts
|
||||||
|
3. You need to:
|
||||||
|
- Check out the backport branch locally
|
||||||
|
- Resolve the conflicts
|
||||||
|
- Push the resolved changes
|
||||||
|
- Mark the PR as ready for review
|
||||||
|
|
||||||
|
## Backport PR Format
|
||||||
|
|
||||||
|
Backport PRs are created with:
|
||||||
|
- **Title**: `[Backport release/{version}] {original PR title}`
|
||||||
|
- **Description**: Includes original PR information, author, and description
|
||||||
|
- **Labels**: `backport`, `automated`
|
||||||
|
- **Assignee**: Original PR author
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
For the workflow to function correctly:
|
||||||
|
1. Release branches must follow the naming pattern: `release/{version}`
|
||||||
|
2. The workflow must have write permissions (already configured)
|
||||||
|
3. Release branches must exist before attempting to backport
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### Backport not triggering
|
||||||
|
- Ensure the PR is merged to `main` (not just closed)
|
||||||
|
- Verify the label format is exactly `backport/{version}`
|
||||||
|
- Check that the target `release/{version}` branch exists
|
||||||
|
|
||||||
|
### Conflicts in backport
|
||||||
|
- The bot will create a draft PR with conflicts
|
||||||
|
- Follow the instructions in the PR to resolve conflicts locally
|
||||||
|
|
||||||
|
### Multiple commits or merge commits
|
||||||
|
- The workflow is configured to skip merge commits
|
||||||
|
- Only non-merge commits will be cherry-picked
|
||||||
|
- If you need merge commits, update the `merge_commits` setting in the workflow
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
The workflow is defined in `.github/workflows/backport.yml`. Key settings:
|
||||||
|
- **Label pattern**: `backport/{version}`
|
||||||
|
- **Target branch pattern**: `release/{version}`
|
||||||
|
- **Conflict strategy**: Create draft PRs with conflicts
|
||||||
|
- **Merge commits**: Skipped (only cherry-picks non-merge commits)
|
||||||
|
|
||||||
|
## Security
|
||||||
|
|
||||||
|
- The workflow uses `GITHUB_TOKEN` for authentication
|
||||||
|
- Runs on `pull_request_target` to handle forks securely
|
||||||
|
- Only triggers on merged PRs to prevent abuse
|
||||||
140
.github/workflows/RELEASE_SIGNING.md
vendored
Normal file
140
.github/workflows/RELEASE_SIGNING.md
vendored
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
# Release Signing Setup
|
||||||
|
|
||||||
|
This document explains how release signing is implemented for bera-geth, including PGP signing for binaries and Cosign signing for Docker images.
|
||||||
|
|
||||||
|
## Overview
|
||||||
|
|
||||||
|
The bera-geth release process includes cryptographic signing for all release artifacts:
|
||||||
|
- **Binary releases**: Signed with PGP/GPG
|
||||||
|
- **Docker images**: Signed with Cosign (keyless signing via OIDC)
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
### Prerequisites for Release Managers
|
||||||
|
|
||||||
|
#### PGP Signing Setup
|
||||||
|
|
||||||
|
1. **Create the `LINUX_SIGNING_KEY` secret in GitHub**:
|
||||||
|
```bash
|
||||||
|
# Export your PGP private key
|
||||||
|
gpg --export-secret-keys --armor YOUR_KEY_ID > private.key
|
||||||
|
|
||||||
|
# Base64 encode it
|
||||||
|
cat private.key | base64 -w 0
|
||||||
|
|
||||||
|
# Copy the output and add it as the LINUX_SIGNING_KEY secret in GitHub repository settings
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Ensure the public key matches**: The public key at `.github/workflows/release.asc` should correspond to the private key used for signing.
|
||||||
|
|
||||||
|
#### Cosign Setup
|
||||||
|
|
||||||
|
Cosign uses keyless signing (no secret required). The workflow uses GitHub's OIDC provider to sign images, which means:
|
||||||
|
- No private keys to manage
|
||||||
|
- Signatures are tied to the GitHub Actions workflow identity
|
||||||
|
- Full transparency via Rekor transparency log
|
||||||
|
|
||||||
|
## Release Process
|
||||||
|
|
||||||
|
### Triggering a Release
|
||||||
|
|
||||||
|
Releases are triggered by:
|
||||||
|
- Pushing a tag matching `v1.*` (e.g., `v1.0.0`, `v1.0.0-rc1`)
|
||||||
|
- The workflow will automatically create a draft release with all signed artifacts
|
||||||
|
|
||||||
|
### What Gets Signed
|
||||||
|
|
||||||
|
1. **Binary Archives**:
|
||||||
|
- `bera-geth-linux-amd64-*.tar.gz` → `bera-geth-linux-amd64-*.tar.gz.asc`
|
||||||
|
- `bera-geth-linux-arm64-*.tar.gz` → `bera-geth-linux-arm64-*.tar.gz.asc`
|
||||||
|
- `bera-geth-alltools-linux-amd64-*.tar.gz` → `bera-geth-alltools-linux-amd64-*.tar.gz.asc`
|
||||||
|
- `bera-geth-alltools-linux-arm64-*.tar.gz` → `bera-geth-alltools-linux-arm64-*.tar.gz.asc`
|
||||||
|
|
||||||
|
2. **Docker Images**:
|
||||||
|
- Multi-arch images at `ghcr.io/berachain/bera-geth:VERSION`
|
||||||
|
- Signed with Cosign using keyless signing
|
||||||
|
|
||||||
|
## Verification Instructions
|
||||||
|
|
||||||
|
### Verifying Binary Signatures
|
||||||
|
|
||||||
|
Users can verify the PGP signatures of release binaries:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Download and import the public key
|
||||||
|
curl -sSL https://raw.githubusercontent.com/berachain/bera-geth/main/.github/workflows/release.asc | gpg --import
|
||||||
|
|
||||||
|
# Download a release archive and its signature
|
||||||
|
wget https://github.com/berachain/bera-geth/releases/download/v1.0.0/bera-geth-linux-amd64-v1.0.0.tar.gz
|
||||||
|
wget https://github.com/berachain/bera-geth/releases/download/v1.0.0/bera-geth-linux-amd64-v1.0.0.tar.gz.asc
|
||||||
|
|
||||||
|
# Verify the signature
|
||||||
|
gpg --verify bera-geth-linux-amd64-v1.0.0.tar.gz.asc bera-geth-linux-amd64-v1.0.0.tar.gz
|
||||||
|
```
|
||||||
|
|
||||||
|
Expected output:
|
||||||
|
```
|
||||||
|
gpg: Signature made [date] using RSA key ID [key-id]
|
||||||
|
gpg: Good signature from "bera-geth-linux-signing-key"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Verifying Docker Images
|
||||||
|
|
||||||
|
Docker images are signed with Cosign and can be verified:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Install cosign if not already installed
|
||||||
|
brew install cosign # macOS
|
||||||
|
# or see https://docs.sigstore.dev/cosign/installation/
|
||||||
|
|
||||||
|
# Verify a specific version
|
||||||
|
cosign verify ghcr.io/berachain/bera-geth:v1.0.0
|
||||||
|
|
||||||
|
# Verify the latest image
|
||||||
|
cosign verify ghcr.io/berachain/bera-geth:latest
|
||||||
|
```
|
||||||
|
|
||||||
|
The verification will show:
|
||||||
|
- The GitHub Actions workflow that created the image
|
||||||
|
- The commit SHA
|
||||||
|
- The OIDC issuer (GitHub)
|
||||||
|
|
||||||
|
## Security Considerations
|
||||||
|
|
||||||
|
1. **PGP Key Security**:
|
||||||
|
- The PGP private key should be kept secure and only accessible to authorized release managers
|
||||||
|
- Regularly rotate keys and update the public key in the repository
|
||||||
|
- Use a strong passphrase for the private key
|
||||||
|
|
||||||
|
2. **Cosign Keyless Signing**:
|
||||||
|
- Signatures are tied to the GitHub Actions workflow identity
|
||||||
|
- Verification includes checking the workflow that signed the image
|
||||||
|
- All signatures are recorded in the Rekor transparency log
|
||||||
|
|
||||||
|
3. **Best Practices**:
|
||||||
|
- Always verify signatures before using release artifacts in production
|
||||||
|
- Check that the signing workflow matches the official repository
|
||||||
|
- Monitor the repository for any changes to signing keys or workflows
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### PGP Signing Issues
|
||||||
|
|
||||||
|
If PGP signing fails:
|
||||||
|
1. Check that the `LINUX_SIGNING_KEY` secret is properly set
|
||||||
|
2. Verify the key hasn't expired: `gpg --list-secret-keys`
|
||||||
|
3. Ensure the base64 encoding was done correctly
|
||||||
|
|
||||||
|
### Cosign Signing Issues
|
||||||
|
|
||||||
|
If Cosign signing fails:
|
||||||
|
1. Ensure the workflow has `id-token: write` permission
|
||||||
|
2. Check that the Docker image was successfully pushed before signing
|
||||||
|
3. Verify the image tag/digest is correct
|
||||||
|
|
||||||
|
### Release Draft Issues
|
||||||
|
|
||||||
|
If the release draft fails:
|
||||||
|
1. Ensure all artifacts were successfully uploaded
|
||||||
|
2. Check that the tag follows the correct format (`v1.*`)
|
||||||
|
3. Verify the workflow has `contents: write` permission
|
||||||
137
.github/workflows/backport.yml
vendored
Normal file
137
.github/workflows/backport.yml
vendored
Normal file
|
|
@ -0,0 +1,137 @@
|
||||||
|
name: Backport merged pull request
|
||||||
|
on:
|
||||||
|
pull_request_target:
|
||||||
|
types: [closed]
|
||||||
|
issue_comment:
|
||||||
|
types: [created]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write # Required to push branches
|
||||||
|
pull-requests: write # Required to create pull requests
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
backport:
|
||||||
|
name: Backport pull request
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
# Only run when:
|
||||||
|
# - A pull request to main is merged (not just closed)
|
||||||
|
# - OR a comment starting with '/backport' is created by someone other than the bot
|
||||||
|
if: >
|
||||||
|
(
|
||||||
|
github.event_name == 'pull_request_target' &&
|
||||||
|
github.event.pull_request.merged &&
|
||||||
|
github.event.pull_request.base.ref == 'main'
|
||||||
|
) || (
|
||||||
|
github.event_name == 'issue_comment' &&
|
||||||
|
github.event.issue.pull_request &&
|
||||||
|
github.event.comment.user.id != 97796249 &&
|
||||||
|
startsWith(github.event.comment.body, '/backport')
|
||||||
|
)
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- name: Checkout repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
# Fetch all history for all branches
|
||||||
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Extract backport targets from labels
|
||||||
|
id: extract-targets
|
||||||
|
uses: actions/github-script@v7
|
||||||
|
with:
|
||||||
|
script: |
|
||||||
|
const labels = context.payload.pull_request?.labels || [];
|
||||||
|
const backportLabels = labels
|
||||||
|
.map(label => label.name)
|
||||||
|
.filter(name => name.startsWith('backport/'))
|
||||||
|
.map(name => {
|
||||||
|
// Extract version from "backport/{version}"
|
||||||
|
const version = name.replace('backport/', '');
|
||||||
|
// Transform to "release/{version}"
|
||||||
|
return `release/${version}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (backportLabels.length > 0) {
|
||||||
|
console.log(`Found backport targets: ${backportLabels.join(', ')}`);
|
||||||
|
// Join with spaces as the backport action expects
|
||||||
|
core.setOutput('targets', backportLabels.join(' '));
|
||||||
|
core.setOutput('has-targets', 'true');
|
||||||
|
} else {
|
||||||
|
console.log('No backport labels found');
|
||||||
|
core.setOutput('has-targets', 'false');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also output the original labels for the action
|
||||||
|
const originalLabels = labels
|
||||||
|
.map(label => label.name)
|
||||||
|
.filter(name => name.startsWith('backport/'))
|
||||||
|
.map(name => {
|
||||||
|
// Transform "backport/{version}" to "backport release/{version}"
|
||||||
|
const version = name.replace('backport/', '');
|
||||||
|
return `backport release/${version}`;
|
||||||
|
})
|
||||||
|
.join(',');
|
||||||
|
|
||||||
|
core.setOutput('transformed-labels', originalLabels);
|
||||||
|
|
||||||
|
- name: Create backport pull requests
|
||||||
|
if: steps.extract-targets.outputs.has-targets == 'true'
|
||||||
|
uses: korthout/backport-action@v3
|
||||||
|
with:
|
||||||
|
# GitHub token for authentication
|
||||||
|
github_token: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
# Directly specify target branches extracted from labels
|
||||||
|
target_branches: ${{ steps.extract-targets.outputs.targets }}
|
||||||
|
|
||||||
|
# Disable label pattern matching since we're using target_branches
|
||||||
|
label_pattern: ""
|
||||||
|
|
||||||
|
# Branch name template for the backport branch
|
||||||
|
# This creates branches like: backport-123-to-release-v1.0.0
|
||||||
|
branch_name: "backport-${pull_number}-to-${target_branch}"
|
||||||
|
|
||||||
|
# Title template for the backport PR
|
||||||
|
pull_title: "${pull_title}"
|
||||||
|
|
||||||
|
# Description template for the backport PR
|
||||||
|
pull_description: |
|
||||||
|
# Backport to ${target_branch}
|
||||||
|
|
||||||
|
This is an automatic backport of pull request #${pull_number} to ${target_branch}.
|
||||||
|
|
||||||
|
## Original PR Information
|
||||||
|
- **Title**: ${pull_title}
|
||||||
|
- **Author**: @${pull_author}
|
||||||
|
- **Original PR**: #${pull_number}
|
||||||
|
|
||||||
|
## Original Description
|
||||||
|
${pull_description}
|
||||||
|
|
||||||
|
## Related Issues
|
||||||
|
${issue_refs}
|
||||||
|
|
||||||
|
---
|
||||||
|
*This pull request was created automatically by the backport action.*
|
||||||
|
|
||||||
|
# Labels to add to the backport PR
|
||||||
|
add_labels: "automated"
|
||||||
|
|
||||||
|
# Add original PR author as assignee
|
||||||
|
add_author_as_assignee: true
|
||||||
|
|
||||||
|
# Enable experimental features (includes conflict handling)
|
||||||
|
experimental: |
|
||||||
|
{
|
||||||
|
"detect_merge_method": true
|
||||||
|
}
|
||||||
|
|
||||||
|
# Cherry-picking strategy
|
||||||
|
# Options: "auto", "recursive", "ort"
|
||||||
|
cherry_picking: "auto"
|
||||||
|
|
||||||
|
# How to handle merge commits
|
||||||
|
# Options: "fail" or "skip"
|
||||||
|
# Using skip to handle PRs that were kept in sync with base via merge commits
|
||||||
|
merge_commits: "skip"
|
||||||
|
|
@ -1,16 +1,16 @@
|
||||||
|
name: CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches: [ main, "release/*" ]
|
||||||
- master
|
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches: [ main ]
|
||||||
- master
|
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
lint:
|
lint:
|
||||||
name: Lint
|
name: Lint
|
||||||
runs-on: self-hosted-ghr
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
|
@ -25,7 +25,7 @@ jobs:
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: 1.25
|
go-version: 1.24
|
||||||
cache: false
|
cache: false
|
||||||
|
|
||||||
- name: Run linters
|
- name: Run linters
|
||||||
|
|
@ -34,15 +34,9 @@ jobs:
|
||||||
go run build/ci.go check_generate
|
go run build/ci.go check_generate
|
||||||
go run build/ci.go check_baddeps
|
go run build/ci.go check_baddeps
|
||||||
|
|
||||||
test:
|
tests:
|
||||||
name: Test
|
name: Tests
|
||||||
needs: lint
|
runs-on: ubuntu-latest
|
||||||
runs-on: self-hosted-ghr
|
|
||||||
strategy:
|
|
||||||
matrix:
|
|
||||||
go:
|
|
||||||
- '1.25'
|
|
||||||
- '1.24'
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
|
|
@ -51,8 +45,8 @@ jobs:
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v5
|
uses: actions/setup-go@v5
|
||||||
with:
|
with:
|
||||||
go-version: ${{ matrix.go }}
|
go-version: 1.24.0
|
||||||
cache: false
|
cache: false
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: go test ./...
|
run: go test -short ./...
|
||||||
118
.github/workflows/docker.yml
vendored
Normal file
118
.github/workflows/docker.yml
vendored
Normal file
|
|
@ -0,0 +1,118 @@
|
||||||
|
name: Docker
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v1.*"
|
||||||
|
branches:
|
||||||
|
- "main"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker-build:
|
||||||
|
name: Docker Image
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v3
|
||||||
|
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: 1.24
|
||||||
|
cache: false
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Build and push multi-arch images to GHCR
|
||||||
|
run: |
|
||||||
|
go run build/ci.go dockerx -platform linux/amd64,linux/arm64 -hub ghcr.io/berachain/bera-geth -upload
|
||||||
|
|
||||||
|
- name: Get image digest and version
|
||||||
|
id: image_info
|
||||||
|
run: |
|
||||||
|
# Extract version information
|
||||||
|
VERSION=""
|
||||||
|
if [[ "${{ github.ref }}" == refs/tags/* ]]; then
|
||||||
|
VERSION="${{ github.ref_name }}"
|
||||||
|
elif [[ "${{ github.ref }}" == refs/heads/main ]]; then
|
||||||
|
VERSION="latest"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$VERSION" ]; then
|
||||||
|
echo "Error: Could not determine version from ref '${{ github.ref }}'"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "VERSION=${VERSION}" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
# Get the digest of the pushed manifest list (top-level manifest list digest)
|
||||||
|
# Avoid relying on template fields (which vary across buildx versions) and avoid -e exit on failure
|
||||||
|
INSPECT_OUTPUT=$(docker buildx imagetools inspect ghcr.io/berachain/bera-geth:${VERSION} || true)
|
||||||
|
DIGEST=$(printf "%s\n" "$INSPECT_OUTPUT" | awk '/^Digest:/ {print $2; exit}')
|
||||||
|
if [ -z "$DIGEST" ]; then
|
||||||
|
echo "Error: Could not determine image digest for ghcr.io/berachain/bera-geth:${VERSION}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "DIGEST=${DIGEST}" >> $GITHUB_OUTPUT
|
||||||
|
outputs:
|
||||||
|
VERSION: ${{ steps.image_info.outputs.VERSION }}
|
||||||
|
DIGEST: ${{ steps.image_info.outputs.DIGEST }}
|
||||||
|
|
||||||
|
docker-signatures:
|
||||||
|
name: Docker Signatures
|
||||||
|
needs: [docker-build]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.docker-build.outputs.VERSION }}
|
||||||
|
DIGEST: ${{ needs.docker-build.outputs.DIGEST }}
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
packages: write
|
||||||
|
attestations: write
|
||||||
|
id-token: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Login to GitHub Container Registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: ghcr.io
|
||||||
|
username: ${{ github.actor }}
|
||||||
|
password: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|
||||||
|
- name: Install Cosign
|
||||||
|
uses: sigstore/cosign-installer@v3
|
||||||
|
|
||||||
|
- name: Sign Docker images with Cosign
|
||||||
|
env:
|
||||||
|
COSIGN_EXPERIMENTAL: true
|
||||||
|
COSIGN_YES: "true"
|
||||||
|
run: |
|
||||||
|
# Sign the tagged version if it exists
|
||||||
|
if [ -n "${{ env.VERSION }}" ]; then
|
||||||
|
cosign sign --yes ghcr.io/berachain/bera-geth:${{ env.VERSION }}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Sign the multi-arch manifest by digest
|
||||||
|
if [ -n "${{ env.DIGEST }}" ]; then
|
||||||
|
cosign sign --yes ghcr.io/berachain/bera-geth@${{ env.DIGEST }}
|
||||||
|
else
|
||||||
|
echo "Error: DIGEST is empty. Skipping digest signing."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
52
.github/workflows/release.asc
vendored
Normal file
52
.github/workflows/release.asc
vendored
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
-----BEGIN PGP PUBLIC KEY BLOCK-----
|
||||||
|
|
||||||
|
mQINBGiFS/oBEAC8b3nWhb1bFjOJhz4tkFN8ku5J6ElWj0wCzM6l2WZPhcU/VBMd
|
||||||
|
0/iIDC2ZtFp2a11N9xpT1+ct5pYaUwLUor4Ms9p+mi7Ct3wGKgcOngGgfAqTdm/1
|
||||||
|
V04e9Q6ATPWimaC6vHEMHXYR7NmQuqazluwIAai6RfKm6gXVfgVHdOFC+Chr7Pk6
|
||||||
|
QRn3fXXnFHnLakQwFz12q0bq6UemKYfPEHl28ObKFXJ0fG8bVKlbghxdJ6UZWbF4
|
||||||
|
n+gzeFHxEdgvChqa/GBt9Rqpw55b/lrEZ4hp9q9RYcvTZ+q5RJjA+KM7zQMehwan
|
||||||
|
8I3Uyo9cNI+6NDp/UBQRSXP5dqMp4CjMxlBTuDHyaB1SSuxNThYkMmsEZIRppRPu
|
||||||
|
g7znwLtErD4Pptzzo1Am7i614t2UtKf4FAVrUPJOeaShu600W7BFeqZvkrKJMbpu
|
||||||
|
+k/Z+EAQR4hQS0FqpGuB4xlIoR3HuEdOaL7aQ04ZjDlEzS12KlZCmKT3rtCWz7Zg
|
||||||
|
kAw89iPkDjzGoO+pNtvU2WA8VroCiGg4BJbuSeIi89KU286IkrSUiB0QZcLicbdX
|
||||||
|
k8ro6Ns+prf0XeWlXn3g5NLpRc1UfVvHB3gRo7L7dCCxHdnPZke0SYLlkY/B6MIL
|
||||||
|
FE4+SnJV5sDCAoSlcYVqAChqN3Vh1hCnsXpK/2HUrX6HDPWOZNSVYuqTXwARAQAB
|
||||||
|
tCpiZXJhLWdldGggcmVsZWFzZXIgPGNhbGJlcmFAYmVyYWNoYWluLmNvbT6JAlEE
|
||||||
|
EwEIADsWIQTN/ECePFkfXNo+9Agx95ZXOzmsaAUCaIVL+gIbAwULCQgHAgIiAgYV
|
||||||
|
CgkICwIEFgIDAQIeBwIXgAAKCRAx95ZXOzmsaKKWEACd+pD8proofzZgwL9b+3ql
|
||||||
|
rwwuDfjkORkKW0+ve5Y10ydu/VsWAqGRQIPBaCyaCFlziFqPSnWQA5NhK7rfytVt
|
||||||
|
2pOTD2KsbBfYtk7wWrgzG78xgOa9SCsO8p908QytsunWUgBK/zFgHH2sVYNjWlPt
|
||||||
|
nU92z7nBdq7NYiW8S2WrsdZgXvVyVitymaVyLUnnyXCezYqZ81+AuIUmKpcz9aLv
|
||||||
|
VQBL3Z2CNt8IWR1xRg0dkVFEqI7C+KoA+lQXIij0gapUOf4039YUIj7XgvIrbDXr
|
||||||
|
juzEhmvWw8kPLC5ZX60whX+QYewYnBCckKeYK8HwUJgcxN6OQ5RsPbt60PK9+Hdb
|
||||||
|
E1D8/Sl2srud6erV4Ji4/TFDBx6o08KqBiHbU1PvEov7qfnQLQ79lhlOiIaNTAzy
|
||||||
|
qIRyiM0NSM4Meq+bVT+2bYn83fgMzI9YOa8kqoCY0wZcbK48/S8YJ3mq3zShoQEm
|
||||||
|
tSD/8EwNjRuoaddwTQdcRnhu45QxkQmg1blwnDr9wp4pGI6xeWSUEzoyn9HePkN9
|
||||||
|
HjQS7Ooyh81ahqrenTO3Sy0t65/XRD1VZfFZ0FYxI0VJr32b1bdyJnlh3+2CRjTB
|
||||||
|
jTC7eRnM+rFSuK1Whv6WPgWK9nKEQa89KDJqRciGddbkjobgKfTGfhwSlCdSPkvr
|
||||||
|
Ffkkzngq5/GwzgLXosTA5rkCDQRohUv6ARAAqxG/ZODPfDXxgunrohuXiL6kdGq6
|
||||||
|
ZgI9ouOgeKSHXEeEeBE5NDmLne/kzmlo/GIDcNucieHoJ1/8rVjL7v/9/veroz3q
|
||||||
|
hHT3E5TrlkSnDR6b2588SqsxVX/OLASw7es2/aOM6Jz4Gd4IgcemZtZuLiopFGBS
|
||||||
|
CmrKqqzMA+WRkGDAkrcji1TZNNZlRlZfhF60LtsIxopKKfJ3wRy38geW84JMM2Ol
|
||||||
|
ZD8lEJr965ikHqeJdsqJkhRLp/Qp1NjM0NEbwh/24KSd2gNcrrMDoOAZSUpv3vV/
|
||||||
|
kXY4ZXJUgBY6L9g5/zbdKwiCtSw3WTJVUBlh+y2Cmgz9NG9ipnqiRXEyeuQsWfVh
|
||||||
|
mmv1XDBxPNGHzEQYGuf09fbzOomdOv8aSma2BZT+UT/ajMLN3EIO1dBioR2CwX2P
|
||||||
|
3zlxNL33aNgFNg0QPyLPlkbjYxty91fj29Cz6UKEJW8XoHJ8LWmeYIwGNc2+B7ty
|
||||||
|
NVpqG7GoWp/yxbbhXT9ISXzI/ZbHwb71wLOyG9c7ZQSaBkMLbgqLdMbdJ4sfhyrI
|
||||||
|
WYfi8HayshWwR0tVlshs2lOaNgL6UtpiC2Ni87MOGO4TeKb3R9QoCiti9hpkSmoW
|
||||||
|
SDqwMWa3VLUMZUMZUvDx3iKAZ23nA1xeB/PPLlsv9+GJDpS7j8CCzlwYKSdEIAL7
|
||||||
|
l7zvu7+eos4gJkEAEQEAAYkCNgQYAQgAIBYhBM38QJ48WR9c2j70CDH3llc7Oaxo
|
||||||
|
BQJohUv6AhsMAAoJEDH3llc7OaxoLmsQAIXXQiD5xTEcu+0JAWIfyr6bHxg1CeeQ
|
||||||
|
luWfxraTxomCsKCHu6uloMCbfA/vkw3ArkAxK4ZsLojzkwkqZIt/SJDV35tMobpv
|
||||||
|
LE32DupyjAPFkuFTCbPFKPtRP5e3aCb8n1bHq7OqaAoMhBqLFyDKeh9hduKNpQie
|
||||||
|
508IOtrdnoq3oN5z1TWNwUY88pcd3sEhpcxekWBftghVhO+EVyVUJ3fUxouH+v/M
|
||||||
|
YX33zxREIYx+OHBMlgQFEM6UWFHwn7ILWxxQaG0/CXYDadnC1IymzP0bWlhEZdpU
|
||||||
|
QG1ZE22Ymkyb2ZuyHAJqUlLMKeYiiv3eY4gXQZCbDUzU/egAXooS/OrO9QVDXswE
|
||||||
|
FlJgGuvf5QIw/aicicc6+uT5jytDewteS/fS7Jic4dPm9vAOZjhEBfnSpEjj3/jw
|
||||||
|
d5+bUu5fVSo5PfMEbwxHv9g+uR505ymqVbkK0pXhpSiZyfb3qXI02aMoegMwY/8h
|
||||||
|
sRSkt25iQ5ofk12pbzHB51pKCK1U8oHYDMB/89hpBUc1amL5M1gP1asZj34TC1y9
|
||||||
|
qhg8Qo9H0AyJY2QAc9OqBIDFhotf+q/st6YSnTkXoY0IaJgA28I5ACEJRsH6/unz
|
||||||
|
51wTAaWKaLFz3OL39GFLMkuIV/2rq5geP+u89m8dgyrZOMB/ZgpG6VA1dY9ZAf3/
|
||||||
|
3uG6ibaGc3mn
|
||||||
|
=/kse
|
||||||
|
-----END PGP PUBLIC KEY BLOCK-----
|
||||||
270
.github/workflows/release.yml
vendored
Normal file
270
.github/workflows/release.yml
vendored
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
name: Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "v1.*"
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
extract-version:
|
||||||
|
name: Extract Version
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Extract version
|
||||||
|
run: echo "VERSION=$(echo ${GITHUB_REF#refs/tags/})" >> $GITHUB_OUTPUT
|
||||||
|
id: extract_version
|
||||||
|
outputs:
|
||||||
|
VERSION: ${{ steps.extract_version.outputs.VERSION }}
|
||||||
|
|
||||||
|
linux-intel:
|
||||||
|
name: Linux Build (intel)
|
||||||
|
needs: [extract-version]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.extract-version.outputs.VERSION }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: 1.24
|
||||||
|
cache: false
|
||||||
|
|
||||||
|
- name: Install cross toolchain
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -yq --no-install-suggests --no-install-recommends install gcc-multilib
|
||||||
|
|
||||||
|
- name: Build (amd64)
|
||||||
|
run: |
|
||||||
|
go run build/ci.go install -static -arch amd64 -dlgo -git-tag="${{ env.VERSION }}"
|
||||||
|
|
||||||
|
- name: Create archive (amd64)
|
||||||
|
run: |
|
||||||
|
go run build/ci.go archive -arch amd64 -type tar -signer LINUX_SIGNING_KEY
|
||||||
|
env:
|
||||||
|
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
||||||
|
- name: Upload artifacts (amd64)
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: bera-geth-linux-amd64-archives
|
||||||
|
path: |
|
||||||
|
bera-geth-linux-amd64-*.tar.gz
|
||||||
|
bera-geth-linux-amd64-*.tar.gz.asc
|
||||||
|
bera-geth-alltools-linux-amd64-*.tar.gz
|
||||||
|
bera-geth-alltools-linux-amd64-*.tar.gz.asc
|
||||||
|
- name: Cleanup bin
|
||||||
|
run: rm -f build/bin/*
|
||||||
|
|
||||||
|
linux-arm:
|
||||||
|
name: Linux Build (arm)
|
||||||
|
needs: [extract-version]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.extract-version.outputs.VERSION }}
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v5
|
||||||
|
with:
|
||||||
|
go-version: 1.24
|
||||||
|
cache: false
|
||||||
|
|
||||||
|
- name: Install cross toolchain
|
||||||
|
run: |
|
||||||
|
sudo apt-get update
|
||||||
|
sudo apt-get -yq --no-install-suggests --no-install-recommends install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
|
||||||
|
sudo ln -s /usr/include/asm-generic /usr/include/asm
|
||||||
|
|
||||||
|
- name: Build (arm64)
|
||||||
|
run: |
|
||||||
|
go run build/ci.go install -static -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc -git-tag="${{ env.VERSION }}"
|
||||||
|
|
||||||
|
- name: Create archive (arm64)
|
||||||
|
run: |
|
||||||
|
go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY
|
||||||
|
env:
|
||||||
|
LINUX_SIGNING_KEY: ${{ secrets.LINUX_SIGNING_KEY }}
|
||||||
|
- name: Upload artifacts (arm64)
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: bera-geth-linux-arm64-archives
|
||||||
|
path: |
|
||||||
|
bera-geth-linux-arm64-*.tar.gz
|
||||||
|
bera-geth-linux-arm64-*.tar.gz.asc
|
||||||
|
bera-geth-alltools-linux-arm64-*.tar.gz
|
||||||
|
bera-geth-alltools-linux-arm64-*.tar.gz.asc
|
||||||
|
- name: Cleanup bin
|
||||||
|
run: rm -fr build/bin/*
|
||||||
|
|
||||||
|
draft-release:
|
||||||
|
name: Draft Release
|
||||||
|
needs: [extract-version, linux-intel, linux-arm]
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
env:
|
||||||
|
VERSION: ${{ needs.extract-version.outputs.VERSION }}
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
with:
|
||||||
|
fetch-depth: 0 # This is necessary for generating the changelog
|
||||||
|
|
||||||
|
- name: Download all artifacts
|
||||||
|
uses: actions/download-artifact@v4
|
||||||
|
with:
|
||||||
|
path: ./artifacts
|
||||||
|
|
||||||
|
- name: Generate full changelog
|
||||||
|
id: changelog
|
||||||
|
run: |
|
||||||
|
echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT
|
||||||
|
echo "$(git log --pretty=format:"- %s" $(git describe --tags --abbrev=0 ${{ env.VERSION }}^)..${{ env.VERSION }})" >> $GITHUB_OUTPUT
|
||||||
|
echo "EOF" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- name: Create release draft
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
run: |
|
||||||
|
# Debug: Show what was downloaded
|
||||||
|
echo "Contents of artifacts directory:"
|
||||||
|
ls -la ./artifacts/ || echo "Artifacts directory not found"
|
||||||
|
|
||||||
|
# Move all artifacts to current directory
|
||||||
|
if [ -d "./artifacts" ]; then
|
||||||
|
find ./artifacts -name "*.tar.gz" -exec mv {} . \;
|
||||||
|
find ./artifacts -name "*.tar.gz.asc" -exec mv {} . \;
|
||||||
|
else
|
||||||
|
echo "Warning: No artifacts directory found"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# List available files for debugging
|
||||||
|
echo "Available files:"
|
||||||
|
ls -la *.tar.gz *.tar.gz.asc 2>/dev/null || echo "No archive files found"
|
||||||
|
|
||||||
|
# Get actual archive names
|
||||||
|
GETH_AMD64=$(ls bera-geth-linux-amd64-*.tar.gz 2>/dev/null | grep -v alltools | head -1)
|
||||||
|
GETH_ARM64=$(ls bera-geth-linux-arm64-*.tar.gz 2>/dev/null | grep -v alltools | head -1)
|
||||||
|
GETH_ALLTOOLS_AMD64=$(ls bera-geth-alltools-linux-amd64-*.tar.gz 2>/dev/null | head -1)
|
||||||
|
GETH_ALLTOOLS_ARM64=$(ls bera-geth-alltools-linux-arm64-*.tar.gz 2>/dev/null | head -1)
|
||||||
|
|
||||||
|
echo "Found archives:"
|
||||||
|
echo " AMD64: ${GETH_AMD64:-NOT FOUND}"
|
||||||
|
echo " ARM64: ${GETH_ARM64:-NOT FOUND}"
|
||||||
|
echo " Alltools AMD64: ${GETH_ALLTOOLS_AMD64:-NOT FOUND}"
|
||||||
|
echo " Alltools ARM64: ${GETH_ALLTOOLS_ARM64:-NOT FOUND}"
|
||||||
|
|
||||||
|
# For tag builds, use the actual tag
|
||||||
|
RELEASE_TAG="${{ env.VERSION }}"
|
||||||
|
echo "Release tag: $RELEASE_TAG"
|
||||||
|
echo "GitHub ref: ${{ github.ref }}"
|
||||||
|
echo "GitHub SHA: ${{ github.sha }}"
|
||||||
|
|
||||||
|
# The tag should already exist since it triggered this workflow
|
||||||
|
# We just need to ensure gh release uses it correctly
|
||||||
|
|
||||||
|
body=$(cat <<- 'ENDBODY'
|
||||||
|

|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
Add a summary, including:
|
||||||
|
|
||||||
|
- Critical bug fixes
|
||||||
|
- New features
|
||||||
|
- Any breaking changes (and what to expect)
|
||||||
|
|
||||||
|
## Update Priority
|
||||||
|
|
||||||
|
This table provides priorities for which classes of users should update particular components.
|
||||||
|
|
||||||
|
| User Class | Priority |
|
||||||
|
|----------------------|-----------------|
|
||||||
|
| Payload Builders | <TODO> |
|
||||||
|
| Non-Payload Builders | <TODO> |
|
||||||
|
|
||||||
|
## All Changes
|
||||||
|
|
||||||
|
${{ steps.changelog.outputs.CHANGELOG }}
|
||||||
|
|
||||||
|
## Binaries
|
||||||
|
|
||||||
|
| System | Architecture | Binary | PGP Signature | Notes |
|
||||||
|
|:---:|:---:|:---:|:---:|:---|
|
||||||
|
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | amd64 | [GETH_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_AMD64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_AMD64_PLACEHOLDER.asc) | Most Linux systems |
|
||||||
|
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | arm64 | [GETH_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ARM64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ARM64_PLACEHOLDER.asc) | 64-bit ARM systems |
|
||||||
|
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | amd64 | [GETH_ALLTOOLS_AMD64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_AMD64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_AMD64_PLACEHOLDER.asc) | All tools bundle (amd64) |
|
||||||
|
| <img src="https://simpleicons.org/icons/linux.svg" style="width: 32px;"/> | arm64 | [GETH_ALLTOOLS_ARM64_PLACEHOLDER](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_ARM64_PLACEHOLDER) | [Signature](https://github.com/${{ github.repository }}/releases/download/RELEASE_TAG_PLACEHOLDER/GETH_ALLTOOLS_ARM64_PLACEHOLDER.asc) | All tools bundle (arm64) |
|
||||||
|
| **System** | **Option** | - | **Resource** |
|
||||||
|
| <img src="https://simpleicons.org/icons/docker.svg" style="width: 32px;"/> | Docker | | [ghcr.io/berachain/bera-geth](https://ghcr.io/berachain/bera-geth) |
|
||||||
|
|
||||||
|
### Verifying Binary Signatures
|
||||||
|
|
||||||
|
All release binaries are signed with PGP. To verify:
|
||||||
|
|
||||||
|
1. Download the [public key](https://raw.githubusercontent.com/${{ github.repository }}/main/.github/workflows/release.asc)
|
||||||
|
2. Import the key: `gpg --import release.asc`
|
||||||
|
3. Verify the signature: `gpg --verify <filename>.asc <filename>`
|
||||||
|
|
||||||
|
### Docker Images
|
||||||
|
|
||||||
|
Docker images are available at `ghcr.io/berachain/bera-geth` and are signed with [Cosign](https://github.com/sigstore/cosign) using keyless signing from GitHub Actions OIDC.
|
||||||
|
|
||||||
|
To verify a specific release image (recommended: by digest):
|
||||||
|
```bash
|
||||||
|
cosign verify \
|
||||||
|
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
|
||||||
|
--certificate-identity-regexp "^https://github.com/berachain/bera-geth/.github/workflows/docker.yml@.+" \
|
||||||
|
ghcr.io/berachain/bera-geth@$(docker buildx imagetools inspect ghcr.io/berachain/bera-geth:RELEASE_TAG_PLACEHOLDER | awk '/^Digest:/ {print $2; exit}')
|
||||||
|
```
|
||||||
|
|
||||||
|
To verify the `latest` unstable image instead (not recommended; tags can move):
|
||||||
|
```bash
|
||||||
|
cosign verify \
|
||||||
|
--certificate-oidc-issuer "https://token.actions.githubusercontent.com" \
|
||||||
|
--certificate-identity-regexp "^https://github.com/berachain/bera-geth/.github/workflows/docker.yml@.+" \
|
||||||
|
ghcr.io/berachain/bera-geth@$(docker buildx imagetools inspect ghcr.io/berachain/bera-geth:latest | awk '/^Digest:/ {print $2; exit}')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
The archives contain the geth binary and license file. Extract and run:
|
||||||
|
```bash
|
||||||
|
tar -xzf GETH_AMD64_PLACEHOLDER
|
||||||
|
./geth
|
||||||
|
```
|
||||||
|
|
||||||
|
The **alltools** archives additionally contain:
|
||||||
|
- `abigen` - Source code generator for Ethereum contracts
|
||||||
|
- `evm` - Developer utility for the Ethereum Virtual Machine
|
||||||
|
- `rlpdump` - Developer utility for RLP data
|
||||||
|
- `clef` - Ethereum account management tool
|
||||||
|
|
||||||
|
ENDBODY
|
||||||
|
)
|
||||||
|
|
||||||
|
# Replace placeholders with actual filenames and release tag
|
||||||
|
body="${body//GETH_AMD64_PLACEHOLDER/$GETH_AMD64}"
|
||||||
|
body="${body//GETH_ARM64_PLACEHOLDER/$GETH_ARM64}"
|
||||||
|
body="${body//GETH_ALLTOOLS_AMD64_PLACEHOLDER/$GETH_ALLTOOLS_AMD64}"
|
||||||
|
body="${body//GETH_ALLTOOLS_ARM64_PLACEHOLDER/$GETH_ALLTOOLS_ARM64}"
|
||||||
|
body="${body//RELEASE_TAG_PLACEHOLDER/$RELEASE_TAG}"
|
||||||
|
|
||||||
|
# Create assets array for gh release
|
||||||
|
assets=()
|
||||||
|
for asset in bera-geth-*.tar.gz bera-geth-*.tar.gz.asc; do
|
||||||
|
if [ -f "$asset" ]; then
|
||||||
|
assets+=("$asset")
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Create the release with the actual tag
|
||||||
|
# Using --target with GITHUB_SHA ensures we create the release at the right commit
|
||||||
|
echo "$body" | gh release create "$RELEASE_TAG" \
|
||||||
|
--draft \
|
||||||
|
--title "Bera Geth $RELEASE_TAG" \
|
||||||
|
-F - \
|
||||||
|
"${assets[@]}"
|
||||||
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -56,3 +56,9 @@ cmd/evm/evm
|
||||||
cmd/geth/geth
|
cmd/geth/geth
|
||||||
cmd/rlpdump/rlpdump
|
cmd/rlpdump/rlpdump
|
||||||
cmd/workload/workload
|
cmd/workload/workload
|
||||||
|
|
||||||
|
# claude
|
||||||
|
.claude
|
||||||
|
|
||||||
|
# for testing docker builds
|
||||||
|
.github/workflows/docker-test.yml
|
||||||
|
|
|
||||||
22
CHANGELOG.md
Normal file
22
CHANGELOG.md
Normal file
|
|
@ -0,0 +1,22 @@
|
||||||
|
# Changelog
|
||||||
|
|
||||||
|
All notable changes to this project will be documented in this file.
|
||||||
|
|
||||||
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
||||||
|
and this project adheres to
|
||||||
|
[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
||||||
|
|
||||||
|
## [v1.TBD.0]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- Add support for the Berachain mainnet (`--berachain`) and Bepolia networks
|
||||||
|
(`--bepolia`)
|
||||||
|
- Add support for configuring the Prague1 fork on Berachain networks.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- BRIP-2: Allowed configuration of the `MinimumBaseFeeWei`. For Berachain, this will be set as 1 gwei. (https://github.com/berachain/bera-geth/pull/2)
|
||||||
|
- BRIP-2: Allowed configuration of the `BaseFeeChangeDenominator`. For Berachain, this will be set as 48 (a 6x increase corresponding to 6x faster block times). (https://github.com/berachain/bera-geth/pull/2)
|
||||||
|
- [WIP] Updated release GH workflow to publish tarballs and push built images to GHCR.
|
||||||
|
- Removed support for appveyor, gitea, travis, circleci.
|
||||||
145
CLAUDE.md
Normal file
145
CLAUDE.md
Normal file
|
|
@ -0,0 +1,145 @@
|
||||||
|
# CLAUDE.md
|
||||||
|
|
||||||
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||||
|
|
||||||
|
## Project Overview
|
||||||
|
|
||||||
|
This is **bera-geth**, Berachain's fork of go-ethereum that implements the Berachain blockchain network. Key differences from upstream:
|
||||||
|
|
||||||
|
- **Custom base fee mechanism**: 1 gwei minimum with 6x faster adjustments via Prague1 fork
|
||||||
|
- **Networks**: Berachain mainnet (Chain ID 80094) and Bepolia testnet (Chain ID 80069)
|
||||||
|
- **Optimized for faster block times** while maintaining Ethereum compatibility
|
||||||
|
|
||||||
|
## Development Commands
|
||||||
|
|
||||||
|
### Building
|
||||||
|
```bash
|
||||||
|
make geth # Build main geth binary
|
||||||
|
make all # Build all executables
|
||||||
|
make evm # Build EVM utility
|
||||||
|
```
|
||||||
|
|
||||||
|
### Testing
|
||||||
|
```bash
|
||||||
|
make test # Run all tests
|
||||||
|
go test ./path/to/package # Run specific package tests
|
||||||
|
go test -run TestName # Run specific test
|
||||||
|
```
|
||||||
|
|
||||||
|
### Code Quality
|
||||||
|
```bash
|
||||||
|
make lint # Run linters
|
||||||
|
make fmt # Format code with gofmt
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development Tools
|
||||||
|
```bash
|
||||||
|
make devtools # Install development dependencies
|
||||||
|
```
|
||||||
|
|
||||||
|
### Cleaning
|
||||||
|
```bash
|
||||||
|
make clean # Clean build artifacts
|
||||||
|
```
|
||||||
|
|
||||||
|
## Codebase Architecture
|
||||||
|
|
||||||
|
### Core Components
|
||||||
|
|
||||||
|
**Core Blockchain Logic** (`/core/`)
|
||||||
|
- `blockchain.go` - Main blockchain state management
|
||||||
|
- `state_processor.go` - Transaction execution
|
||||||
|
- `types/` - Core data structures (blocks, transactions, receipts)
|
||||||
|
- `vm/` - Ethereum Virtual Machine implementation
|
||||||
|
- `txpool/` - Transaction pool management
|
||||||
|
|
||||||
|
**Consensus Layer** (`/consensus/`)
|
||||||
|
- `beacon/` - Proof-of-stake consensus (primary)
|
||||||
|
- `misc/eip1559/` - Base fee calculation with Berachain modifications
|
||||||
|
- `clique/` - Proof-of-authority for testing
|
||||||
|
|
||||||
|
**Network Protocol** (`/eth/`)
|
||||||
|
- `backend.go` - Main Ethereum service
|
||||||
|
- `downloader/` - Block/state synchronization
|
||||||
|
- `protocols/` - Network protocol handlers
|
||||||
|
|
||||||
|
**P2P Networking** (`/p2p/`)
|
||||||
|
- `discover/` - Node discovery protocols
|
||||||
|
- `rlpx/` - Encrypted communication
|
||||||
|
|
||||||
|
### Key Entry Points
|
||||||
|
|
||||||
|
**Main Binary**: `/cmd/geth/main.go`
|
||||||
|
- CLI application setup
|
||||||
|
- Network selection logic
|
||||||
|
- Node initialization
|
||||||
|
|
||||||
|
**Other Executables**: `/cmd/`
|
||||||
|
- `clef/` - Account management
|
||||||
|
- `abigen/` - ABI binding generator
|
||||||
|
- `evm/` - Standalone EVM executor
|
||||||
|
|
||||||
|
### Configuration Management
|
||||||
|
|
||||||
|
**Chain Configs**: `/params/config.go`
|
||||||
|
- Network parameters and fork schedules
|
||||||
|
- Berachain/Bepolia network definitions
|
||||||
|
- Prague1 fork configuration
|
||||||
|
|
||||||
|
**Network Discovery**: `/params/bootnodes.go`
|
||||||
|
- Bootstrap nodes for peer discovery
|
||||||
|
|
||||||
|
### Berachain-Specific Modifications
|
||||||
|
|
||||||
|
**Base Fee Changes** (`/consensus/misc/eip1559/eip1559.go:116-121`)
|
||||||
|
- Prague1 fork enforces 1 gwei minimum base fee
|
||||||
|
- BaseFeeChangeDenominator set to 48 (6x faster adjustment)
|
||||||
|
|
||||||
|
**Network Configurations** (`/params/config.go:77-99, 107-129`)
|
||||||
|
- BerachainChainConfig with Chain ID 80094
|
||||||
|
- BepoliaChainConfig with Chain ID 80069
|
||||||
|
- Custom Prague1 fork activation parameters
|
||||||
|
|
||||||
|
### Test Organization
|
||||||
|
|
||||||
|
Tests follow Go conventions with `*_test.go` files alongside source code:
|
||||||
|
- Unit tests in package directories
|
||||||
|
- Integration tests in `/tests/`
|
||||||
|
- Consensus tests for Ethereum specification compliance
|
||||||
|
- EVM operation tests in `/core/vm/testdata/`
|
||||||
|
|
||||||
|
### Build System
|
||||||
|
|
||||||
|
**Primary Build**: `/build/ci.go`
|
||||||
|
- Cross-platform compilation
|
||||||
|
- Docker image building
|
||||||
|
- Release packaging
|
||||||
|
|
||||||
|
**Simple Builds**: `/Makefile`
|
||||||
|
- Development-focused targets
|
||||||
|
- Requires Go 1.23+ and C compiler
|
||||||
|
|
||||||
|
## Development Workflow
|
||||||
|
|
||||||
|
1. **Architecture Understanding**: The codebase follows Ethereum's layered architecture (consensus → state → networking → application)
|
||||||
|
2. **Testing Strategy**: Always run tests after changes with `make test`
|
||||||
|
3. **Code Style**: Use `make fmt` and `make lint` before committing
|
||||||
|
4. **Network Testing**: Use `--bepolia` flag for testnet development
|
||||||
|
5. **Debugging**: Use `./build/bin/geth --help` for comprehensive CLI options
|
||||||
|
|
||||||
|
## Network-Specific Usage
|
||||||
|
|
||||||
|
### Berachain Mainnet
|
||||||
|
```bash
|
||||||
|
./build/bin/geth --berachain
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bepolia Testnet
|
||||||
|
```bash
|
||||||
|
./build/bin/geth --bepolia
|
||||||
|
```
|
||||||
|
|
||||||
|
### Development Mode
|
||||||
|
```bash
|
||||||
|
./build/bin/geth --dev
|
||||||
|
```
|
||||||
26
Dockerfile
26
Dockerfile
|
|
@ -6,24 +6,36 @@ ARG BUILDNUM=""
|
||||||
# Build Geth in a stock Go builder container
|
# Build Geth in a stock Go builder container
|
||||||
FROM golang:1.24-alpine AS builder
|
FROM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
|
# These build arguments need to be redeclared in the builder stage
|
||||||
|
ARG COMMIT
|
||||||
|
ARG VERSION
|
||||||
|
ARG BUILDNUM
|
||||||
|
|
||||||
RUN apk add --no-cache gcc musl-dev linux-headers git
|
RUN apk add --no-cache gcc musl-dev linux-headers git
|
||||||
|
|
||||||
# Get dependencies - will also be cached if we won't change go.mod/go.sum
|
# Get dependencies - will also be cached if we won't change go.mod/go.sum
|
||||||
COPY go.mod /go-ethereum/
|
COPY go.mod /bera-geth/
|
||||||
COPY go.sum /go-ethereum/
|
COPY go.sum /bera-geth/
|
||||||
RUN cd /go-ethereum && go mod download
|
RUN cd /bera-geth && go mod download
|
||||||
|
|
||||||
ADD . /go-ethereum
|
ADD . /bera-geth
|
||||||
RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
|
# Pass git information to the build process
|
||||||
|
# When VERSION is provided (e.g., from CI), use it as the git tag
|
||||||
|
RUN cd /bera-geth && \
|
||||||
|
if [ -n "$VERSION" ]; then \
|
||||||
|
go run build/ci.go install -static -git-tag="$VERSION" -git-commit="$COMMIT" ./cmd/bera-geth; \
|
||||||
|
else \
|
||||||
|
go run build/ci.go install -static ./cmd/bera-geth; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Pull Geth into a second stage deploy alpine container
|
# Pull Geth into a second stage deploy alpine container
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates
|
||||||
COPY --from=builder /go-ethereum/build/bin/geth /usr/local/bin/
|
COPY --from=builder /bera-geth/build/bin/bera-geth /usr/local/bin/
|
||||||
|
|
||||||
EXPOSE 8545 8546 30303 30303/udp
|
EXPOSE 8545 8546 30303 30303/udp
|
||||||
ENTRYPOINT ["geth"]
|
ENTRYPOINT ["bera-geth"]
|
||||||
|
|
||||||
# Add some metadata labels to help programmatic image consumption
|
# Add some metadata labels to help programmatic image consumption
|
||||||
ARG COMMIT=""
|
ARG COMMIT=""
|
||||||
|
|
|
||||||
|
|
@ -6,28 +6,44 @@ ARG BUILDNUM=""
|
||||||
# Build Geth in a stock Go builder container
|
# Build Geth in a stock Go builder container
|
||||||
FROM golang:1.24-alpine AS builder
|
FROM golang:1.24-alpine AS builder
|
||||||
|
|
||||||
|
# These build arguments need to be redeclared in the builder stage
|
||||||
|
ARG COMMIT
|
||||||
|
ARG VERSION
|
||||||
|
ARG BUILDNUM
|
||||||
|
|
||||||
RUN apk add --no-cache gcc musl-dev linux-headers git
|
RUN apk add --no-cache gcc musl-dev linux-headers git
|
||||||
|
|
||||||
# Get dependencies - will also be cached if we won't change go.mod/go.sum
|
# Get dependencies - will also be cached if we won't change go.mod/go.sum
|
||||||
COPY go.mod /go-ethereum/
|
COPY go.mod /bera-geth/
|
||||||
COPY go.sum /go-ethereum/
|
COPY go.sum /bera-geth/
|
||||||
RUN cd /go-ethereum && go mod download
|
RUN cd /bera-geth && go mod download
|
||||||
|
|
||||||
ADD . /go-ethereum
|
ADD . /bera-geth
|
||||||
|
|
||||||
# This is not strictly necessary, but it matches the "Dockerfile" steps, thus
|
# This is not strictly necessary, but it matches the "Dockerfile" steps, thus
|
||||||
# makes it so that under certain circumstances, the docker layer can be cached,
|
# makes it so that under certain circumstances, the docker layer can be cached,
|
||||||
# and the builder can jump to the next (build all) command, with the go cache fully loaded.
|
# and the builder can jump to the next (build all) command, with the go cache fully loaded.
|
||||||
#
|
#
|
||||||
RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
|
# Pass git information to the build process when provided
|
||||||
|
RUN cd /bera-geth && \
|
||||||
|
if [ -n "$VERSION" ]; then \
|
||||||
|
go run build/ci.go install -static -git-tag="$VERSION" -git-commit="$COMMIT" ./cmd/bera-geth; \
|
||||||
|
else \
|
||||||
|
go run build/ci.go install -static ./cmd/bera-geth; \
|
||||||
|
fi
|
||||||
|
|
||||||
RUN cd /go-ethereum && go run build/ci.go install -static
|
RUN cd /bera-geth && \
|
||||||
|
if [ -n "$VERSION" ]; then \
|
||||||
|
go run build/ci.go install -static -git-tag="$VERSION" -git-commit="$COMMIT"; \
|
||||||
|
else \
|
||||||
|
go run build/ci.go install -static; \
|
||||||
|
fi
|
||||||
|
|
||||||
# Pull all binaries into a second stage deploy alpine container
|
# Pull all binaries into a second stage deploy alpine container
|
||||||
FROM alpine:latest
|
FROM alpine:latest
|
||||||
|
|
||||||
RUN apk add --no-cache ca-certificates
|
RUN apk add --no-cache ca-certificates
|
||||||
COPY --from=builder /go-ethereum/build/bin/* /usr/local/bin/
|
COPY --from=builder /bera-geth/build/bin/* /usr/local/bin/
|
||||||
|
|
||||||
EXPOSE 8545 8546 30303 30303/udp
|
EXPOSE 8545 8546 30303 30303/udp
|
||||||
|
|
||||||
|
|
|
||||||
10
Makefile
10
Makefile
|
|
@ -2,17 +2,17 @@
|
||||||
# with Go source code. If you know what GOPATH is then you probably
|
# with Go source code. If you know what GOPATH is then you probably
|
||||||
# don't need to bother with make.
|
# don't need to bother with make.
|
||||||
|
|
||||||
.PHONY: geth evm all test lint fmt clean devtools help
|
.PHONY: bera-geth evm all test lint fmt clean devtools help
|
||||||
|
|
||||||
GOBIN = ./build/bin
|
GOBIN = ./build/bin
|
||||||
GO ?= latest
|
GO ?= latest
|
||||||
GORUN = go run
|
GORUN = go run
|
||||||
|
|
||||||
#? geth: Build geth.
|
#? bera-geth: Build bera-geth.
|
||||||
geth:
|
bera-geth:
|
||||||
$(GORUN) build/ci.go install ./cmd/geth
|
$(GORUN) build/ci.go install ./cmd/bera-geth
|
||||||
@echo "Done building."
|
@echo "Done building."
|
||||||
@echo "Run \"$(GOBIN)/geth\" to launch geth."
|
@echo "Run \"$(GOBIN)/bera-geth\" to launch bera-geth."
|
||||||
|
|
||||||
#? evm: Build evm.
|
#? evm: Build evm.
|
||||||
evm:
|
evm:
|
||||||
|
|
|
||||||
58
README.md
58
README.md
|
|
@ -17,11 +17,11 @@ archives are published at https://geth.ethereum.org/downloads/.
|
||||||
|
|
||||||
For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth).
|
For prerequisites and detailed build instructions please read the [Installation Instructions](https://geth.ethereum.org/docs/getting-started/installing-geth).
|
||||||
|
|
||||||
Building `geth` requires both a Go (version 1.23 or later) and a C compiler. You can install
|
Building `bera-geth` requires both a Go (version 1.23 or later) and a C compiler. You can install
|
||||||
them using your favourite package manager. Once the dependencies are installed, run
|
them using your favourite package manager. Once the dependencies are installed, run
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
make geth
|
make bera-geth
|
||||||
```
|
```
|
||||||
|
|
||||||
or, to build the full suite of utilities:
|
or, to build the full suite of utilities:
|
||||||
|
|
@ -37,19 +37,19 @@ directory.
|
||||||
|
|
||||||
| Command | Description |
|
| Command | Description |
|
||||||
| :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
| :--------: | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
| **`geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `geth --help` and the [CLI page](https://geth.ethereum.org/docs/fundamentals/command-line-options) for command line options. |
|
| **`bera-geth`** | Our main Ethereum CLI client. It is the entry point into the Ethereum network (main-, test- or private net), capable of running as a full node (default), archive node (retaining all historical state) or a light node (retrieving data live). It can be used by other processes as a gateway into the Ethereum network via JSON RPC endpoints exposed on top of HTTP, WebSocket and/or IPC transports. `bera-geth --help` and the [CLI page](https://geth.ethereum.org/docs/fundamentals/command-line-options) for command line options. |
|
||||||
| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. |
|
| `clef` | Stand-alone signing tool, which can be used as a backend signer for `bera-geth`. |
|
||||||
| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. |
|
| `devp2p` | Utilities to interact with nodes on the networking layer, without running a full blockchain. |
|
||||||
| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings) page for details. |
|
| `abigen` | Source code generator to convert Ethereum contract definitions into easy-to-use, compile-time type-safe Go packages. It operates on plain [Ethereum contract ABIs](https://docs.soliditylang.org/en/develop/abi-spec.html) with expanded functionality if the contract bytecode is also available. However, it also accepts Solidity source files, making development much more streamlined. Please see our [Native DApps](https://geth.ethereum.org/docs/developers/dapp-developer/native-bindings) page for details. |
|
||||||
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). |
|
| `evm` | Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode. Its purpose is to allow isolated, fine-grained debugging of EVM opcodes (e.g. `evm --code 60ff60ff --debug run`). |
|
||||||
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |
|
| `rlpdump` | Developer utility tool to convert binary RLP ([Recursive Length Prefix](https://ethereum.org/en/developers/docs/data-structures-and-encoding/rlp)) dumps (data encoding used by the Ethereum protocol both network as well as consensus wise) to user-friendlier hierarchical representation (e.g. `rlpdump --hex CE0183FFFFFFC4C304050583616263`). |
|
||||||
|
|
||||||
## Running `geth`
|
## Running `bera-geth`
|
||||||
|
|
||||||
Going through all the possible command line flags is out of scope here (please consult our
|
Going through all the possible command line flags is out of scope here (please consult our
|
||||||
[CLI Wiki page](https://geth.ethereum.org/docs/fundamentals/command-line-options)),
|
[CLI Wiki page](https://geth.ethereum.org/docs/fundamentals/command-line-options)),
|
||||||
but we've enumerated a few common parameter combos to get you up to speed quickly
|
but we've enumerated a few common parameter combos to get you up to speed quickly
|
||||||
on how you can run your own `geth` instance.
|
on how you can run your own `bera-geth` instance.
|
||||||
|
|
||||||
### Hardware Requirements
|
### Hardware Requirements
|
||||||
|
|
||||||
|
|
@ -75,19 +75,19 @@ particular use case, the user doesn't care about years-old historical data, so w
|
||||||
sync quickly to the current state of the network. To do so:
|
sync quickly to the current state of the network. To do so:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ geth console
|
$ bera-geth console
|
||||||
```
|
```
|
||||||
|
|
||||||
This command will:
|
This command will:
|
||||||
* Start `geth` in snap sync mode (default, can be changed with the `--syncmode` flag),
|
* Start `bera-geth` in snap sync mode (default, can be changed with the `--syncmode` flag),
|
||||||
causing it to download more data in exchange for avoiding processing the entire history
|
causing it to download more data in exchange for avoiding processing the entire history
|
||||||
of the Ethereum network, which is very CPU intensive.
|
of the Ethereum network, which is very CPU intensive.
|
||||||
* Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interacting-with-geth/javascript-console),
|
* Start the built-in interactive [JavaScript console](https://geth.ethereum.org/docs/interacting-with-geth/javascript-console),
|
||||||
(via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md)
|
(via the trailing `console` subcommand) through which you can interact using [`web3` methods](https://github.com/ChainSafe/web3.js/blob/0.20.7/DOCUMENTATION.md)
|
||||||
(note: the `web3` version bundled within `geth` is very old, and not up to date with official docs),
|
(note: the `web3` version bundled within `bera-geth` is very old, and not up to date with official docs),
|
||||||
as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc).
|
as well as `bera-geth`'s own [management APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc).
|
||||||
This tool is optional and if you leave it out you can always attach it to an already running
|
This tool is optional and if you leave it out you can always attach it to an already running
|
||||||
`geth` instance with `geth attach`.
|
`bera-geth` instance with `bera-geth attach`.
|
||||||
|
|
||||||
### A Full node on the Holesky test network
|
### A Full node on the Holesky test network
|
||||||
|
|
||||||
|
|
@ -98,45 +98,45 @@ network, you want to join the **test** network with your node, which is fully eq
|
||||||
the main network, but with play-Ether only.
|
the main network, but with play-Ether only.
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ geth --holesky console
|
$ bera-geth --holesky console
|
||||||
```
|
```
|
||||||
|
|
||||||
The `console` subcommand has the same meaning as above and is equally
|
The `console` subcommand has the same meaning as above and is equally
|
||||||
useful on the testnet too.
|
useful on the testnet too.
|
||||||
|
|
||||||
Specifying the `--holesky` flag, however, will reconfigure your `geth` instance a bit:
|
Specifying the `--holesky` flag, however, will reconfigure your `bera-geth` instance a bit:
|
||||||
|
|
||||||
* Instead of connecting to the main Ethereum network, the client will connect to the Holesky
|
* Instead of connecting to the main Ethereum network, the client will connect to the Holesky
|
||||||
test network, which uses different P2P bootnodes, different network IDs and genesis
|
test network, which uses different P2P bootnodes, different network IDs and genesis
|
||||||
states.
|
states.
|
||||||
* Instead of using the default data directory (`~/.ethereum` on Linux for example), `geth`
|
* Instead of using the default data directory (`~/.ethereum` on Linux for example), `bera-geth`
|
||||||
will nest itself one level deeper into a `holesky` subfolder (`~/.ethereum/holesky` on
|
will nest itself one level deeper into a `holesky` subfolder (`~/.ethereum/holesky` on
|
||||||
Linux). Note, on OSX and Linux this also means that attaching to a running testnet node
|
Linux). Note, on OSX and Linux this also means that attaching to a running testnet node
|
||||||
requires the use of a custom endpoint since `geth attach` will try to attach to a
|
requires the use of a custom endpoint since `bera-geth attach` will try to attach to a
|
||||||
production node endpoint by default, e.g.,
|
production node endpoint by default, e.g.,
|
||||||
`geth attach <datadir>/holesky/geth.ipc`. Windows users are not affected by
|
`bera-geth attach <datadir>/holesky/geth.ipc`. Windows users are not affected by
|
||||||
this.
|
this.
|
||||||
|
|
||||||
*Note: Although some internal protective measures prevent transactions from
|
*Note: Although some internal protective measures prevent transactions from
|
||||||
crossing over between the main network and test network, you should always
|
crossing over between the main network and test network, you should always
|
||||||
use separate accounts for play and real money. Unless you manually move
|
use separate accounts for play and real money. Unless you manually move
|
||||||
accounts, `geth` will by default correctly separate the two networks and will not make any
|
accounts, `bera-geth` will by default correctly separate the two networks and will not make any
|
||||||
accounts available between them.*
|
accounts available between them.*
|
||||||
|
|
||||||
### Configuration
|
### Configuration
|
||||||
|
|
||||||
As an alternative to passing the numerous flags to the `geth` binary, you can also pass a
|
As an alternative to passing the numerous flags to the `bera-geth` binary, you can also pass a
|
||||||
configuration file via:
|
configuration file via:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ geth --config /path/to/your_config.toml
|
$ bera-geth --config /path/to/your_config.toml
|
||||||
```
|
```
|
||||||
|
|
||||||
To get an idea of how the file should look like you can use the `dumpconfig` subcommand to
|
To get an idea of how the file should look like you can use the `dumpconfig` subcommand to
|
||||||
export your existing configuration:
|
export your existing configuration:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
$ geth --your-favourite-flags dumpconfig
|
$ bera-geth --your-favourite-flags dumpconfig
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Docker quick start
|
#### Docker quick start
|
||||||
|
|
@ -150,25 +150,25 @@ docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \
|
||||||
ethereum/client-go
|
ethereum/client-go
|
||||||
```
|
```
|
||||||
|
|
||||||
This will start `geth` in snap-sync mode with a DB memory allowance of 1GB, as the
|
This will start `bera-geth` in snap-sync mode with a DB memory allowance of 1GB, as the
|
||||||
above command does. It will also create a persistent volume in your home directory for
|
above command does. It will also create a persistent volume in your home directory for
|
||||||
saving your blockchain as well as map the default ports. There is also an `alpine` tag
|
saving your blockchain as well as map the default ports. There is also an `alpine` tag
|
||||||
available for a slim version of the image.
|
available for a slim version of the image.
|
||||||
|
|
||||||
Do not forget `--http.addr 0.0.0.0`, if you want to access RPC from other containers
|
Do not forget `--http.addr 0.0.0.0`, if you want to access RPC from other containers
|
||||||
and/or hosts. By default, `geth` binds to the local interface and RPC endpoints are not
|
and/or hosts. By default, `bera-geth` binds to the local interface and RPC endpoints are not
|
||||||
accessible from the outside.
|
accessible from the outside.
|
||||||
|
|
||||||
### Programmatically interfacing `geth` nodes
|
### Programmatically interfacing `bera-geth` nodes
|
||||||
|
|
||||||
As a developer, sooner rather than later you'll want to start interacting with `geth` and the
|
As a developer, sooner rather than later you'll want to start interacting with `bera-geth` and the
|
||||||
Ethereum network via your own programs and not manually through the console. To aid
|
Ethereum network via your own programs and not manually through the console. To aid
|
||||||
this, `geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.org/en/developers/docs/apis/json-rpc/)
|
this, `bera-geth` has built-in support for a JSON-RPC based APIs ([standard APIs](https://ethereum.org/en/developers/docs/apis/json-rpc/)
|
||||||
and [`geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)).
|
and [`bera-geth` specific APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc)).
|
||||||
These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based
|
These can be exposed via HTTP, WebSockets and IPC (UNIX sockets on UNIX based
|
||||||
platforms, and named pipes on Windows).
|
platforms, and named pipes on Windows).
|
||||||
|
|
||||||
The IPC interface is enabled by default and exposes all the APIs supported by `geth`,
|
The IPC interface is enabled by default and exposes all the APIs supported by `bera-geth`,
|
||||||
whereas the HTTP and WS interfaces need to manually be enabled and only expose a
|
whereas the HTTP and WS interfaces need to manually be enabled and only expose a
|
||||||
subset of APIs due to security reasons. These can be turned on/off and configured as
|
subset of APIs due to security reasons. These can be turned on/off and configured as
|
||||||
you'd expect.
|
you'd expect.
|
||||||
|
|
@ -189,7 +189,7 @@ HTTP based JSON-RPC API options:
|
||||||
* `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it)
|
* `--ipcpath` Filename for IPC socket/pipe within the datadir (explicit paths escape it)
|
||||||
|
|
||||||
You'll need to use your own programming environments' capabilities (libraries, tools, etc) to
|
You'll need to use your own programming environments' capabilities (libraries, tools, etc) to
|
||||||
connect via HTTP, WS or IPC to a `geth` node configured with the above flags and you'll
|
connect via HTTP, WS or IPC to a `bera-geth` node configured with the above flags and you'll
|
||||||
need to speak [JSON-RPC](https://www.jsonrpc.org/specification) on all transports. You
|
need to speak [JSON-RPC](https://www.jsonrpc.org/specification) on all transports. You
|
||||||
can reuse the same connection for multiple requests!
|
can reuse the same connection for multiple requests!
|
||||||
|
|
||||||
|
|
@ -205,7 +205,7 @@ Maintaining your own private network is more involved as a lot of configurations
|
||||||
granted in the official networks need to be manually set up.
|
granted in the official networks need to be manually set up.
|
||||||
|
|
||||||
Unfortunately since [the Merge](https://ethereum.org/en/roadmap/merge/) it is no longer possible
|
Unfortunately since [the Merge](https://ethereum.org/en/roadmap/merge/) it is no longer possible
|
||||||
to easily set up a network of geth nodes without also setting up a corresponding beacon chain.
|
to easily set up a network of bera-geth nodes without also setting up a corresponding beacon chain.
|
||||||
|
|
||||||
There are three different solutions depending on your use case:
|
There are three different solutions depending on your use case:
|
||||||
|
|
||||||
|
|
|
||||||
59
appveyor.yml
59
appveyor.yml
|
|
@ -1,59 +0,0 @@
|
||||||
clone_depth: 5
|
|
||||||
version: "{branch}.{build}"
|
|
||||||
|
|
||||||
image:
|
|
||||||
- Ubuntu
|
|
||||||
- Visual Studio 2019
|
|
||||||
|
|
||||||
environment:
|
|
||||||
matrix:
|
|
||||||
- GETH_ARCH: amd64
|
|
||||||
GETH_MINGW: 'C:\msys64\mingw64'
|
|
||||||
- GETH_ARCH: 386
|
|
||||||
GETH_MINGW: 'C:\msys64\mingw32'
|
|
||||||
|
|
||||||
install:
|
|
||||||
- git submodule update --init --depth 1 --recursive
|
|
||||||
- go version
|
|
||||||
|
|
||||||
for:
|
|
||||||
# Linux has its own script without -arch and -cc.
|
|
||||||
# The linux builder also runs lint.
|
|
||||||
- matrix:
|
|
||||||
only:
|
|
||||||
- image: Ubuntu
|
|
||||||
build_script:
|
|
||||||
- go run build/ci.go lint
|
|
||||||
- go run build/ci.go check_generate
|
|
||||||
- go run build/ci.go check_baddeps
|
|
||||||
- go run build/ci.go install -dlgo
|
|
||||||
test_script:
|
|
||||||
- go run build/ci.go test -dlgo -short
|
|
||||||
|
|
||||||
# linux/386 is disabled.
|
|
||||||
- matrix:
|
|
||||||
exclude:
|
|
||||||
- image: Ubuntu
|
|
||||||
GETH_ARCH: 386
|
|
||||||
|
|
||||||
# Windows builds for amd64 + 386.
|
|
||||||
- matrix:
|
|
||||||
only:
|
|
||||||
- image: Visual Studio 2019
|
|
||||||
environment:
|
|
||||||
# We use gcc from MSYS2 because it is the most recent compiler version available on
|
|
||||||
# AppVeyor. Note: gcc.exe only works properly if the corresponding bin/ directory is
|
|
||||||
# contained in PATH.
|
|
||||||
GETH_CC: '%GETH_MINGW%\bin\gcc.exe'
|
|
||||||
PATH: '%GETH_MINGW%\bin;C:\Program Files (x86)\NSIS\;%PATH%'
|
|
||||||
build_script:
|
|
||||||
- 'echo %GETH_ARCH%'
|
|
||||||
- 'echo %GETH_CC%'
|
|
||||||
- '%GETH_CC% --version'
|
|
||||||
- go run build/ci.go install -dlgo -arch %GETH_ARCH% -cc %GETH_CC%
|
|
||||||
after_build:
|
|
||||||
# Upload builds. Note that ci.go makes this a no-op PR builds.
|
|
||||||
- go run build/ci.go archive -arch %GETH_ARCH% -type zip -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
|
||||||
- go run build/ci.go nsis -arch %GETH_ARCH% -signer WINDOWS_SIGNING_KEY -upload gethstore/builds
|
|
||||||
test_script:
|
|
||||||
- go run build/ci.go test -dlgo -arch %GETH_ARCH% -cc %GETH_CC% -short
|
|
||||||
|
|
@ -101,6 +101,17 @@ func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent)
|
||||||
params = []any{execData}
|
params = []any{execData}
|
||||||
)
|
)
|
||||||
switch fork {
|
switch fork {
|
||||||
|
case "electra1":
|
||||||
|
// TODO(BRIP-4): Add ParentProposerPubkey to the chainHeadEvent to add to the newPayload call.
|
||||||
|
method = "engine_newPayloadV4P11"
|
||||||
|
parentBeaconRoot := event.BeaconHead.ParentRoot
|
||||||
|
blobHashes := collectBlobHashes(event.Block)
|
||||||
|
hexRequests := make([]hexutil.Bytes, len(event.ExecRequests))
|
||||||
|
for i := range event.ExecRequests {
|
||||||
|
hexRequests[i] = hexutil.Bytes(event.ExecRequests[i])
|
||||||
|
}
|
||||||
|
parentProposerPubkey := &common.Pubkey{}
|
||||||
|
params = append(params, blobHashes, parentBeaconRoot, hexRequests, parentProposerPubkey)
|
||||||
case "electra":
|
case "electra":
|
||||||
method = "engine_newPayloadV4"
|
method = "engine_newPayloadV4"
|
||||||
parentBeaconRoot := event.BeaconHead.ParentRoot
|
parentBeaconRoot := event.BeaconHead.ParentRoot
|
||||||
|
|
@ -145,6 +156,8 @@ func (ec *engineClient) callForkchoiceUpdated(fork string, event types.ChainHead
|
||||||
|
|
||||||
var method string
|
var method string
|
||||||
switch fork {
|
switch fork {
|
||||||
|
case "electra1":
|
||||||
|
method = "engine_forkchoiceUpdatedV3P11"
|
||||||
case "deneb", "electra":
|
case "deneb", "electra":
|
||||||
method = "engine_forkchoiceUpdatedV3"
|
method = "engine_forkchoiceUpdatedV3"
|
||||||
case "capella":
|
case "capella":
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
||||||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
ProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
|
||||||
}
|
}
|
||||||
var enc PayloadAttributes
|
var enc PayloadAttributes
|
||||||
enc.Timestamp = hexutil.Uint64(p.Timestamp)
|
enc.Timestamp = hexutil.Uint64(p.Timestamp)
|
||||||
|
|
@ -28,6 +29,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
|
||||||
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
|
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
|
||||||
enc.Withdrawals = p.Withdrawals
|
enc.Withdrawals = p.Withdrawals
|
||||||
enc.BeaconRoot = p.BeaconRoot
|
enc.BeaconRoot = p.BeaconRoot
|
||||||
|
enc.ProposerPubkey = p.ProposerPubkey
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -39,6 +41,7 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
||||||
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
ProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
|
||||||
}
|
}
|
||||||
var dec PayloadAttributes
|
var dec PayloadAttributes
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -62,5 +65,8 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
|
||||||
if dec.BeaconRoot != nil {
|
if dec.BeaconRoot != nil {
|
||||||
p.BeaconRoot = dec.BeaconRoot
|
p.BeaconRoot = dec.BeaconRoot
|
||||||
}
|
}
|
||||||
|
if dec.ProposerPubkey != nil {
|
||||||
|
p.ProposerPubkey = dec.ProposerPubkey
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ var (
|
||||||
PayloadV1 PayloadVersion = 0x1
|
PayloadV1 PayloadVersion = 0x1
|
||||||
PayloadV2 PayloadVersion = 0x2
|
PayloadV2 PayloadVersion = 0x2
|
||||||
PayloadV3 PayloadVersion = 0x3
|
PayloadV3 PayloadVersion = 0x3
|
||||||
|
PayloadV3P11 PayloadVersion = 0x31
|
||||||
)
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
||||||
|
|
@ -48,6 +49,7 @@ type PayloadAttributes struct {
|
||||||
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
|
||||||
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
Withdrawals []*types.Withdrawal `json:"withdrawals"`
|
||||||
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
ProposerPubkey *common.Pubkey `json:"parentProposerPubkey"` // Berachain: only used prague1 and onwards
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON type overrides for PayloadAttributes.
|
// JSON type overrides for PayloadAttributes.
|
||||||
|
|
@ -218,8 +220,8 @@ func decodeTransactions(enc [][]byte) ([]*types.Transaction, error) {
|
||||||
// and that the blockhash of the constructed block matches the parameters. Nil
|
// and that the blockhash of the constructed block matches the parameters. Nil
|
||||||
// Withdrawals value will propagate through the returned block. Empty
|
// Withdrawals value will propagate through the returned block. Empty
|
||||||
// Withdrawals value must be passed via non-nil, length 0 value in data.
|
// Withdrawals value must be passed via non-nil, length 0 value in data.
|
||||||
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
|
func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte, proposerPubkey *common.Pubkey) (*types.Block, error) {
|
||||||
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot, requests)
|
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot, requests, proposerPubkey)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -232,7 +234,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
|
||||||
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
|
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
|
||||||
// for stateless execution, so it skips checking if the executable data hashes to
|
// for stateless execution, so it skips checking if the executable data hashes to
|
||||||
// the requested hash (stateless has to *compute* the root hash, it's not given).
|
// the requested hash (stateless has to *compute* the root hash, it's not given).
|
||||||
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte) (*types.Block, error) {
|
func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.Hash, beaconRoot *common.Hash, requests [][]byte, proposerPubkey *common.Pubkey) (*types.Block, error) {
|
||||||
txs, err := decodeTransactions(data.Transactions)
|
txs, err := decodeTransactions(data.Transactions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -295,6 +297,7 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
|
||||||
BlobGasUsed: data.BlobGasUsed,
|
BlobGasUsed: data.BlobGasUsed,
|
||||||
ParentBeaconRoot: beaconRoot,
|
ParentBeaconRoot: beaconRoot,
|
||||||
RequestsHash: requestsHash,
|
RequestsHash: requestsHash,
|
||||||
|
ParentProposerPubkey: proposerPubkey,
|
||||||
}
|
}
|
||||||
return types.NewBlockWithHeader(header).
|
return types.NewBlockWithHeader(header).
|
||||||
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}).
|
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}).
|
||||||
|
|
@ -359,8 +362,8 @@ type ExecutionPayloadBody struct {
|
||||||
|
|
||||||
// Client identifiers to support ClientVersionV1.
|
// Client identifiers to support ClientVersionV1.
|
||||||
const (
|
const (
|
||||||
ClientCode = "GE"
|
ClientCode = "BG"
|
||||||
ClientName = "go-ethereum"
|
ClientName = "bera-geth"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ClientVersionV1 contains information which identifies a client implementation.
|
// ClientVersionV1 contains information which identifies a client implementation.
|
||||||
|
|
|
||||||
|
|
@ -5,54 +5,54 @@
|
||||||
# https://github.com/ethereum/execution-spec-tests/releases/download/fusaka-devnet-3%40v1.0.0
|
# https://github.com/ethereum/execution-spec-tests/releases/download/fusaka-devnet-3%40v1.0.0
|
||||||
576261e1280e5300c458aa9b05eccb2fec5ff80a0005940dc52fa03fdd907249 fixtures_fusaka-devnet-3.tar.gz
|
576261e1280e5300c458aa9b05eccb2fec5ff80a0005940dc52fa03fdd907249 fixtures_fusaka-devnet-3.tar.gz
|
||||||
|
|
||||||
# version:golang 1.25.0
|
# version:golang 1.24.4
|
||||||
# https://go.dev/dl/
|
# https://go.dev/dl/
|
||||||
4bd01e91297207bfa450ea40d4d5a93b1b531a5e438473b2a06e18e077227225 go1.25.0.src.tar.gz
|
5a86a83a31f9fa81490b8c5420ac384fd3d95a3e71fba665c7b3f95d1dfef2b4 go1.24.4.src.tar.gz
|
||||||
e5234a7dac67bc86c528fe9752fc9d63557918627707a733ab4cac1a6faed2d4 go1.25.0.aix-ppc64.tar.gz
|
0d2af78e3b6e08f8013dbbdb26ae33052697b6b72e03ec17d496739c2a1aed68 go1.24.4.aix-ppc64.tar.gz
|
||||||
5bd60e823037062c2307c71e8111809865116714d6f6b410597cf5075dfd80ef go1.25.0.darwin-amd64.tar.gz
|
69bef555e114b4a2252452b6e7049afc31fbdf2d39790b669165e89525cd3f5c go1.24.4.darwin-amd64.tar.gz
|
||||||
95e836238bcf8f9a71bffea43344cbd35ee1f16db3aaced2f98dbac045d102db go1.25.0.darwin-amd64.pkg
|
c4d74453a26f488bdb4b0294da4840d9020806de4661785334eb6d1803ee5c27 go1.24.4.darwin-amd64.pkg
|
||||||
544932844156d8172f7a28f77f2ac9c15a23046698b6243f633b0a0b00c0749c go1.25.0.darwin-arm64.tar.gz
|
27973684b515eaf461065054e6b572d9390c05e69ba4a423076c160165336470 go1.24.4.darwin-arm64.tar.gz
|
||||||
202a0d8338c152cb4c9f04782429e9ba8bef31d9889272380837e4043c9d800a go1.25.0.darwin-arm64.pkg
|
2fe1f8746745c4bfebd494583aaef24cad42594f6d25ed67856879d567ee66e7 go1.24.4.darwin-arm64.pkg
|
||||||
5ed3cf9a810a1483822538674f1336c06b51aa1b94d6d545a1a0319a48177120 go1.25.0.dragonfly-amd64.tar.gz
|
70b2de9c1cafe5af7be3eb8f80753cce0501ef300db3f3bd59be7ccc464234e1 go1.24.4.dragonfly-amd64.tar.gz
|
||||||
abea5d5c6697e6b5c224731f2158fe87c602996a2a233ac0c4730cd57bf8374e go1.25.0.freebsd-386.tar.gz
|
8d529839db29ee171505b89dc9c3de76003a4ab56202d84bddbbecacbfb6d7c9 go1.24.4.freebsd-386.tar.gz
|
||||||
86e6fe0a29698d7601c4442052dac48bd58d532c51cccb8f1917df648138730b go1.25.0.freebsd-amd64.tar.gz
|
6cbc3ad6cc21bdcc7283824d3ac0e85512c02022f6a35eb2e844882ea6e8448c go1.24.4.freebsd-amd64.tar.gz
|
||||||
d90b78e41921f72f30e8bbc81d9dec2cff7ff384a33d8d8debb24053e4336bfe go1.25.0.freebsd-arm.tar.gz
|
d49ae050c20aff646a7641dd903f03eb674570790b90ffb298076c4d41e36655 go1.24.4.freebsd-arm.tar.gz
|
||||||
451d0da1affd886bfb291b7c63a6018527b269505db21ce6e14724f22ab0662e go1.25.0.freebsd-arm64.tar.gz
|
e31924abef2a28456b7103c0a5d333dcc11ecf19e76d5de1a383ad5fe0b42457 go1.24.4.freebsd-arm64.tar.gz
|
||||||
7b565f76bd8bda46549eeaaefe0e53b251e644c230577290c0f66b1ecdb3cdbe go1.25.0.freebsd-riscv64.tar.gz
|
b5bca135eae8ebddf22972611ac1c58ae9fbb5979fd953cc5245c5b1b2517546 go1.24.4.freebsd-riscv64.tar.gz
|
||||||
b1e1fdaab1ad25aa1c08d7a36c97d45d74b98b89c3f78c6d2145f77face54a2c go1.25.0.illumos-amd64.tar.gz
|
7d5efda511ff7e3114b130acee5d0bffbb078fedbfa9b2c1b6a807107e1ca23a go1.24.4.illumos-amd64.tar.gz
|
||||||
8c602dd9d99bc9453b3995d20ce4baf382cc50855900a0ece5de9929df4a993a go1.25.0.linux-386.tar.gz
|
130c9b061082eca15513e595e9952a2ded32e737e609dd0e49f7dfa74eba026d go1.24.4.linux-386.tar.gz
|
||||||
2852af0cb20a13139b3448992e69b868e50ed0f8a1e5940ee1de9e19a123b613 go1.25.0.linux-amd64.tar.gz
|
77e5da33bb72aeaef1ba4418b6fe511bc4d041873cbf82e5aa6318740df98717 go1.24.4.linux-amd64.tar.gz
|
||||||
05de75d6994a2783699815ee553bd5a9327d8b79991de36e38b66862782f54ae go1.25.0.linux-arm64.tar.gz
|
d5501ee5aca0f258d5fe9bfaed401958445014495dc115f202d43d5210b45241 go1.24.4.linux-arm64.tar.gz
|
||||||
a5a8f8198fcf00e1e485b8ecef9ee020778bf32a408a4e8873371bfce458cd09 go1.25.0.linux-armv6l.tar.gz
|
6a554e32301cecae3162677e66d4264b81b3b1a89592dd1b7b5c552c7a49fe37 go1.24.4.linux-armv6l.tar.gz
|
||||||
cab86b1cf761b1cb3bac86a8877cfc92e7b036fc0d3084123d77013d61432afc go1.25.0.linux-loong64.tar.gz
|
b208eb25fe244408cbe269ed426454bc46e59d0e0a749b6240d39e884e969875 go1.24.4.linux-loong64.tar.gz
|
||||||
d66b6fb74c3d91b9829dc95ec10ca1f047ef5e89332152f92e136cf0e2da5be1 go1.25.0.linux-mips.tar.gz
|
fddfcb28fd36fe63d2ae181026798f86f3bbd3a7bb0f1e1f617dd3d604bf3fe4 go1.24.4.linux-mips.tar.gz
|
||||||
4082e4381a8661bc2a839ff94ba3daf4f6cde20f8fb771b5b3d4762dc84198a2 go1.25.0.linux-mips64.tar.gz
|
7934b924d5ab8c8ae3134a09a6ae74d3c39f63f6c4322ec289364dbbf0bac3ca go1.24.4.linux-mips64.tar.gz
|
||||||
70002c299ec7f7175ac2ef673b1b347eecfa54ae11f34416a6053c17f855afcc go1.25.0.linux-mips64le.tar.gz
|
fa763d8673f94d6e534bb72c3cf675d4c2b8da4a6da42a89f08c5586106db39c go1.24.4.linux-mips64le.tar.gz
|
||||||
b00a3a39eff099f6df9f1c7355bf28e4589d0586f42d7d4a394efb763d145a73 go1.25.0.linux-mipsle.tar.gz
|
84363dbfe49b41d43df84420a09bd53a4770053d63bfa509868c46a5f8eb3ff7 go1.24.4.linux-mipsle.tar.gz
|
||||||
df166f33bd98160662560a72ff0b4ba731f969a80f088922bddcf566a88c1ec1 go1.25.0.linux-ppc64.tar.gz
|
28fcbd5d3b56493606873c33f2b4bdd84ba93c633f37313613b5a1e6495c6fe5 go1.24.4.linux-ppc64.tar.gz
|
||||||
0f18a89e7576cf2c5fa0b487a1635d9bcbf843df5f110e9982c64df52a983ad0 go1.25.0.linux-ppc64le.tar.gz
|
9ca4afef813a2578c23843b640ae0290aa54b2e3c950a6cc4c99e16a57dec2ec go1.24.4.linux-ppc64le.tar.gz
|
||||||
c018ff74a2c48d55c8ca9b07c8e24163558ffec8bea08b326d6336905d956b67 go1.25.0.linux-riscv64.tar.gz
|
1d7034f98662d8f2c8abd7c700ada4093acb4f9c00e0e51a30344821d0785c77 go1.24.4.linux-riscv64.tar.gz
|
||||||
34e5a2e19f2292fbaf8783e3a241e6e49689276aef6510a8060ea5ef54eee408 go1.25.0.linux-s390x.tar.gz
|
0449f3203c39703ab27684be763e9bb78ca9a051e0e4176727aead9461b6deb5 go1.24.4.linux-s390x.tar.gz
|
||||||
f8586cdb7aa855657609a5c5f6dbf523efa00c2bbd7c76d3936bec80aa6c0aba go1.25.0.netbsd-386.tar.gz
|
954b49ccc2cfcf4b5f7cd33ff662295e0d3b74e7590c8e25fc2abb30bce120ba go1.24.4.netbsd-386.tar.gz
|
||||||
ae8dc1469385b86a157a423bb56304ba45730de8a897615874f57dd096db2c2a go1.25.0.netbsd-amd64.tar.gz
|
370fabcdfee7c18857c96fdd5b706e025d4fb86a208da88ba56b1493b35498e9 go1.24.4.netbsd-amd64.tar.gz
|
||||||
1ff7e4cc764425fc9dd6825eaee79d02b3c7cafffbb3691687c8d672ade76cb7 go1.25.0.netbsd-arm.tar.gz
|
7935ef95d4d1acc48587b1eb4acab98b0a7d9569736a32398b9c1d2e89026865 go1.24.4.netbsd-arm.tar.gz
|
||||||
e1b310739f26724216aa6d7d7208c4031f9ff54c9b5b9a796ddc8bebcb4a5f16 go1.25.0.netbsd-arm64.tar.gz
|
ead78fd0fa29fbb176cc83f1caa54032e1a44f842affa56a682c647e0759f237 go1.24.4.netbsd-arm64.tar.gz
|
||||||
4802a9b20e533da91adb84aab42e94aa56cfe3e5475d0550bed3385b182e69d8 go1.25.0.openbsd-386.tar.gz
|
913e217394b851a636b99de175f0c2f9ab9938b41c557f047168f77ee485d776 go1.24.4.openbsd-386.tar.gz
|
||||||
c016cd984bebe317b19a4f297c4f50def120dc9788490540c89f28e42f1dabe1 go1.25.0.openbsd-amd64.tar.gz
|
24568da3dcbcdb24ec18b631f072faf0f3763e3d04f79032dc56ad9ec35379c4 go1.24.4.openbsd-amd64.tar.gz
|
||||||
a1e31d0bf22172ddde42edf5ec811ef81be43433df0948ece52fecb247ccfd8d go1.25.0.openbsd-arm.tar.gz
|
45abf523f870632417ab007de3841f64dd906bde546ffc8c6380ccbe91c7fb73 go1.24.4.openbsd-arm.tar.gz
|
||||||
343ea8edd8c218196e15a859c6072d0dd3246fbbb168481ab665eb4c4140458d go1.25.0.openbsd-arm64.tar.gz
|
7c57c69b5dd1e946b28a3034c285240a48e2861bdcb50b7d9c0ed61bcf89c879 go1.24.4.openbsd-arm64.tar.gz
|
||||||
694c14da1bcaeb5e3332d49bdc2b6d155067648f8fe1540c5de8f3cf8e157154 go1.25.0.openbsd-ppc64.tar.gz
|
91ed711f704829372d6931e1897631ef40288b8f9e3cd6ef4a24df7126d1066a go1.24.4.openbsd-ppc64.tar.gz
|
||||||
aa510ad25cf54c06cd9c70b6d80ded69cb20188ac6e1735655eef29ff7e7885f go1.25.0.openbsd-riscv64.tar.gz
|
de5e270d971c8790e8880168d56a2ea103979927c10ded136d792bbdf9bce3d3 go1.24.4.openbsd-riscv64.tar.gz
|
||||||
46f8cef02086cf04bf186c5912776b56535178d4cb319cd19c9fdbdd29231986 go1.25.0.plan9-386.tar.gz
|
ff429d03f00bcd32a50f445320b8329d0fadb2a2fff899c11e95e0922a82c543 go1.24.4.plan9-386.tar.gz
|
||||||
29b34391d84095e44608a228f63f2f88113a37b74a79781353ec043dfbcb427b go1.25.0.plan9-amd64.tar.gz
|
39d6363a43fd16b60ae9ad7346a264e982e4fa653dee3b45f83e03cd2f7a6647 go1.24.4.plan9-amd64.tar.gz
|
||||||
0a047107d13ebe7943aaa6d54b1d7bbd2e45e68ce449b52915a818da715799c2 go1.25.0.plan9-arm.tar.gz
|
1964ae2571259de77b930e97f2891aa92706ff81aac9909d45bb107b0fab16c8 go1.24.4.plan9-arm.tar.gz
|
||||||
9977f9e4351984364a3b2b78f8b88bfd1d339812356d5237678514594b7d3611 go1.25.0.solaris-amd64.tar.gz
|
a7f9af424e8fb87886664754badca459513f64f6a321d17f1d219b8edf519821 go1.24.4.solaris-amd64.tar.gz
|
||||||
df9f39db82a803af0db639e3613a36681ab7a42866b1384b3f3a1045663961a7 go1.25.0.windows-386.zip
|
d454d3cb144432f1726bf00e28c6017e78ccb256a8d01b8e3fb1b2e6b5650f28 go1.24.4.windows-386.zip
|
||||||
afd9e0a8d2665ff122c8302bb4a3ce4a5331e4e630ddc388be1f9238adfa8fe3 go1.25.0.windows-386.msi
|
966ecace1cdbb3497a2b930bdb0f90c3ad32922fa1a7c655b2d4bbeb7e4ac308 go1.24.4.windows-386.msi
|
||||||
89efb4f9b30812eee083cc1770fdd2913c14d301064f6454851428f9707d190b go1.25.0.windows-amd64.zip
|
b751a1136cb9d8a2e7ebb22c538c4f02c09b98138c7c8bfb78a54a4566c013b1 go1.24.4.windows-amd64.zip
|
||||||
936bd87109da515f79d80211de5bc6cbda071f2cc577f7e6af1a9e754ea34819 go1.25.0.windows-amd64.msi
|
0cbb6e83865747dbe69b3d4155f92e88fcf336ff5d70182dba145e9d7bd3d8f6 go1.24.4.windows-amd64.msi
|
||||||
27bab004c72b3d7bd05a69b6ec0fc54a309b4b78cc569dd963d8b3ec28bfdb8c go1.25.0.windows-arm64.zip
|
d17da51bc85bd010754a4063215d15d2c033cc289d67ca9201a03c9041b2969d go1.24.4.windows-arm64.zip
|
||||||
357d030b217ff68e700b6cfc56097bc21ad493bb45b79733a052d112f5031ed9 go1.25.0.windows-arm64.msi
|
47dbe734b6a829de45654648a7abcf05bdceef5c80e03ea0b208eeebef75a852 go1.24.4.windows-arm64.msi
|
||||||
|
|
||||||
# version:golangci 2.0.2
|
# version:golangci 2.0.2
|
||||||
# https://github.com/golangci/golangci-lint/releases/
|
# https://github.com/golangci/golangci-lint/releases/
|
||||||
|
|
|
||||||
69
build/ci.go
69
build/ci.go
|
|
@ -64,18 +64,18 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// Files that end up in the geth*.zip archive.
|
// Files that end up in the bera-geth*.zip archive.
|
||||||
gethArchiveFiles = []string{
|
gethArchiveFiles = []string{
|
||||||
"COPYING",
|
"COPYING",
|
||||||
executablePath("geth"),
|
executablePath("bera-geth"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Files that end up in the geth-alltools*.zip archive.
|
// Files that end up in the bera-geth-alltools*.zip archive.
|
||||||
allToolsArchiveFiles = []string{
|
allToolsArchiveFiles = []string{
|
||||||
"COPYING",
|
"COPYING",
|
||||||
executablePath("abigen"),
|
executablePath("abigen"),
|
||||||
executablePath("evm"),
|
executablePath("evm"),
|
||||||
executablePath("geth"),
|
executablePath("bera-geth"),
|
||||||
executablePath("rlpdump"),
|
executablePath("rlpdump"),
|
||||||
executablePath("clef"),
|
executablePath("clef"),
|
||||||
}
|
}
|
||||||
|
|
@ -91,7 +91,7 @@ var (
|
||||||
Description: "Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode.",
|
Description: "Developer utility version of the EVM (Ethereum Virtual Machine) that is capable of running bytecode snippets within a configurable environment and execution mode.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
BinaryName: "geth",
|
BinaryName: "bera-geth",
|
||||||
Description: "Ethereum CLI client.",
|
Description: "Ethereum CLI client.",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -238,6 +238,7 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (
|
||||||
if env.Commit != "" {
|
if env.Commit != "" {
|
||||||
ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitCommit="+env.Commit)
|
ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitCommit="+env.Commit)
|
||||||
ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitDate="+env.Date)
|
ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitDate="+env.Date)
|
||||||
|
ld = append(ld, "-X", "github.com/ethereum/go-ethereum/internal/version.gitTag="+env.Tag)
|
||||||
}
|
}
|
||||||
// Strip DWARF on darwin. This used to be required for certain things,
|
// Strip DWARF on darwin. This used to be required for certain things,
|
||||||
// and there is no downside to this, so we just keep doing it.
|
// and there is no downside to this, so we just keep doing it.
|
||||||
|
|
@ -554,7 +555,7 @@ func doArchive(cmdline []string) {
|
||||||
atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
|
atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
|
||||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
|
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
|
||||||
signify = flag.String("signify", "", `Environment variable holding the signify key (e.g. LINUX_SIGNIFY_KEY)`)
|
signify = flag.String("signify", "", `Environment variable holding the signify key (e.g. LINUX_SIGNIFY_KEY)`)
|
||||||
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
|
upload = flag.String("upload", "", `Destination to upload the archives (usually "berachain/bera-geth")`)
|
||||||
ext string
|
ext string
|
||||||
)
|
)
|
||||||
flag.CommandLine.Parse(cmdline)
|
flag.CommandLine.Parse(cmdline)
|
||||||
|
|
@ -569,9 +570,9 @@ func doArchive(cmdline []string) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
env = build.Env()
|
env = build.Env()
|
||||||
basegeth = archiveBasename(*arch, version.Archive(env.Commit))
|
basegeth = archiveBasename(*arch, version.Archive(env.Tag, env.Commit))
|
||||||
geth = "geth-" + basegeth + ext
|
geth = "bera-geth-" + basegeth + ext
|
||||||
alltools = "geth-alltools-" + basegeth + ext
|
alltools = "bera-geth-alltools-" + basegeth + ext
|
||||||
)
|
)
|
||||||
maybeSkipArchive(env)
|
maybeSkipArchive(env)
|
||||||
if err := build.WriteArchive(geth, gethArchiveFiles); err != nil {
|
if err := build.WriteArchive(geth, gethArchiveFiles); err != nil {
|
||||||
|
|
@ -611,7 +612,7 @@ func archiveUpload(archive string, blobstore string, signer string, signifyVar s
|
||||||
}
|
}
|
||||||
if signifyVar != "" {
|
if signifyVar != "" {
|
||||||
key := os.Getenv(signifyVar)
|
key := os.Getenv(signifyVar)
|
||||||
untrustedComment := "verify with geth-release.pub"
|
untrustedComment := "verify with bera-geth-release.pub"
|
||||||
trustedComment := fmt.Sprintf("%s (%s)", archive, time.Now().UTC().Format(time.RFC1123))
|
trustedComment := fmt.Sprintf("%s (%s)", archive, time.Now().UTC().Format(time.RFC1123))
|
||||||
if err := signify.SignFile(archive, archive+".sig", key, untrustedComment, trustedComment); err != nil {
|
if err := signify.SignFile(archive, archive+".sig", key, untrustedComment, trustedComment); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -647,17 +648,17 @@ func maybeSkipArchive(env build.Environment) {
|
||||||
log.Printf("skipping archive creation because this is a PR build")
|
log.Printf("skipping archive creation because this is a PR build")
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
if env.Branch != "master" && !strings.HasPrefix(env.Tag, "v1.") {
|
if env.Branch != "main" && !strings.HasPrefix(env.Tag, "v1.") {
|
||||||
log.Printf("skipping archive creation because branch %q, tag %q is not on the inclusion list", env.Branch, env.Tag)
|
log.Printf("skipping archive creation because branch %q, tag %q is not on the inclusion list", env.Branch, env.Tag)
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Builds the docker images and optionally uploads them to Docker Hub.
|
// Builds the docker images and optionally uploads them to GHCR.
|
||||||
func doDockerBuildx(cmdline []string) {
|
func doDockerBuildx(cmdline []string) {
|
||||||
var (
|
var (
|
||||||
platform = flag.String("platform", "", `Push a multi-arch docker image for the specified architectures (usually "linux/amd64,linux/arm64")`)
|
platform = flag.String("platform", "", `Push a multi-arch docker image for the specified architectures (usually "linux/amd64,linux/arm64")`)
|
||||||
hubImage = flag.String("hub", "ethereum/client-go", `Where to upload the docker image`)
|
hubImage = flag.String("hub", "ghcr.io/berachain/bera-geth", `Where to upload the docker image`)
|
||||||
upload = flag.Bool("upload", false, `Whether to trigger upload`)
|
upload = flag.Bool("upload", false, `Whether to trigger upload`)
|
||||||
)
|
)
|
||||||
flag.CommandLine.Parse(cmdline)
|
flag.CommandLine.Parse(cmdline)
|
||||||
|
|
@ -676,21 +677,16 @@ func doDockerBuildx(cmdline []string) {
|
||||||
build.MustRun(auther)
|
build.MustRun(auther)
|
||||||
}
|
}
|
||||||
// Retrieve the version infos to build and push to the following paths:
|
// Retrieve the version infos to build and push to the following paths:
|
||||||
// - ethereum/client-go:latest - Pushes to the master branch, Geth only
|
// - ethereum/client-go:latest - Pushes to the main branch, Geth only
|
||||||
// - ethereum/client-go:stable - Version tag publish on GitHub, Geth only
|
// - ethereum/client-go:alltools-latest - Pushes to the main branch, Geth & tools
|
||||||
// - ethereum/client-go:alltools-latest - Pushes to the master branch, Geth & tools
|
|
||||||
// - ethereum/client-go:alltools-stable - Version tag publish on GitHub, Geth & tools
|
|
||||||
// - ethereum/client-go:release-<major>.<minor> - Version tag publish on GitHub, Geth only
|
|
||||||
// - ethereum/client-go:alltools-release-<major>.<minor> - Version tag publish on GitHub, Geth & tools
|
|
||||||
// - ethereum/client-go:v<major>.<minor>.<patch> - Version tag publish on GitHub, Geth only
|
// - ethereum/client-go:v<major>.<minor>.<patch> - Version tag publish on GitHub, Geth only
|
||||||
// - ethereum/client-go:alltools-v<major>.<minor>.<patch> - Version tag publish on GitHub, Geth & tools
|
// - ethereum/client-go:alltools-v<major>.<minor>.<patch> - Version tag publish on GitHub, Geth & tools
|
||||||
var tags []string
|
var tag string
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case env.Branch == "master":
|
case env.Branch == "main":
|
||||||
tags = []string{"latest"}
|
tag = "latest"
|
||||||
case strings.HasPrefix(env.Tag, "v1."):
|
case strings.HasPrefix(env.Tag, "v1."):
|
||||||
tags = []string{"stable", fmt.Sprintf("release-%v", version.Family), "v" + version.Semantic}
|
tag = env.Tag
|
||||||
}
|
}
|
||||||
// Need to create a mult-arch builder
|
// Need to create a mult-arch builder
|
||||||
check := exec.Command("docker", "buildx", "inspect", "multi-arch-builder")
|
check := exec.Command("docker", "buildx", "inspect", "multi-arch-builder")
|
||||||
|
|
@ -705,11 +701,15 @@ func doDockerBuildx(cmdline []string) {
|
||||||
{file: "Dockerfile", base: fmt.Sprintf("%s:", *hubImage)},
|
{file: "Dockerfile", base: fmt.Sprintf("%s:", *hubImage)},
|
||||||
{file: "Dockerfile.alltools", base: fmt.Sprintf("%s:alltools-", *hubImage)},
|
{file: "Dockerfile.alltools", base: fmt.Sprintf("%s:alltools-", *hubImage)},
|
||||||
} {
|
} {
|
||||||
for _, tag := range tags { // latest, stable etc
|
|
||||||
gethImage := fmt.Sprintf("%s%s", spec.base, tag)
|
gethImage := fmt.Sprintf("%s%s", spec.base, tag)
|
||||||
|
// Prefer tag when present for VERSION
|
||||||
|
dockerVersion := version.WithMeta
|
||||||
|
if env.Tag != "" {
|
||||||
|
dockerVersion = env.Tag
|
||||||
|
}
|
||||||
cmd := exec.Command("docker", "buildx", "build",
|
cmd := exec.Command("docker", "buildx", "build",
|
||||||
"--build-arg", "COMMIT="+env.Commit,
|
"--build-arg", "COMMIT="+env.Commit,
|
||||||
"--build-arg", "VERSION="+version.WithMeta,
|
"--build-arg", "VERSION="+dockerVersion,
|
||||||
"--build-arg", "BUILDNUM="+env.Buildnum,
|
"--build-arg", "BUILDNUM="+env.Buildnum,
|
||||||
"--tag", gethImage,
|
"--tag", gethImage,
|
||||||
"--platform", *platform,
|
"--platform", *platform,
|
||||||
|
|
@ -722,7 +722,6 @@ func doDockerBuildx(cmdline []string) {
|
||||||
build.MustRun(cmd)
|
build.MustRun(cmd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Debian Packaging
|
// Debian Packaging
|
||||||
func doDebianSource(cmdline []string) {
|
func doDebianSource(cmdline []string) {
|
||||||
|
|
@ -730,7 +729,7 @@ func doDebianSource(cmdline []string) {
|
||||||
cachedir = flag.String("cachedir", "./build/cache", `Filesystem path to cache the downloaded Go bundles at`)
|
cachedir = flag.String("cachedir", "./build/cache", `Filesystem path to cache the downloaded Go bundles at`)
|
||||||
signer = flag.String("signer", "", `Signing key name, also used as package author`)
|
signer = flag.String("signer", "", `Signing key name, also used as package author`)
|
||||||
upload = flag.String("upload", "", `Where to upload the source package (usually "ethereum/ethereum")`)
|
upload = flag.String("upload", "", `Where to upload the source package (usually "ethereum/ethereum")`)
|
||||||
sshUser = flag.String("sftp-user", "", `Username for SFTP upload (usually "geth-ci")`)
|
sshUser = flag.String("sftp-user", "", `Username for SFTP upload (usually "bera-geth-ci")`)
|
||||||
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
|
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
|
||||||
now = time.Now()
|
now = time.Now()
|
||||||
)
|
)
|
||||||
|
|
@ -889,7 +888,7 @@ func makeWorkdir(wdflag string) string {
|
||||||
if wdflag != "" {
|
if wdflag != "" {
|
||||||
err = os.MkdirAll(wdflag, 0744)
|
err = os.MkdirAll(wdflag, 0744)
|
||||||
} else {
|
} else {
|
||||||
wdflag, err = os.MkdirTemp("", "geth-build-")
|
wdflag, err = os.MkdirTemp("", "bera-geth-build-")
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
@ -1043,7 +1042,7 @@ func doWindowsInstaller(cmdline []string) {
|
||||||
arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging")
|
arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging")
|
||||||
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`)
|
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`)
|
||||||
signify = flag.String("signify key", "", `Environment variable holding the signify signing key (e.g. WINDOWS_SIGNIFY_KEY)`)
|
signify = flag.String("signify key", "", `Environment variable holding the signify signing key (e.g. WINDOWS_SIGNIFY_KEY)`)
|
||||||
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
|
upload = flag.String("upload", "", `Destination to upload the archives (usually "berachain/bera-geth")`)
|
||||||
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
|
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
|
||||||
)
|
)
|
||||||
flag.CommandLine.Parse(cmdline)
|
flag.CommandLine.Parse(cmdline)
|
||||||
|
|
@ -1062,7 +1061,7 @@ func doWindowsInstaller(cmdline []string) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
allTools = append(allTools, filepath.Base(file))
|
allTools = append(allTools, filepath.Base(file))
|
||||||
if filepath.Base(file) == "geth.exe" {
|
if filepath.Base(file) == "bera-geth.exe" {
|
||||||
gethTool = file
|
gethTool = file
|
||||||
} else {
|
} else {
|
||||||
devTools = append(devTools, file)
|
devTools = append(devTools, file)
|
||||||
|
|
@ -1076,7 +1075,7 @@ func doWindowsInstaller(cmdline []string) {
|
||||||
"Geth": gethTool,
|
"Geth": gethTool,
|
||||||
"DevTools": devTools,
|
"DevTools": devTools,
|
||||||
}
|
}
|
||||||
build.Render("build/nsis.geth.nsi", filepath.Join(*workdir, "geth.nsi"), 0644, nil)
|
build.Render("build/nsis.geth.nsi", filepath.Join(*workdir, "bera-geth.nsi"), 0644, nil)
|
||||||
build.Render("build/nsis.install.nsh", filepath.Join(*workdir, "install.nsh"), 0644, templateData)
|
build.Render("build/nsis.install.nsh", filepath.Join(*workdir, "install.nsh"), 0644, templateData)
|
||||||
build.Render("build/nsis.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, allTools)
|
build.Render("build/nsis.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, allTools)
|
||||||
build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil)
|
build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil)
|
||||||
|
|
@ -1094,7 +1093,7 @@ func doWindowsInstaller(cmdline []string) {
|
||||||
if env.Commit != "" {
|
if env.Commit != "" {
|
||||||
ver[2] += "-" + env.Commit[:8]
|
ver[2] += "-" + env.Commit[:8]
|
||||||
}
|
}
|
||||||
installer, err := filepath.Abs("geth-" + archiveBasename(*arch, version.Archive(env.Commit)) + ".exe")
|
installer, err := filepath.Abs("bera-geth-" + archiveBasename(*arch, version.Archive(env.Tag, env.Commit)) + ".exe")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed to convert installer file path: %v", err)
|
log.Fatalf("Failed to convert installer file path: %v", err)
|
||||||
}
|
}
|
||||||
|
|
@ -1104,7 +1103,7 @@ func doWindowsInstaller(cmdline []string) {
|
||||||
"/DMINORVERSION="+ver[1],
|
"/DMINORVERSION="+ver[1],
|
||||||
"/DBUILDVERSION="+ver[2],
|
"/DBUILDVERSION="+ver[2],
|
||||||
"/DARCH="+*arch,
|
"/DARCH="+*arch,
|
||||||
filepath.Join(*workdir, "geth.nsi"),
|
filepath.Join(*workdir, "bera-geth.nsi"),
|
||||||
)
|
)
|
||||||
// Sign and publish installer.
|
// Sign and publish installer.
|
||||||
if err := archiveUpload(installer, *upload, *signer, *signify); err != nil {
|
if err := archiveUpload(installer, *upload, *signer, *signify); err != nil {
|
||||||
|
|
@ -1116,7 +1115,7 @@ func doWindowsInstaller(cmdline []string) {
|
||||||
|
|
||||||
func doPurge(cmdline []string) {
|
func doPurge(cmdline []string) {
|
||||||
var (
|
var (
|
||||||
store = flag.String("store", "", `Destination from where to purge archives (usually "gethstore/builds")`)
|
store = flag.String("store", "", `Destination from where to purge archives (usually "berachain/bera-geth")`)
|
||||||
limit = flag.Int("days", 30, `Age threshold above which to delete unstable archives`)
|
limit = flag.Int("days", 30, `Age threshold above which to delete unstable archives`)
|
||||||
)
|
)
|
||||||
flag.CommandLine.Parse(cmdline)
|
flag.CommandLine.Parse(cmdline)
|
||||||
|
|
|
||||||
32
circle.yml
32
circle.yml
|
|
@ -1,32 +0,0 @@
|
||||||
machine:
|
|
||||||
services:
|
|
||||||
- docker
|
|
||||||
|
|
||||||
dependencies:
|
|
||||||
cache_directories:
|
|
||||||
- "~/.ethash" # Cache the ethash DAG generated by hive for consecutive builds
|
|
||||||
- "~/.docker" # Cache all docker images manually to avoid lengthy rebuilds
|
|
||||||
override:
|
|
||||||
# Restore all previously cached docker images
|
|
||||||
- mkdir -p ~/.docker
|
|
||||||
- for img in `ls ~/.docker`; do docker load -i ~/.docker/$img; done
|
|
||||||
|
|
||||||
# Pull in and hive, restore cached ethash DAGs and do a dry run
|
|
||||||
- go get -u github.com/karalabe/hive
|
|
||||||
- (cd ~/.go_workspace/src/github.com/karalabe/hive && mkdir -p workspace/ethash/ ~/.ethash)
|
|
||||||
- (cd ~/.go_workspace/src/github.com/karalabe/hive && cp -r ~/.ethash/. workspace/ethash/)
|
|
||||||
- (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=NONE --test=. --sim=. --loglevel=6)
|
|
||||||
|
|
||||||
# Cache all the docker images and the ethash DAGs
|
|
||||||
- for img in `docker images | grep -v "^<none>" | tail -n +2 | awk '{print $1}'`; do docker save $img > ~/.docker/`echo $img | tr '/' ':'`.tar; done
|
|
||||||
- cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/ethash/. ~/.ethash
|
|
||||||
|
|
||||||
test:
|
|
||||||
override:
|
|
||||||
# Build Geth and move into a known folder
|
|
||||||
- make geth
|
|
||||||
- cp ./build/bin/geth $HOME/geth
|
|
||||||
|
|
||||||
# Run hive and move all generated logs into the public artifacts folder
|
|
||||||
- (cd ~/.go_workspace/src/github.com/karalabe/hive && hive --docker-noshell --client=go-ethereum:local --override=$HOME/geth --test=. --sim=.)
|
|
||||||
- cp -r ~/.go_workspace/src/github.com/karalabe/hive/workspace/logs/* $CIRCLE_ARTIFACTS
|
|
||||||
|
|
@ -47,6 +47,7 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/node"
|
"github.com/ethereum/go-ethereum/node"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/triedb"
|
||||||
"github.com/urfave/cli/v2"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -282,8 +283,19 @@ func initGenesis(ctx *cli.Context) error {
|
||||||
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
chaindb := utils.MakeChainDatabase(ctx, stack, false)
|
||||||
defer chaindb.Close()
|
defer chaindb.Close()
|
||||||
|
|
||||||
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
// Berachain: Check if genesis already exists for PBSS databases BEFORE opening trie database.
|
||||||
|
// This prevents the state history truncation that happens during trie database initialization.
|
||||||
|
var triedb *triedb.Database
|
||||||
|
if rawdb.ReadStateScheme(chaindb) == rawdb.PathScheme &&
|
||||||
|
rawdb.ReadChainConfig(chaindb, rawdb.ReadCanonicalHash(chaindb, 0)) != nil {
|
||||||
|
log.Info("PBSS db already initialized with genesis, skipping trie db initialization")
|
||||||
|
} else {
|
||||||
|
// Only create triedb if we're not using PBSS or genesis is empty on disk. Refer to
|
||||||
|
// https://github.com/ethereum/go-ethereum/pull/25523 for why the triedb cannot be
|
||||||
|
// re-created when using PBSS.
|
||||||
|
triedb = utils.MakeTrieDatabase(ctx, stack, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
|
||||||
defer triedb.Close()
|
defer triedb.Close()
|
||||||
|
}
|
||||||
|
|
||||||
_, hash, compatErr, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
_, hash, compatErr, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -480,6 +492,10 @@ func importHistory(ctx *cli.Context) error {
|
||||||
network = "holesky"
|
network = "holesky"
|
||||||
case ctx.Bool(utils.HoodiFlag.Name):
|
case ctx.Bool(utils.HoodiFlag.Name):
|
||||||
network = "hoodi"
|
network = "hoodi"
|
||||||
|
case ctx.Bool(utils.BerachainFlag.Name):
|
||||||
|
network = "berachain"
|
||||||
|
case ctx.Bool(utils.BepoliaFlag.Name):
|
||||||
|
network = "bepolia"
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// No network flag set, try to determine network based on files
|
// No network flag set, try to determine network based on files
|
||||||
|
|
@ -716,6 +732,10 @@ func downloadEra(ctx *cli.Context) error {
|
||||||
case ctx.IsSet(utils.MainnetFlag.Name):
|
case ctx.IsSet(utils.MainnetFlag.Name):
|
||||||
case ctx.IsSet(utils.SepoliaFlag.Name):
|
case ctx.IsSet(utils.SepoliaFlag.Name):
|
||||||
network = "sepolia"
|
network = "sepolia"
|
||||||
|
case ctx.IsSet(utils.BerachainFlag.Name):
|
||||||
|
network = "berachain"
|
||||||
|
case ctx.IsSet(utils.BepoliaFlag.Name):
|
||||||
|
network = "bepolia"
|
||||||
default:
|
default:
|
||||||
return errors.New("unsupported network, no known era1 checksums")
|
return errors.New("unsupported network, no known era1 checksums")
|
||||||
}
|
}
|
||||||
|
|
@ -131,7 +131,13 @@ func defaultNodeConfig() node.Config {
|
||||||
git, _ := version.VCS()
|
git, _ := version.VCS()
|
||||||
cfg := node.DefaultConfig
|
cfg := node.DefaultConfig
|
||||||
cfg.Name = clientIdentifier
|
cfg.Name = clientIdentifier
|
||||||
cfg.Version = version.WithCommit(git.Commit, git.Date)
|
// Prefer git tag for the advertised version (used in web3_clientVersion),
|
||||||
|
// trimming any leading 'v' because NodeName adds the 'v' prefix itself.
|
||||||
|
ver := version.WithMeta
|
||||||
|
if git.Tag != "" {
|
||||||
|
ver = strings.TrimPrefix(git.Tag, "v")
|
||||||
|
}
|
||||||
|
cfg.Version = ver
|
||||||
cfg.HTTPModules = append(cfg.HTTPModules, "eth")
|
cfg.HTTPModules = append(cfg.HTTPModules, "eth")
|
||||||
cfg.WSModules = append(cfg.WSModules, "eth")
|
cfg.WSModules = append(cfg.WSModules, "eth")
|
||||||
cfg.IPCPath = clientIdentifier + ".ipc"
|
cfg.IPCPath = clientIdentifier + ".ipc"
|
||||||
|
|
@ -69,7 +69,7 @@ func TestConsoleWelcome(t *testing.T) {
|
||||||
geth.Expect(`
|
geth.Expect(`
|
||||||
Welcome to the Geth JavaScript console!
|
Welcome to the Geth JavaScript console!
|
||||||
|
|
||||||
instance: Geth/v{{gethver}}/{{goos}}-{{goarch}}/{{gover}}
|
instance: BeraGeth/v{{gethver}}/{{goos}}-{{goarch}}/{{gover}}
|
||||||
at block: 0 ({{niltime}})
|
at block: 0 ({{niltime}})
|
||||||
datadir: {{.Datadir}}
|
datadir: {{.Datadir}}
|
||||||
modules: {{apis}}
|
modules: {{apis}}
|
||||||
|
|
@ -89,9 +89,9 @@ func TestAttachWelcome(t *testing.T) {
|
||||||
)
|
)
|
||||||
// Configure the instance for IPC attachment
|
// Configure the instance for IPC attachment
|
||||||
if runtime.GOOS == "windows" {
|
if runtime.GOOS == "windows" {
|
||||||
ipc = `\\.\pipe\geth` + strconv.Itoa(trulyRandInt(100000, 999999))
|
ipc = `\\.\pipe\bera-geth` + strconv.Itoa(trulyRandInt(100000, 999999))
|
||||||
} else {
|
} else {
|
||||||
ipc = filepath.Join(t.TempDir(), "geth.ipc")
|
ipc = filepath.Join(t.TempDir(), "bera-geth.ipc")
|
||||||
}
|
}
|
||||||
// And HTTP + WS attachment
|
// And HTTP + WS attachment
|
||||||
p := trulyRandInt(1024, 65533) // Yeah, sometimes this will fail, sorry :P
|
p := trulyRandInt(1024, 65533) // Yeah, sometimes this will fail, sorry :P
|
||||||
|
|
@ -140,7 +140,7 @@ func testAttachWelcome(t *testing.T, geth *testgeth, endpoint, apis string) {
|
||||||
attach.Expect(`
|
attach.Expect(`
|
||||||
Welcome to the Geth JavaScript console!
|
Welcome to the Geth JavaScript console!
|
||||||
|
|
||||||
instance: Geth/v{{gethver}}/{{goos}}-{{goarch}}/{{gover}}
|
instance: BeraGeth/v{{gethver}}/{{goos}}-{{goarch}}/{{gover}}
|
||||||
at block: 0 ({{niltime}}){{if ipc}}
|
at block: 0 ({{niltime}}){{if ipc}}
|
||||||
datadir: {{datadir}}{{end}}
|
datadir: {{datadir}}{{end}}
|
||||||
modules: {{apis}}
|
modules: {{apis}}
|
||||||
|
|
@ -21,6 +21,7 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -97,6 +98,142 @@ func TestCustomGenesis(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestPBSSRepeatInitNoTrieOpen verifies that running init twice on a PBSS (path-scheme)
|
||||||
|
// database does not re-initialize the trie database and safely short-circuits.
|
||||||
|
func TestPBSSRepeatInitNoTrieOpen(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Minimal genesis with TTD=0 to keep execution simple
|
||||||
|
genesis := `{
|
||||||
|
"alloc": {"0x0000000000000000000000000000000000000001": {"balance": "0x1"}},
|
||||||
|
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||||
|
"difficulty": "0x1",
|
||||||
|
"gasLimit": "0x2fefd8",
|
||||||
|
"nonce": "0x0000000000000000",
|
||||||
|
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"timestamp": "0x00",
|
||||||
|
"config": { "terminalTotalDifficulty": 0 }
|
||||||
|
}`
|
||||||
|
|
||||||
|
datadir := t.TempDir()
|
||||||
|
jsonPath := filepath.Join(datadir, "genesis.json")
|
||||||
|
if err := os.WriteFile(jsonPath, []byte(genesis), 0600); err != nil {
|
||||||
|
t.Fatalf("failed to write genesis file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// First init should perform normal initialization
|
||||||
|
gethInit1 := runGeth(t, "--datadir", datadir, "init", jsonPath)
|
||||||
|
gethInit1.WaitExit()
|
||||||
|
if gethInit1.Err != nil {
|
||||||
|
t.Fatalf("first init failed: %v", gethInit1.Err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second init should skip trie db initialization and not truncate freezer
|
||||||
|
gethInit2 := runGeth(t, "--datadir", datadir, "init", jsonPath)
|
||||||
|
gethInit2.WaitExit()
|
||||||
|
if gethInit2.Err != nil {
|
||||||
|
t.Fatalf("second init failed: %v", gethInit2.Err)
|
||||||
|
}
|
||||||
|
stderr := gethInit2.StderrText()
|
||||||
|
if !strings.Contains(stderr, "PBSS db already initialized with genesis, skipping trie db initialization") {
|
||||||
|
t.Fatalf("expected skip-triedb log not found in stderr. got:\n%s", stderr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestPBSSConfigUpdate verifies that a repeat init on PBSS writes updated chain
|
||||||
|
// configuration without touching the trie database when the genesis block hash
|
||||||
|
// is unchanged.
|
||||||
|
func TestPBSSConfigUpdate(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
// Base genesis (no Prague1 yet). Include all prior timestamp forks explicitly
|
||||||
|
// with timestamp 0 to satisfy fork ordering: Shanghai -> Cancun -> Prague -> Prague1.
|
||||||
|
baseGenesis := `{
|
||||||
|
"alloc": {"0x0000000000000000000000000000000000000001": {"balance": "0x1"}},
|
||||||
|
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||||
|
"difficulty": "0x1",
|
||||||
|
"gasLimit": "0x2fefd8",
|
||||||
|
"nonce": "0x0000000000000000",
|
||||||
|
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"timestamp": "0x00",
|
||||||
|
"config": {
|
||||||
|
"terminalTotalDifficulty": 0,
|
||||||
|
"homesteadBlock": 0,
|
||||||
|
"eip150Block": 0,
|
||||||
|
"eip155Block": 0,
|
||||||
|
"eip158Block": 0,
|
||||||
|
"byzantiumBlock": 0,
|
||||||
|
"constantinopleBlock": 0,
|
||||||
|
"petersburgBlock": 0,
|
||||||
|
"istanbulBlock": 0,
|
||||||
|
"berlinBlock": 0,
|
||||||
|
"londonBlock": 0,
|
||||||
|
"shanghaiTime": 0
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
// Updated config: enable Berachain Prague1 while keeping genesis state identical.
|
||||||
|
// Include all prior timestamp forks to maintain correct ordering.
|
||||||
|
updatedGenesis := `{
|
||||||
|
"alloc": {"0x0000000000000000000000000000000000000001": {"balance": "0x1"}},
|
||||||
|
"coinbase": "0x0000000000000000000000000000000000000000",
|
||||||
|
"difficulty": "0x1",
|
||||||
|
"gasLimit": "0x2fefd8",
|
||||||
|
"nonce": "0x0000000000000000",
|
||||||
|
"mixhash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
|
||||||
|
"timestamp": "0x00",
|
||||||
|
"config": {
|
||||||
|
"terminalTotalDifficulty": 0,
|
||||||
|
"homesteadBlock": 0,
|
||||||
|
"eip150Block": 0,
|
||||||
|
"eip155Block": 0,
|
||||||
|
"eip158Block": 0,
|
||||||
|
"byzantiumBlock": 0,
|
||||||
|
"constantinopleBlock": 0,
|
||||||
|
"petersburgBlock": 0,
|
||||||
|
"istanbulBlock": 0,
|
||||||
|
"berlinBlock": 0,
|
||||||
|
"londonBlock": 0,
|
||||||
|
"shanghaiTime": 0,
|
||||||
|
"berachain": {
|
||||||
|
"prague1": {
|
||||||
|
"time": 1000,
|
||||||
|
"baseFeeChangeDenominator": 48,
|
||||||
|
"poLDistributorAddress": "0x1111111111111111111111111111111111111111"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
datadir := t.TempDir()
|
||||||
|
jsonPath := filepath.Join(datadir, "genesis.json")
|
||||||
|
if err := os.WriteFile(jsonPath, []byte(baseGenesis), 0600); err != nil {
|
||||||
|
t.Fatalf("failed to write base genesis file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// First init with base config
|
||||||
|
runGeth(t, "--datadir", datadir, "init", jsonPath).WaitExit()
|
||||||
|
|
||||||
|
// Overwrite with updated config (same genesis state, different chain config)
|
||||||
|
if err := os.WriteFile(jsonPath, []byte(updatedGenesis), 0600); err != nil {
|
||||||
|
t.Fatalf("failed to write updated genesis file: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second init should skip trie db init and write the new chain config
|
||||||
|
geth := runGeth(t, "--datadir", datadir, "init", jsonPath)
|
||||||
|
geth.WaitExit()
|
||||||
|
stderr := geth.StderrText()
|
||||||
|
if !strings.Contains(stderr, "PBSS db already initialized with genesis, skipping trie db initialization") {
|
||||||
|
t.Fatalf("expected PBSS skip log not found in stderr. got:\n%s", stderr)
|
||||||
|
}
|
||||||
|
if !strings.Contains(stderr, "Writing new chain config") {
|
||||||
|
t.Fatalf("expected config-update log not found in stderr. got:\n%s", stderr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TestCustomBackend that the backend selection and detection (leveldb vs pebble) works properly.
|
// TestCustomBackend that the backend selection and detection (leveldb vs pebble) works properly.
|
||||||
func TestCustomBackend(t *testing.T) {
|
func TestCustomBackend(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
@ -186,9 +323,9 @@ func TestCustomBackend(t *testing.T) {
|
||||||
{ // Reject invalid backend choice
|
{ // Reject invalid backend choice
|
||||||
initArgs: []string{"--db.engine", "mssql"},
|
initArgs: []string{"--db.engine", "mssql"},
|
||||||
initExpect: `Fatal: Invalid choice for db.engine 'mssql', allowed 'leveldb' or 'pebble'`,
|
initExpect: `Fatal: Invalid choice for db.engine 'mssql', allowed 'leveldb' or 'pebble'`,
|
||||||
// Since the init fails, this will return the (default) mainnet genesis
|
// Since the init fails, this will return the (default) berachain mainnet genesis
|
||||||
// block nonce
|
// block nonce
|
||||||
execExpect: `0x0000000000000042`,
|
execExpect: `0x0000000000001234`,
|
||||||
},
|
},
|
||||||
} {
|
} {
|
||||||
if err := testfunc(t, tt); err != nil {
|
if err := testfunc(t, tt); err != nil {
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// geth is a command-line client for Ethereum.
|
// bera-geth is a command-line client for Ethereum.
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
|
@ -46,7 +46,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
clientIdentifier = "geth" // Client identifier to advertise over the network
|
clientIdentifier = "bera-geth" // Client identifier to advertise over the network
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
|
@ -208,7 +208,7 @@ var app = flags.NewApp("the go-ethereum command line interface")
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
// Initialize the CLI app and start Geth
|
// Initialize the CLI app and start Geth
|
||||||
app.Action = geth
|
app.Action = berageth
|
||||||
app.Commands = []*cli.Command{
|
app.Commands = []*cli.Command{
|
||||||
// See chaincmd.go:
|
// See chaincmd.go:
|
||||||
initCommand,
|
initCommand,
|
||||||
|
|
@ -256,7 +256,7 @@ func init() {
|
||||||
debug.Flags,
|
debug.Flags,
|
||||||
metricsFlags,
|
metricsFlags,
|
||||||
)
|
)
|
||||||
flags.AutoEnvVars(app.Flags, "GETH")
|
flags.AutoEnvVars(app.Flags, "BERA_GETH")
|
||||||
|
|
||||||
app.Before = func(ctx *cli.Context) error {
|
app.Before = func(ctx *cli.Context) error {
|
||||||
maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota.
|
maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota.
|
||||||
|
|
@ -264,7 +264,7 @@ func init() {
|
||||||
if err := debug.Setup(ctx); err != nil {
|
if err := debug.Setup(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
flags.CheckEnvVars(ctx, app.Flags, "GETH")
|
flags.CheckEnvVars(ctx, app.Flags, "BERA_GETH")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
app.After = func(ctx *cli.Context) error {
|
app.After = func(ctx *cli.Context) error {
|
||||||
|
|
@ -286,24 +286,32 @@ func main() {
|
||||||
func prepare(ctx *cli.Context) {
|
func prepare(ctx *cli.Context) {
|
||||||
// If we're running a known preset, log it for convenience.
|
// If we're running a known preset, log it for convenience.
|
||||||
switch {
|
switch {
|
||||||
|
case ctx.IsSet(utils.MainnetFlag.Name):
|
||||||
|
log.Info("Starting bera-geth on Ethereum mainnet...")
|
||||||
|
|
||||||
case ctx.IsSet(utils.SepoliaFlag.Name):
|
case ctx.IsSet(utils.SepoliaFlag.Name):
|
||||||
log.Info("Starting Geth on Sepolia testnet...")
|
log.Info("Starting bera-geth on Sepolia testnet...")
|
||||||
|
|
||||||
case ctx.IsSet(utils.HoleskyFlag.Name):
|
case ctx.IsSet(utils.HoleskyFlag.Name):
|
||||||
log.Info("Starting Geth on Holesky testnet...")
|
log.Info("Starting bera-geth on Holesky testnet...")
|
||||||
|
|
||||||
case ctx.IsSet(utils.HoodiFlag.Name):
|
case ctx.IsSet(utils.HoodiFlag.Name):
|
||||||
log.Info("Starting Geth on Hoodi testnet...")
|
log.Info("Starting bera-geth on Hoodi testnet...")
|
||||||
|
|
||||||
case !ctx.IsSet(utils.NetworkIdFlag.Name):
|
case ctx.IsSet(utils.BepoliaFlag.Name):
|
||||||
log.Info("Starting Geth on Ethereum mainnet...")
|
log.Info("Starting bera-geth on Bepolia testnet...")
|
||||||
|
|
||||||
|
case ctx.IsSet(utils.BerachainFlag.Name):
|
||||||
|
log.Info("Starting bera-geth on Berachain mainnet...")
|
||||||
}
|
}
|
||||||
// If we're a full node on mainnet without --cache specified, bump default cache allowance
|
|
||||||
|
// If we're a full node on Berachain mainnet without --cache specified, bump default cache allowance
|
||||||
if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
if !ctx.IsSet(utils.CacheFlag.Name) && !ctx.IsSet(utils.NetworkIdFlag.Name) {
|
||||||
// Make sure we're not on any supported preconfigured testnet either
|
// Make sure we're not on any supported preconfigured testnet either
|
||||||
if !ctx.IsSet(utils.HoleskyFlag.Name) &&
|
if !ctx.IsSet(utils.HoleskyFlag.Name) &&
|
||||||
!ctx.IsSet(utils.SepoliaFlag.Name) &&
|
!ctx.IsSet(utils.SepoliaFlag.Name) &&
|
||||||
!ctx.IsSet(utils.HoodiFlag.Name) &&
|
!ctx.IsSet(utils.HoodiFlag.Name) &&
|
||||||
|
!ctx.IsSet(utils.BepoliaFlag.Name) &&
|
||||||
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
!ctx.IsSet(utils.DeveloperFlag.Name) {
|
||||||
// Nope, we're really on mainnet. Bump that cache up!
|
// Nope, we're really on mainnet. Bump that cache up!
|
||||||
log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)
|
log.Info("Bumping default cache on mainnet", "provided", ctx.Int(utils.CacheFlag.Name), "updated", 4096)
|
||||||
|
|
@ -312,10 +320,10 @@ func prepare(ctx *cli.Context) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// geth is the main entry point into the system if no special subcommand is run.
|
// berageth is the main entry point into the system if no special subcommand is run.
|
||||||
// It creates a default node based on the command line arguments and runs it in
|
// It creates a default node based on the command line arguments and runs it in
|
||||||
// blocking mode, waiting for it to be shut down.
|
// blocking mode, waiting for it to be shut down.
|
||||||
func geth(ctx *cli.Context) error {
|
func berageth(ctx *cli.Context) error {
|
||||||
if args := ctx.Args().Slice(); len(args) > 0 {
|
if args := ctx.Args().Slice(); len(args) > 0 {
|
||||||
return fmt.Errorf("invalid command: %q", args[0])
|
return fmt.Errorf("invalid command: %q", args[0])
|
||||||
}
|
}
|
||||||
|
|
@ -343,7 +351,7 @@ func startNode(ctx *cli.Context, stack *node.Node, isConsole bool) {
|
||||||
events := make(chan accounts.WalletEvent, 16)
|
events := make(chan accounts.WalletEvent, 16)
|
||||||
stack.AccountManager().Subscribe(events)
|
stack.AccountManager().Subscribe(events)
|
||||||
|
|
||||||
// Create a client to interact with local geth node.
|
// Create a client to interact with local bera-geth node.
|
||||||
rpcClient := stack.Attach()
|
rpcClient := stack.Attach()
|
||||||
ethClient := ethclient.NewClient(rpcClient)
|
ethClient := ethclient.NewClient(rpcClient)
|
||||||
|
|
||||||
|
|
@ -72,7 +72,12 @@ func printVersion(ctx *cli.Context) error {
|
||||||
git, _ := version.VCS()
|
git, _ := version.VCS()
|
||||||
|
|
||||||
fmt.Println(strings.Title(clientIdentifier))
|
fmt.Println(strings.Title(clientIdentifier))
|
||||||
|
// Use git tag if available, otherwise fall back to hardcoded version
|
||||||
|
if git.Tag != "" {
|
||||||
|
fmt.Println("Version:", git.Tag)
|
||||||
|
} else {
|
||||||
fmt.Println("Version:", version.WithMeta)
|
fmt.Println("Version:", version.WithMeta)
|
||||||
|
}
|
||||||
if git.Commit != "" {
|
if git.Commit != "" {
|
||||||
fmt.Println("Git Commit:", git.Commit)
|
fmt.Println("Git Commit:", git.Commit)
|
||||||
}
|
}
|
||||||
|
|
@ -236,6 +236,10 @@ func ethFilter(args []string) (nodeFilter, error) {
|
||||||
filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock())
|
filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock())
|
||||||
case "hoodi":
|
case "hoodi":
|
||||||
filter = forkid.NewStaticFilter(params.HoodiChainConfig, core.DefaultHoodiGenesisBlock().ToBlock())
|
filter = forkid.NewStaticFilter(params.HoodiChainConfig, core.DefaultHoodiGenesisBlock().ToBlock())
|
||||||
|
case "berachain":
|
||||||
|
filter = forkid.NewStaticFilter(params.BerachainChainConfig, core.DefaultBerachainGenesisBlock().ToBlock())
|
||||||
|
case "bepolia":
|
||||||
|
filter = forkid.NewStaticFilter(params.BepoliaChainConfig, core.DefaultBepoliaGenesisBlock().ToBlock())
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown network %q", args[0])
|
return nil, fmt.Errorf("unknown network %q", args[0])
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ type header struct {
|
||||||
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
|
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type headerMarshaling struct {
|
type headerMarshaling struct {
|
||||||
|
|
@ -136,6 +137,7 @@ func (i *bbInput) ToBlock() *types.Block {
|
||||||
BlobGasUsed: i.Header.BlobGasUsed,
|
BlobGasUsed: i.Header.BlobGasUsed,
|
||||||
ExcessBlobGas: i.Header.ExcessBlobGas,
|
ExcessBlobGas: i.Header.ExcessBlobGas,
|
||||||
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
|
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
|
||||||
|
ParentProposerPubkey: i.Header.ParentProposerPubkey,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill optional values.
|
// Fill optional values.
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,7 @@ type stEnv struct {
|
||||||
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type stEnvMarshaling struct {
|
type stEnvMarshaling struct {
|
||||||
|
|
@ -220,6 +221,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
|
||||||
)
|
)
|
||||||
core.ProcessParentBlockHash(prevHash, evm)
|
core.ProcessParentBlockHash(prevHash, evm)
|
||||||
}
|
}
|
||||||
|
// TODO(BRIP-4): Validate Prague1 block rules.
|
||||||
for i := 0; txIt.Next(); i++ {
|
for i := 0; txIt.Next(); i++ {
|
||||||
tx, err := txIt.Tx()
|
tx, err := txIt.Tx()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ func (h header) MarshalJSON() ([]byte, error) {
|
||||||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
|
||||||
}
|
}
|
||||||
var enc header
|
var enc header
|
||||||
enc.ParentHash = h.ParentHash
|
enc.ParentHash = h.ParentHash
|
||||||
|
|
@ -60,6 +61,7 @@ func (h header) MarshalJSON() ([]byte, error) {
|
||||||
enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed)
|
enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed)
|
||||||
enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas)
|
enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas)
|
||||||
enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot
|
enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot
|
||||||
|
enc.ParentProposerPubkey = h.ParentProposerPubkey
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -86,6 +88,7 @@ func (h *header) UnmarshalJSON(input []byte) error {
|
||||||
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
|
||||||
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
|
||||||
}
|
}
|
||||||
var dec header
|
var dec header
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -155,5 +158,8 @@ func (h *header) UnmarshalJSON(input []byte) error {
|
||||||
if dec.ParentBeaconBlockRoot != nil {
|
if dec.ParentBeaconBlockRoot != nil {
|
||||||
h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||||
}
|
}
|
||||||
|
if dec.ParentProposerPubkey != nil {
|
||||||
|
h.ParentProposerPubkey = dec.ParentProposerPubkey
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
|
||||||
}
|
}
|
||||||
var enc stEnv
|
var enc stEnv
|
||||||
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
|
||||||
|
|
@ -59,6 +60,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
|
||||||
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
|
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
|
||||||
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
|
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
|
||||||
enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
|
enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
|
||||||
|
enc.ParentProposerPubkey = s.ParentProposerPubkey
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,6 +87,7 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||||
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
|
||||||
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
|
||||||
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
|
||||||
}
|
}
|
||||||
var dec stEnv
|
var dec stEnv
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -154,5 +157,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
|
||||||
if dec.ParentBeaconBlockRoot != nil {
|
if dec.ParentBeaconBlockRoot != nil {
|
||||||
s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
|
||||||
}
|
}
|
||||||
|
if dec.ParentProposerPubkey != nil {
|
||||||
|
s.ParentProposerPubkey = dec.ParentProposerPubkey
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -150,6 +150,9 @@ func Transition(ctx *cli.Context) error {
|
||||||
if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil {
|
if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := applyPrague1Checks(&prestate.Env, chainConfig); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// Configure tracer
|
// Configure tracer
|
||||||
if ctx.IsSet(TraceTracerFlag.Name) { // Custom tracing
|
if ctx.IsSet(TraceTracerFlag.Name) { // Custom tracing
|
||||||
|
|
@ -265,6 +268,19 @@ func applyCancunChecks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func applyPrague1Checks(env *stEnv, chainConfig *params.ChainConfig) error {
|
||||||
|
if !chainConfig.IsPrague1(big.NewInt(int64(env.Number)), env.Timestamp) {
|
||||||
|
env.ParentProposerPubkey = nil // un-set it if it has been set too early
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Post-prague1
|
||||||
|
// We require BRIP-0004 proposer pubkey to be set in the env
|
||||||
|
if env.ParentProposerPubkey == nil {
|
||||||
|
return NewError(ErrorConfig, errors.New("post-prague1 env requires parentProposerPubkey to be set"))
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
type Alloc map[common.Address]types.Account
|
type Alloc map[common.Address]types.Account
|
||||||
|
|
||||||
func (g Alloc) OnRoot(common.Hash) {}
|
func (g Alloc) OnRoot(common.Hash) {}
|
||||||
|
|
|
||||||
|
|
@ -139,7 +139,7 @@ var (
|
||||||
}
|
}
|
||||||
NetworkIdFlag = &cli.Uint64Flag{
|
NetworkIdFlag = &cli.Uint64Flag{
|
||||||
Name: "networkid",
|
Name: "networkid",
|
||||||
Usage: "Explicitly set network id (integer)(For testnets: use --sepolia, --holesky, --hoodi instead)",
|
Usage: "Explicitly set network id (integer)(Testnet: use --bepolia)(For Ethereum: use --mainnet, --sepolia, etc.)",
|
||||||
Value: ethconfig.Defaults.NetworkId,
|
Value: ethconfig.Defaults.NetworkId,
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
|
|
@ -163,6 +163,17 @@ var (
|
||||||
Usage: "Hoodi network: pre-configured proof-of-stake test network",
|
Usage: "Hoodi network: pre-configured proof-of-stake test network",
|
||||||
Category: flags.EthCategory,
|
Category: flags.EthCategory,
|
||||||
}
|
}
|
||||||
|
// Berachain
|
||||||
|
BerachainFlag = &cli.BoolFlag{
|
||||||
|
Name: "berachain",
|
||||||
|
Usage: "Berachain mainnet",
|
||||||
|
Category: flags.EthCategory,
|
||||||
|
}
|
||||||
|
BepoliaFlag = &cli.BoolFlag{
|
||||||
|
Name: "bepolia",
|
||||||
|
Usage: "Bepolia network: pre-configured proof-of-stake test network",
|
||||||
|
Category: flags.EthCategory,
|
||||||
|
}
|
||||||
// Dev mode
|
// Dev mode
|
||||||
DeveloperFlag = &cli.BoolFlag{
|
DeveloperFlag = &cli.BoolFlag{
|
||||||
Name: "dev",
|
Name: "dev",
|
||||||
|
|
@ -455,7 +466,7 @@ var (
|
||||||
// Performance tuning settings
|
// Performance tuning settings
|
||||||
CacheFlag = &cli.IntFlag{
|
CacheFlag = &cli.IntFlag{
|
||||||
Name: "cache",
|
Name: "cache",
|
||||||
Usage: "Megabytes of memory allocated to internal caching (default = 4096 mainnet full node, 128 light mode)",
|
Usage: "Megabytes of memory allocated to internal caching (default = 4096 berachain mainnet full node, 128 light mode)",
|
||||||
Value: 1024,
|
Value: 1024,
|
||||||
Category: flags.PerfCategory,
|
Category: flags.PerfCategory,
|
||||||
}
|
}
|
||||||
|
|
@ -1062,9 +1073,9 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
|
||||||
// 1. --bootnodes flag
|
// 1. --bootnodes flag
|
||||||
// 2. Config file
|
// 2. Config file
|
||||||
// 3. Network preset flags (e.g. --holesky)
|
// 3. Network preset flags (e.g. --holesky)
|
||||||
// 4. default to mainnet nodes
|
// 4. default to Berachain mainnet nodes
|
||||||
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
urls := params.MainnetBootnodes
|
urls := params.BerachainBootnodes
|
||||||
if ctx.IsSet(BootnodesFlag.Name) {
|
if ctx.IsSet(BootnodesFlag.Name) {
|
||||||
urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
|
urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1072,12 +1083,16 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
||||||
return // Already set by config file, don't apply defaults.
|
return // Already set by config file, don't apply defaults.
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
|
case ctx.Bool(MainnetFlag.Name):
|
||||||
|
urls = params.MainnetBootnodes
|
||||||
case ctx.Bool(HoleskyFlag.Name):
|
case ctx.Bool(HoleskyFlag.Name):
|
||||||
urls = params.HoleskyBootnodes
|
urls = params.HoleskyBootnodes
|
||||||
case ctx.Bool(SepoliaFlag.Name):
|
case ctx.Bool(SepoliaFlag.Name):
|
||||||
urls = params.SepoliaBootnodes
|
urls = params.SepoliaBootnodes
|
||||||
case ctx.Bool(HoodiFlag.Name):
|
case ctx.Bool(HoodiFlag.Name):
|
||||||
urls = params.HoodiBootnodes
|
urls = params.HoodiBootnodes
|
||||||
|
case ctx.Bool(BepoliaFlag.Name):
|
||||||
|
urls = params.BepoliaBootnodes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cfg.BootstrapNodes = mustParseBootnodes(urls)
|
cfg.BootstrapNodes = mustParseBootnodes(urls)
|
||||||
|
|
@ -1568,7 +1583,7 @@ func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
|
||||||
// SetEthConfig applies eth-related command line flags to the config.
|
// SetEthConfig applies eth-related command line flags to the config.
|
||||||
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// Avoid conflicting network flags, don't allow network id override on preset networks
|
// Avoid conflicting network flags, don't allow network id override on preset networks
|
||||||
flags.CheckExclusive(ctx, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag, HoodiFlag, NetworkIdFlag)
|
flags.CheckExclusive(ctx, BerachainFlag, BepoliaFlag, MainnetFlag, DeveloperFlag, SepoliaFlag, HoleskyFlag, HoodiFlag, NetworkIdFlag)
|
||||||
flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
||||||
|
|
||||||
// Set configurations from CLI flags
|
// Set configurations from CLI flags
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,8 @@ var (
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
testSepoliaFlag,
|
testSepoliaFlag,
|
||||||
testMainnetFlag,
|
testMainnetFlag,
|
||||||
|
testBepoliaFlag,
|
||||||
|
testBerachainFlag,
|
||||||
filterQueryFileFlag,
|
filterQueryFileFlag,
|
||||||
filterErrorFileFlag,
|
filterErrorFileFlag,
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -85,6 +85,16 @@ var (
|
||||||
Usage: "Use test cases for mainnet network",
|
Usage: "Use test cases for mainnet network",
|
||||||
Category: flags.TestingCategory,
|
Category: flags.TestingCategory,
|
||||||
}
|
}
|
||||||
|
testBepoliaFlag = &cli.BoolFlag{
|
||||||
|
Name: "bepolia",
|
||||||
|
Usage: "Use test cases for bepolia network",
|
||||||
|
Category: flags.TestingCategory,
|
||||||
|
}
|
||||||
|
testBerachainFlag = &cli.BoolFlag{
|
||||||
|
Name: "berachain",
|
||||||
|
Usage: "Use test cases for berachain mainnet network",
|
||||||
|
Category: flags.TestingCategory,
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
// testConfig holds the parameters for testing.
|
// testConfig holds the parameters for testing.
|
||||||
|
|
@ -117,10 +127,13 @@ func validateHistoryPruneErr(err error, blockNum uint64, historyPruneBlock *uint
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(bera): Add test filter & history queries for Berachain mainnet & Bepolia in queries/ folder
|
||||||
func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) {
|
func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) {
|
||||||
flags.CheckExclusive(ctx, testMainnetFlag, testSepoliaFlag)
|
flags.CheckExclusive(ctx, testMainnetFlag, testSepoliaFlag, testBerachainFlag, testBepoliaFlag)
|
||||||
if (ctx.IsSet(testMainnetFlag.Name) || ctx.IsSet(testSepoliaFlag.Name)) && ctx.IsSet(filterQueryFileFlag.Name) {
|
if (ctx.IsSet(testMainnetFlag.Name) || ctx.IsSet(testSepoliaFlag.Name) || ctx.IsSet(testBerachainFlag.Name) || ctx.IsSet(testBepoliaFlag.Name)) &&
|
||||||
exit(filterQueryFileFlag.Name + " cannot be used with " + testMainnetFlag.Name + " or " + testSepoliaFlag.Name)
|
ctx.IsSet(filterQueryFileFlag.Name) {
|
||||||
|
exit(filterQueryFileFlag.Name + " cannot be used with " + testMainnetFlag.Name + " or " +
|
||||||
|
testSepoliaFlag.Name + "or" + testBerachainFlag.Name + " or " + testBepoliaFlag.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
// configure ethclient
|
// configure ethclient
|
||||||
|
|
@ -166,6 +179,44 @@ func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) {
|
||||||
}
|
}
|
||||||
cfg.historyPruneBlock = new(uint64)
|
cfg.historyPruneBlock = new(uint64)
|
||||||
*cfg.historyPruneBlock = history.PrunePoints[params.SepoliaGenesisHash].BlockNumber
|
*cfg.historyPruneBlock = history.PrunePoints[params.SepoliaGenesisHash].BlockNumber
|
||||||
|
case ctx.Bool(testBerachainFlag.Name):
|
||||||
|
cfg.fsys = builtinTestFiles
|
||||||
|
if ctx.IsSet(filterQueryFileFlag.Name) {
|
||||||
|
cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name)
|
||||||
|
} else {
|
||||||
|
cfg.filterQueryFile = "queries/filter_queries_berachain.json"
|
||||||
|
}
|
||||||
|
if ctx.IsSet(historyTestFileFlag.Name) {
|
||||||
|
cfg.historyTestFile = ctx.String(historyTestFileFlag.Name)
|
||||||
|
} else {
|
||||||
|
cfg.historyTestFile = "queries/history_berachain.json"
|
||||||
|
}
|
||||||
|
if ctx.IsSet(traceTestFileFlag.Name) {
|
||||||
|
cfg.traceTestFile = ctx.String(traceTestFileFlag.Name)
|
||||||
|
} else {
|
||||||
|
cfg.traceTestFile = "queries/trace_berachain.json"
|
||||||
|
}
|
||||||
|
cfg.historyPruneBlock = new(uint64)
|
||||||
|
*cfg.historyPruneBlock = history.PrunePoints[params.BerachainGenesisHash].BlockNumber
|
||||||
|
case ctx.Bool(testBepoliaFlag.Name):
|
||||||
|
cfg.fsys = builtinTestFiles
|
||||||
|
if ctx.IsSet(filterQueryFileFlag.Name) {
|
||||||
|
cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name)
|
||||||
|
} else {
|
||||||
|
cfg.filterQueryFile = "queries/filter_queries_bepolia.json"
|
||||||
|
}
|
||||||
|
if ctx.IsSet(historyTestFileFlag.Name) {
|
||||||
|
cfg.historyTestFile = ctx.String(historyTestFileFlag.Name)
|
||||||
|
} else {
|
||||||
|
cfg.historyTestFile = "queries/history_bepolia.json"
|
||||||
|
}
|
||||||
|
if ctx.IsSet(traceTestFileFlag.Name) {
|
||||||
|
cfg.traceTestFile = ctx.String(traceTestFileFlag.Name)
|
||||||
|
} else {
|
||||||
|
cfg.traceTestFile = "queries/trace_bepolia.json"
|
||||||
|
}
|
||||||
|
cfg.historyPruneBlock = new(uint64)
|
||||||
|
*cfg.historyPruneBlock = history.PrunePoints[params.BepoliaGenesisHash].BlockNumber
|
||||||
default:
|
default:
|
||||||
cfg.fsys = os.DirFS(".")
|
cfg.fsys = os.DirFS(".")
|
||||||
cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name)
|
cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name)
|
||||||
|
|
|
||||||
|
|
@ -39,11 +39,16 @@ const (
|
||||||
HashLength = 32
|
HashLength = 32
|
||||||
// AddressLength is the expected length of the address
|
// AddressLength is the expected length of the address
|
||||||
AddressLength = 20
|
AddressLength = 20
|
||||||
|
|
||||||
|
// Berachain: PubkeyLength represents the expected byte length of a BLS12-381 public key
|
||||||
|
// as used by the beacon chain.
|
||||||
|
PubkeyLength = 48
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
hashT = reflect.TypeFor[Hash]()
|
hashT = reflect.TypeOf(Hash{})
|
||||||
addressT = reflect.TypeFor[Address]()
|
addressT = reflect.TypeOf(Address{})
|
||||||
|
pubkeyT = reflect.TypeOf(Pubkey{})
|
||||||
|
|
||||||
// MaxAddress represents the maximum possible address value.
|
// MaxAddress represents the maximum possible address value.
|
||||||
MaxAddress = HexToAddress("0xffffffffffffffffffffffffffffffffffffffff")
|
MaxAddress = HexToAddress("0xffffffffffffffffffffffffffffffffffffffff")
|
||||||
|
|
@ -486,3 +491,60 @@ func (b PrettyBytes) TerminalString() string {
|
||||||
}
|
}
|
||||||
return fmt.Sprintf("%#x...%x (%dB)", b[:3], b[len(b)-3:], len(b))
|
return fmt.Sprintf("%#x...%x (%dB)", b[:3], b[len(b)-3:], len(b))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/////////// Berachain: Pubkey
|
||||||
|
|
||||||
|
// Pubkey represents a fixed-length 48-byte BLS public key.
|
||||||
|
// JSON and text serialization use 0x-prefixed hex strings.
|
||||||
|
type Pubkey [PubkeyLength]byte
|
||||||
|
|
||||||
|
// Bytes returns a copy of the underlying byte slice.
|
||||||
|
func (p Pubkey) Bytes() []byte { return p[:] }
|
||||||
|
|
||||||
|
// String returns the hex-encoded string representation of the pubkey.
|
||||||
|
func (p Pubkey) String() string { return hexutil.Encode(p[:]) }
|
||||||
|
|
||||||
|
// Format implements fmt.Formatter.
|
||||||
|
// Pubkey supports the %v, %s, %q, %x, %X and %d format verbs.
|
||||||
|
func (p Pubkey) Format(s fmt.State, c rune) {
|
||||||
|
hexb := make([]byte, 2+len(p)*2)
|
||||||
|
copy(hexb, "0x")
|
||||||
|
hex.Encode(hexb[2:], p[:])
|
||||||
|
|
||||||
|
switch c {
|
||||||
|
case 'x', 'X':
|
||||||
|
if !s.Flag('#') {
|
||||||
|
hexb = hexb[2:]
|
||||||
|
}
|
||||||
|
if c == 'X' {
|
||||||
|
hexb = bytes.ToUpper(hexb)
|
||||||
|
}
|
||||||
|
fallthrough
|
||||||
|
case 'v', 's':
|
||||||
|
s.Write(hexb)
|
||||||
|
case 'q':
|
||||||
|
q := []byte{'"'}
|
||||||
|
s.Write(q)
|
||||||
|
s.Write(hexb)
|
||||||
|
s.Write(q)
|
||||||
|
case 'd':
|
||||||
|
fmt.Fprint(s, ([len(p)]byte)(p))
|
||||||
|
default:
|
||||||
|
fmt.Fprintf(s, "%%!%c(pubkey=%x)", c, p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MarshalText encodes the pubkey as a 0x-prefixed hex string.
|
||||||
|
func (p Pubkey) MarshalText() ([]byte, error) {
|
||||||
|
return hexutil.Bytes(p[:]).MarshalText()
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalText decodes a 0x-prefixed hex string into the pubkey.
|
||||||
|
func (p *Pubkey) UnmarshalText(input []byte) error {
|
||||||
|
return hexutil.UnmarshalFixedText("Pubkey", input, p[:])
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON decodes a JSON string containing the 0x-prefixed hex pubkey.
|
||||||
|
func (p *Pubkey) UnmarshalJSON(input []byte) error {
|
||||||
|
return hexutil.UnmarshalFixedJSON(pubkeyT, input, p[:])
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -282,6 +282,17 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Berachain specific: verify the existence of the proposer pubkey.
|
||||||
|
prague1 := chain.Config().IsPrague1(header.Number, header.Time)
|
||||||
|
if !prague1 {
|
||||||
|
if header.ParentProposerPubkey != nil {
|
||||||
|
return fmt.Errorf("invalid proposer pubkey: have %#x, expected nil", header.ParentProposerPubkey)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if header.ParentProposerPubkey == nil {
|
||||||
|
return errors.New("header is missing proposer pubkey")
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,21 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade
|
||||||
|
|
||||||
// CalcBaseFee calculates the basefee of the header.
|
// CalcBaseFee calculates the basefee of the header.
|
||||||
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||||
|
calculatedBaseFee := calcBaseFee(config, parent)
|
||||||
|
|
||||||
|
// Starting at the Prague1 fork, the base fee must be at least the minimum base fee.
|
||||||
|
if config.IsPrague1(parent.Number, parent.Time) {
|
||||||
|
minBaseFee := new(big.Int).SetUint64(config.Berachain.Prague1.MinimumBaseFeeWei)
|
||||||
|
if calculatedBaseFee.Cmp(minBaseFee) < 0 {
|
||||||
|
calculatedBaseFee = minBaseFee
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return calculatedBaseFee
|
||||||
|
}
|
||||||
|
|
||||||
|
// calcBaseFee calculates the basefee of the header in wei.
|
||||||
|
func calcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||||
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
|
// If the current block is the first EIP-1559 block, return the InitialBaseFee.
|
||||||
if !config.IsLondon(parent.Number) {
|
if !config.IsLondon(parent.Number) {
|
||||||
return new(big.Int).SetUint64(params.InitialBaseFee)
|
return new(big.Int).SetUint64(params.InitialBaseFee)
|
||||||
|
|
@ -76,7 +91,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||||
num.SetUint64(parent.GasUsed - parentGasTarget)
|
num.SetUint64(parent.GasUsed - parentGasTarget)
|
||||||
num.Mul(num, parent.BaseFee)
|
num.Mul(num, parent.BaseFee)
|
||||||
num.Div(num, denom.SetUint64(parentGasTarget))
|
num.Div(num, denom.SetUint64(parentGasTarget))
|
||||||
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator(parent.Number, parent.Time)))
|
||||||
if num.Cmp(common.Big1) < 0 {
|
if num.Cmp(common.Big1) < 0 {
|
||||||
return num.Add(parent.BaseFee, common.Big1)
|
return num.Add(parent.BaseFee, common.Big1)
|
||||||
}
|
}
|
||||||
|
|
@ -87,7 +102,7 @@ func CalcBaseFee(config *params.ChainConfig, parent *types.Header) *big.Int {
|
||||||
num.SetUint64(parentGasTarget - parent.GasUsed)
|
num.SetUint64(parentGasTarget - parent.GasUsed)
|
||||||
num.Mul(num, parent.BaseFee)
|
num.Mul(num, parent.BaseFee)
|
||||||
num.Div(num, denom.SetUint64(parentGasTarget))
|
num.Div(num, denom.SetUint64(parentGasTarget))
|
||||||
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator()))
|
num.Div(num, denom.SetUint64(config.BaseFeeChangeDenominator(parent.Number, parent.Time)))
|
||||||
|
|
||||||
baseFee := num.Sub(parent.BaseFee, num)
|
baseFee := num.Sub(parent.BaseFee, num)
|
||||||
if baseFee.Cmp(common.Big0) < 0 {
|
if baseFee.Cmp(common.Big0) < 0 {
|
||||||
|
|
|
||||||
|
|
@ -20,9 +20,11 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/ethereum/go-ethereum/consensus"
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
"github.com/ethereum/go-ethereum/core/state"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
)
|
)
|
||||||
|
|
@ -47,7 +49,7 @@ func NewBlockValidator(config *params.ChainConfig, blockchain *BlockChain) *Bloc
|
||||||
|
|
||||||
// ValidateBody validates the given block's uncles and verifies the block
|
// ValidateBody validates the given block's uncles and verifies the block
|
||||||
// header's transaction and uncle roots. The headers are assumed to be already
|
// header's transaction and uncle roots. The headers are assumed to be already
|
||||||
// validated at this point.
|
// validated at this point. Also it the Prague1 block according to BRIP-0004.
|
||||||
func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
// check EIP 7934 RLP-encoded block size cap
|
// check EIP 7934 RLP-encoded block size cap
|
||||||
if v.config.IsOsaka(block.Number(), block.Time()) && block.Size() > params.MaxBlockSize {
|
if v.config.IsOsaka(block.Number(), block.Time()) && block.Size() > params.MaxBlockSize {
|
||||||
|
|
@ -67,7 +69,8 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
|
if hash := types.CalcUncleHash(block.Uncles()); hash != header.UncleHash {
|
||||||
return fmt.Errorf("uncle root hash mismatch (header value %x, calculated %x)", header.UncleHash, hash)
|
return fmt.Errorf("uncle root hash mismatch (header value %x, calculated %x)", header.UncleHash, hash)
|
||||||
}
|
}
|
||||||
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
|
txs := block.Transactions()
|
||||||
|
if hash := types.DeriveSha(txs, trie.NewStackTrie(nil)); hash != header.TxHash {
|
||||||
return fmt.Errorf("transaction root hash mismatch (header value %x, calculated %x)", header.TxHash, hash)
|
return fmt.Errorf("transaction root hash mismatch (header value %x, calculated %x)", header.TxHash, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -85,9 +88,48 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
|
||||||
return errors.New("withdrawals present in block body")
|
return errors.New("withdrawals present in block body")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Berachain: Pre-compute expected PoL tx hash when in Prague1.
|
||||||
|
isPrague1 := v.config.IsPrague1(block.Number(), block.Time())
|
||||||
|
var expectedPoLTx *types.Transaction
|
||||||
|
if isPrague1 {
|
||||||
|
if block.ProposerPubkey() == nil {
|
||||||
|
return errors.New("post-prague1 block missing parent proposer pubkey")
|
||||||
|
}
|
||||||
|
|
||||||
|
polTx, err := types.NewPoLTx(
|
||||||
|
v.config.ChainID,
|
||||||
|
v.config.Berachain.Prague1.PoLDistributorAddress,
|
||||||
|
block.Number(),
|
||||||
|
params.PoLTxGasLimit,
|
||||||
|
block.BaseFee(),
|
||||||
|
block.ProposerPubkey(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create expected PoL tx: %w", err)
|
||||||
|
}
|
||||||
|
expectedPoLTx = polTx
|
||||||
|
|
||||||
|
// Validate that the block has at least one tx.
|
||||||
|
if len(txs) == 0 {
|
||||||
|
return errors.New("post-prague1 block missing PoL tx")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Blob transactions may be present after the Cancun fork.
|
// Blob transactions may be present after the Cancun fork.
|
||||||
var blobs int
|
var blobs int
|
||||||
for i, tx := range block.Transactions() {
|
for i, tx := range txs {
|
||||||
|
// Berachain: validate the PoL tx is only the first tx in the block.
|
||||||
|
switch {
|
||||||
|
case isPrague1 && i == 0:
|
||||||
|
if tx.Hash() != expectedPoLTx.Hash() {
|
||||||
|
log.Debug("PoL tx hash mismatch", "have", tx.Hash(), "expected", expectedPoLTx.Hash())
|
||||||
|
log.Debug("PoL tx contents", "have", spew.Sdump(tx), "expected", spew.Sdump(expectedPoLTx))
|
||||||
|
return fmt.Errorf("PoL tx hash mismatch: have %v, want %v", tx.Hash(), expectedPoLTx.Hash())
|
||||||
|
}
|
||||||
|
case tx.Type() == types.PoLTxType:
|
||||||
|
return fmt.Errorf("invalid block: tx at index %d is a PoL tx", i)
|
||||||
|
}
|
||||||
|
|
||||||
// Count the number of blobs to validate against the header's blobGasUsed
|
// Count the number of blobs to validate against the header's blobGasUsed
|
||||||
blobs += len(tx.BlobHashes())
|
blobs += len(tx.BlobHashes())
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,131 @@ import (
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
// Berachain:Prague-1 PoL validation tests
|
||||||
|
// -----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
// newPrague1Config returns a ChainConfig where Prague (and Prague-1) are active
|
||||||
|
// from timestamp 0. The caller can specify the PoL distributor address.
|
||||||
|
func newPrague1Config(distributor common.Address) *params.ChainConfig {
|
||||||
|
zero := uint64(0)
|
||||||
|
cfg := *params.AllDevChainProtocolChanges // copy
|
||||||
|
cfg.Berachain.Prague1 = params.Prague1Config{
|
||||||
|
Time: &zero,
|
||||||
|
BaseFeeChangeDenominator: 48,
|
||||||
|
MinimumBaseFeeWei: 10000000000,
|
||||||
|
PoLDistributorAddress: distributor,
|
||||||
|
}
|
||||||
|
return &cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
// buildTestChain initialises an in-memory blockchain with the provided config
|
||||||
|
// and returns the chain and its validator.
|
||||||
|
func buildTestChain(t *testing.T, cfg *params.ChainConfig) (*BlockChain, Validator) {
|
||||||
|
t.Helper()
|
||||||
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
genesis := &Genesis{Config: cfg}
|
||||||
|
chain, err := NewBlockChain(db, genesis, ethash.NewFaker(), nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create blockchain: %v", err)
|
||||||
|
}
|
||||||
|
return chain, chain.Validator()
|
||||||
|
}
|
||||||
|
|
||||||
|
// samplePubkey returns a deterministic 48-byte pubkey for tests.
|
||||||
|
func samplePubkey() *common.Pubkey {
|
||||||
|
var pk common.Pubkey
|
||||||
|
for i := 0; i < common.PubkeyLength; i++ {
|
||||||
|
pk[i] = byte(i)
|
||||||
|
}
|
||||||
|
return &pk
|
||||||
|
}
|
||||||
|
|
||||||
|
// makeBlock builds a child block on top of parent with the supplied txs and timestamp.
|
||||||
|
func makeBlock(parent *types.Header, txs types.Transactions, timestamp uint64) *types.Block {
|
||||||
|
header := &types.Header{
|
||||||
|
ParentHash: parent.Hash(),
|
||||||
|
Number: new(big.Int).Add(parent.Number, big.NewInt(1)),
|
||||||
|
Time: timestamp,
|
||||||
|
GasLimit: params.GenesisGasLimit * 10,
|
||||||
|
Difficulty: big.NewInt(1),
|
||||||
|
ParentProposerPubkey: samplePubkey(),
|
||||||
|
BaseFee: big.NewInt(1000000000),
|
||||||
|
}
|
||||||
|
return types.NewBlock(header, &types.Body{Transactions: txs}, nil, trie.NewStackTrie(nil))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateBody_Prague1_Valid(t *testing.T) {
|
||||||
|
distributor := common.HexToAddress("0x1111111111111111111111111111111111111111")
|
||||||
|
cfg := newPrague1Config(distributor)
|
||||||
|
chain, validator := buildTestChain(t, cfg)
|
||||||
|
|
||||||
|
// Build PoL tx + dummy tx.
|
||||||
|
polTx, err := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(1), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey())
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("failed to create PoL tx: %v", err)
|
||||||
|
}
|
||||||
|
dummyTx := types.NewTx(&types.LegacyTx{Nonce: 1})
|
||||||
|
|
||||||
|
block := makeBlock(chain.CurrentHeader(), types.Transactions{polTx, dummyTx}, 1)
|
||||||
|
|
||||||
|
if err := validator.ValidateBody(block); err != nil {
|
||||||
|
t.Fatalf("ValidateBody returned error for valid Prague1 block: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateBody_Prague1_InvalidHash(t *testing.T) {
|
||||||
|
distributor := common.HexToAddress("0x2222222222222222222222222222222222222222")
|
||||||
|
cfg := newPrague1Config(distributor)
|
||||||
|
chain, validator := buildTestChain(t, cfg)
|
||||||
|
|
||||||
|
// PoL tx with WRONG pubkey (different from header.ParentProposerPubkey).
|
||||||
|
wrongPk := &common.Pubkey{}
|
||||||
|
polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(1), params.PoLTxGasLimit, big.NewInt(1000000000), wrongPk)
|
||||||
|
block := makeBlock(chain.CurrentHeader(), types.Transactions{polTx}, 1)
|
||||||
|
|
||||||
|
if err := validator.ValidateBody(block); err == nil {
|
||||||
|
t.Fatalf("expected error due to invalid PoL hash, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateBody_Prague1_MisplacedPoL(t *testing.T) {
|
||||||
|
distributor := common.HexToAddress("0x3333333333333333333333333333333333333333")
|
||||||
|
cfg := newPrague1Config(distributor)
|
||||||
|
chain, validator := buildTestChain(t, cfg)
|
||||||
|
|
||||||
|
polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(1), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey())
|
||||||
|
dummyTx := types.NewTx(&types.LegacyTx{Nonce: 1})
|
||||||
|
// PoL tx placed second.
|
||||||
|
block := makeBlock(chain.CurrentHeader(), types.Transactions{dummyTx, polTx}, 1)
|
||||||
|
|
||||||
|
if err := validator.ValidateBody(block); err == nil {
|
||||||
|
t.Fatalf("expected error for PoL tx at index >0, got nil")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateBody_PrePrague1_PoLProhibited(t *testing.T) {
|
||||||
|
distributor := common.HexToAddress("0x4444444444444444444444444444444444444444")
|
||||||
|
// Prague time active, but Prague1 *future* at timestamp 1000.
|
||||||
|
future := uint64(1000)
|
||||||
|
cfg := *params.AllDevChainProtocolChanges
|
||||||
|
cfg.Berachain.Prague1.Time = &future
|
||||||
|
cfg.Berachain.Prague1.BaseFeeChangeDenominator = 48
|
||||||
|
cfg.Berachain.Prague1.MinimumBaseFeeWei = 10000000000
|
||||||
|
cfg.Berachain.Prague1.PoLDistributorAddress = distributor
|
||||||
|
chain, validator := buildTestChain(t, &cfg)
|
||||||
|
|
||||||
|
polTx, _ := types.NewPoLTx(cfg.ChainID, distributor, big.NewInt(1), params.PoLTxGasLimit, big.NewInt(1000000000), samplePubkey())
|
||||||
|
block := makeBlock(chain.CurrentHeader(), types.Transactions{polTx}, 1) // timestamp 1 < future
|
||||||
|
|
||||||
|
if err := validator.ValidateBody(block); err == nil {
|
||||||
|
t.Fatalf("expected error: PoL tx before Prague1 fork should be invalid")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Tests that simple header verification works, for both good and bad blocks.
|
// Tests that simple header verification works, for both good and bad blocks.
|
||||||
func TestHeaderVerification(t *testing.T) {
|
func TestHeaderVerification(t *testing.T) {
|
||||||
testHeaderVerification(t, rawdb.HashScheme)
|
testHeaderVerification(t, rawdb.HashScheme)
|
||||||
|
|
|
||||||
|
|
@ -102,6 +102,25 @@ func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
|
||||||
ProcessBeaconBlockRoot(root, vm.NewEVM(blockContext, b.statedb, b.cm.config, vm.Config{}))
|
ProcessBeaconBlockRoot(root, vm.NewEVM(blockContext, b.statedb, b.cm.config, vm.Config{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SetParentProposerPubkey sets the parent proposer pubkey field of the generated
|
||||||
|
// block.
|
||||||
|
func (b *BlockGen) SetParentProposerPubkey(pubkey common.Pubkey) error {
|
||||||
|
b.header.ParentProposerPubkey = &pubkey
|
||||||
|
tx, err := types.NewPoLTx(
|
||||||
|
b.cm.config.ChainID,
|
||||||
|
b.cm.config.Berachain.Prague1.PoLDistributorAddress,
|
||||||
|
b.header.Number,
|
||||||
|
params.PoLTxGasLimit,
|
||||||
|
b.header.BaseFee,
|
||||||
|
b.header.ParentProposerPubkey,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
b.AddTx(tx)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// addTx adds a transaction to the generated block. If no coinbase has
|
// addTx adds a transaction to the generated block. If no coinbase has
|
||||||
// been set, the block's coinbase is set to the zero address.
|
// been set, the block's coinbase is set to the zero address.
|
||||||
//
|
//
|
||||||
|
|
@ -116,9 +135,14 @@ func (b *BlockGen) addTx(bc *BlockChain, vmConfig vm.Config, tx *types.Transacti
|
||||||
var (
|
var (
|
||||||
blockContext = NewEVMBlockContext(b.header, bc, &b.header.Coinbase)
|
blockContext = NewEVMBlockContext(b.header, bc, &b.header.Coinbase)
|
||||||
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
|
evm = vm.NewEVM(blockContext, b.statedb, b.cm.config, vmConfig)
|
||||||
|
gasUsed = &b.header.GasUsed
|
||||||
)
|
)
|
||||||
|
// Berachain: PoL txs do not count towards block gas.
|
||||||
|
if tx.Type() == types.PoLTxType {
|
||||||
|
gasUsed = new(uint64)
|
||||||
|
}
|
||||||
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
|
b.statedb.SetTxContext(tx.Hash(), len(b.txs))
|
||||||
receipt, err := ApplyTransaction(evm, b.gasPool, b.statedb, b.header, tx, &b.header.GasUsed)
|
receipt, err := ApplyTransaction(evm, b.gasPool, b.statedb, b.header, tx, gasUsed)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
@ -619,6 +643,9 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi
|
||||||
header.BlobGasUsed = new(uint64)
|
header.BlobGasUsed = new(uint64)
|
||||||
header.ParentBeaconRoot = new(common.Hash)
|
header.ParentBeaconRoot = new(common.Hash)
|
||||||
}
|
}
|
||||||
|
if cm.config.IsPrague1(header.Number, header.Time) {
|
||||||
|
header.ParentProposerPubkey = new(common.Pubkey)
|
||||||
|
}
|
||||||
return header
|
return header
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -268,6 +268,11 @@ func gatherForks(config *params.ChainConfig, genesis uint64) ([]uint64, []uint64
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Berachain-specific: include nested Prague1 fork time in the fork id set
|
||||||
|
// so that clients using it (e.g. reth) compute the same fork checksum.
|
||||||
|
if config != nil && config.Berachain.Prague1.Time != nil {
|
||||||
|
forksByTime = append(forksByTime, *config.Berachain.Prague1.Time)
|
||||||
|
}
|
||||||
slices.Sort(forksByBlock)
|
slices.Sort(forksByBlock)
|
||||||
slices.Sort(forksByTime)
|
slices.Sort(forksByTime)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -223,6 +223,10 @@ func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.Gene
|
||||||
genesis = DefaultHoleskyGenesisBlock()
|
genesis = DefaultHoleskyGenesisBlock()
|
||||||
case params.HoodiGenesisHash:
|
case params.HoodiGenesisHash:
|
||||||
genesis = DefaultHoodiGenesisBlock()
|
genesis = DefaultHoodiGenesisBlock()
|
||||||
|
case params.BerachainGenesisHash:
|
||||||
|
genesis = DefaultBerachainGenesisBlock()
|
||||||
|
case params.BepoliaGenesisHash:
|
||||||
|
genesis = DefaultBepoliaGenesisBlock()
|
||||||
}
|
}
|
||||||
if genesis != nil {
|
if genesis != nil {
|
||||||
return genesis.Alloc, nil
|
return genesis.Alloc, nil
|
||||||
|
|
@ -303,8 +307,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
|
||||||
ghash := rawdb.ReadCanonicalHash(db, 0)
|
ghash := rawdb.ReadCanonicalHash(db, 0)
|
||||||
if (ghash == common.Hash{}) {
|
if (ghash == common.Hash{}) {
|
||||||
if genesis == nil {
|
if genesis == nil {
|
||||||
log.Info("Writing default main-net genesis block")
|
log.Info("Writing default berachain mainnet genesis block")
|
||||||
genesis = DefaultGenesisBlock()
|
genesis = DefaultBerachainGenesisBlock()
|
||||||
} else {
|
} else {
|
||||||
log.Info("Writing custom genesis block")
|
log.Info("Writing custom genesis block")
|
||||||
}
|
}
|
||||||
|
|
@ -328,8 +332,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
|
||||||
// networks must explicitly specify the genesis in the config file, mainnet
|
// networks must explicitly specify the genesis in the config file, mainnet
|
||||||
// genesis will be used as default and the initialization will always fail.
|
// genesis will be used as default and the initialization will always fail.
|
||||||
if genesis == nil {
|
if genesis == nil {
|
||||||
log.Info("Writing default main-net genesis block")
|
log.Info("Writing default berachain mainnet genesis block")
|
||||||
genesis = DefaultGenesisBlock()
|
genesis = DefaultBerachainGenesisBlock()
|
||||||
} else {
|
} else {
|
||||||
log.Info("Writing custom genesis block")
|
log.Info("Writing custom genesis block")
|
||||||
}
|
}
|
||||||
|
|
@ -381,9 +385,11 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
|
||||||
return newCfg, ghash, compatErr, nil
|
return newCfg, ghash, compatErr, nil
|
||||||
}
|
}
|
||||||
// Don't overwrite if the old is identical to the new. It's useful
|
// Don't overwrite if the old is identical to the new. It's useful
|
||||||
// for the scenarios that database is opened in the read-only mode.
|
// for the scenarios that database is opened in the read-only mode
|
||||||
|
// OR if the chain config is updated to include new Berachain fork info.
|
||||||
storedData, _ := json.Marshal(storedCfg)
|
storedData, _ := json.Marshal(storedCfg)
|
||||||
if newData, _ := json.Marshal(newCfg); !bytes.Equal(storedData, newData) {
|
if newData, _ := json.Marshal(newCfg); !bytes.Equal(storedData, newData) {
|
||||||
|
log.Info("Writing new chain config")
|
||||||
rawdb.WriteChainConfig(db, ghash, newCfg)
|
rawdb.WriteChainConfig(db, ghash, newCfg)
|
||||||
}
|
}
|
||||||
return newCfg, ghash, nil, nil
|
return newCfg, ghash, nil, nil
|
||||||
|
|
@ -419,8 +425,8 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (cfg *params.ChainConf
|
||||||
return genesis.Config, ghash, nil
|
return genesis.Config, ghash, nil
|
||||||
}
|
}
|
||||||
// There is no stored chain config and no new config provided,
|
// There is no stored chain config and no new config provided,
|
||||||
// In this case the default chain config(mainnet) will be used
|
// In this case the default chain config(berachain mainnet) will be used
|
||||||
return params.MainnetChainConfig, params.MainnetGenesisHash, nil
|
return params.BerachainChainConfig, params.BerachainGenesisHash, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// chainConfigOrDefault retrieves the attached chain configuration. If the genesis
|
// chainConfigOrDefault retrieves the attached chain configuration. If the genesis
|
||||||
|
|
@ -438,6 +444,10 @@ func (g *Genesis) chainConfigOrDefault(ghash common.Hash, stored *params.ChainCo
|
||||||
return params.SepoliaChainConfig
|
return params.SepoliaChainConfig
|
||||||
case ghash == params.HoodiGenesisHash:
|
case ghash == params.HoodiGenesisHash:
|
||||||
return params.HoodiChainConfig
|
return params.HoodiChainConfig
|
||||||
|
case ghash == params.BerachainGenesisHash:
|
||||||
|
return params.BerachainChainConfig
|
||||||
|
case ghash == params.BepoliaGenesisHash:
|
||||||
|
return params.BepoliaChainConfig
|
||||||
default:
|
default:
|
||||||
return stored
|
return stored
|
||||||
}
|
}
|
||||||
|
|
@ -518,6 +528,12 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
|
||||||
if conf.IsPrague(num, g.Timestamp) {
|
if conf.IsPrague(num, g.Timestamp) {
|
||||||
head.RequestsHash = &types.EmptyRequestsHash
|
head.RequestsHash = &types.EmptyRequestsHash
|
||||||
}
|
}
|
||||||
|
if conf.IsPrague1(num, g.Timestamp) {
|
||||||
|
// BRIP-0004: The parentProposerPubkey of the genesis block is always
|
||||||
|
// the zero pubkey. This is because the genesis block does not have a parent
|
||||||
|
// by definition.
|
||||||
|
head.ParentProposerPubkey = new(common.Pubkey)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
|
return types.NewBlock(head, &types.Body{Withdrawals: withdrawals}, nil, trie.NewStackTrie(nil))
|
||||||
}
|
}
|
||||||
|
|
@ -644,6 +660,32 @@ func DefaultHoodiGenesisBlock() *Genesis {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// DefaultBerachainGenesisBlock returns the Berachain main net genesis block.
|
||||||
|
func DefaultBerachainGenesisBlock() *Genesis {
|
||||||
|
return &Genesis{
|
||||||
|
Config: params.BerachainChainConfig,
|
||||||
|
Nonce: 0x1234,
|
||||||
|
ExtraData: []byte{},
|
||||||
|
GasLimit: 0x1c9c380,
|
||||||
|
Difficulty: big.NewInt(0x01),
|
||||||
|
Timestamp: 1737381600,
|
||||||
|
Alloc: decodePrealloc(berachainAllocData),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// DefaultBepoliaGenesisBlock returns the Bepolia network genesis block.
|
||||||
|
func DefaultBepoliaGenesisBlock() *Genesis {
|
||||||
|
return &Genesis{
|
||||||
|
Config: params.BepoliaChainConfig,
|
||||||
|
Nonce: 0x1234,
|
||||||
|
ExtraData: []byte{},
|
||||||
|
GasLimit: 0x1c9c380,
|
||||||
|
Difficulty: big.NewInt(0x01),
|
||||||
|
Timestamp: 1739976735,
|
||||||
|
Alloc: decodePrealloc(bepoliaAllocData),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
||||||
func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
|
func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
|
||||||
// Override the default period to the user requested one
|
// Override the default period to the user requested one
|
||||||
|
|
|
||||||
File diff suppressed because one or more lines are too long
|
|
@ -72,8 +72,8 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||||
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
|
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
|
||||||
},
|
},
|
||||||
wantHash: params.MainnetGenesisHash,
|
wantHash: params.BerachainGenesisHash,
|
||||||
wantConfig: params.MainnetChainConfig,
|
wantConfig: params.BerachainChainConfig,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "mainnet block in DB, genesis == nil",
|
name: "mainnet block in DB, genesis == nil",
|
||||||
|
|
@ -84,6 +84,15 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
||||||
wantHash: params.MainnetGenesisHash,
|
wantHash: params.MainnetGenesisHash,
|
||||||
wantConfig: params.MainnetChainConfig,
|
wantConfig: params.MainnetChainConfig,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "berachain block in DB, genesis == nil",
|
||||||
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||||
|
DefaultBerachainGenesisBlock().MustCommit(db, triedb.NewDatabase(db, newDbConfig(scheme)))
|
||||||
|
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
|
||||||
|
},
|
||||||
|
wantHash: params.BerachainGenesisHash,
|
||||||
|
wantConfig: params.BerachainChainConfig,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "custom block in DB, genesis == nil",
|
name: "custom block in DB, genesis == nil",
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||||
|
|
@ -103,6 +112,15 @@ func testSetupGenesis(t *testing.T, scheme string) {
|
||||||
},
|
},
|
||||||
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
|
wantErr: &GenesisMismatchError{Stored: customghash, New: params.SepoliaGenesisHash},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "custom block in DB, genesis == bepolia",
|
||||||
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||||
|
tdb := triedb.NewDatabase(db, newDbConfig(scheme))
|
||||||
|
customg.Commit(db, tdb)
|
||||||
|
return SetupGenesisBlock(db, tdb, DefaultBepoliaGenesisBlock())
|
||||||
|
},
|
||||||
|
wantErr: &GenesisMismatchError{Stored: customghash, New: params.BepoliaGenesisHash},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: "custom block in DB, genesis == hoodi",
|
name: "custom block in DB, genesis == hoodi",
|
||||||
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
|
||||||
|
|
@ -188,6 +206,8 @@ func TestGenesisHashes(t *testing.T) {
|
||||||
{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
|
{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
|
||||||
{DefaultHoleskyGenesisBlock(), params.HoleskyGenesisHash},
|
{DefaultHoleskyGenesisBlock(), params.HoleskyGenesisHash},
|
||||||
{DefaultHoodiGenesisBlock(), params.HoodiGenesisHash},
|
{DefaultHoodiGenesisBlock(), params.HoodiGenesisHash},
|
||||||
|
{DefaultBerachainGenesisBlock(), params.BerachainGenesisHash},
|
||||||
|
{DefaultBepoliaGenesisBlock(), params.BepoliaGenesisHash},
|
||||||
} {
|
} {
|
||||||
// Test via MustCommit
|
// Test via MustCommit
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
|
|
|
||||||
|
|
@ -413,6 +413,10 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
|
||||||
nBlobs += len(tx.BlobHashes())
|
nBlobs += len(tx.BlobHashes())
|
||||||
}
|
}
|
||||||
header.Root = common.BytesToHash(hasher.Sum(nil))
|
header.Root = common.BytesToHash(hasher.Sum(nil))
|
||||||
|
if config.IsPrague1(header.Number, header.Time) {
|
||||||
|
proposerPubkey := common.Pubkey{0x01, 0x02, 0x03}
|
||||||
|
header.ParentProposerPubkey = &proposerPubkey
|
||||||
|
}
|
||||||
if config.IsCancun(header.Number, header.Time) {
|
if config.IsCancun(header.Number, header.Time) {
|
||||||
excess := eip4844.CalcExcessBlobGas(config, parent.Header(), header.Time)
|
excess := eip4844.CalcExcessBlobGas(config, parent.Header(), header.Time)
|
||||||
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)
|
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)
|
||||||
|
|
|
||||||
|
|
@ -166,6 +166,9 @@ type Message struct {
|
||||||
|
|
||||||
// When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
|
// When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
|
||||||
SkipFromEOACheck bool
|
SkipFromEOACheck bool
|
||||||
|
|
||||||
|
// Berachain:IsPoLTx is true if the message is a PoL tx.
|
||||||
|
IsPoLTx bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// TransactionToMessage converts a transaction into a Message.
|
// TransactionToMessage converts a transaction into a Message.
|
||||||
|
|
@ -185,6 +188,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
|
||||||
SkipFromEOACheck: false,
|
SkipFromEOACheck: false,
|
||||||
BlobHashes: tx.BlobHashes(),
|
BlobHashes: tx.BlobHashes(),
|
||||||
BlobGasFeeCap: tx.BlobGasFeeCap(),
|
BlobGasFeeCap: tx.BlobGasFeeCap(),
|
||||||
|
IsPoLTx: tx.Type() == types.PoLTxType,
|
||||||
}
|
}
|
||||||
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
||||||
if baseFee != nil {
|
if baseFee != nil {
|
||||||
|
|
@ -207,9 +211,30 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
|
||||||
// state and would never be accepted within a block.
|
// state and would never be accepted within a block.
|
||||||
func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) {
|
func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) {
|
||||||
evm.SetTxContext(NewEVMTxContext(msg))
|
evm.SetTxContext(NewEVMTxContext(msg))
|
||||||
|
|
||||||
|
// Berachain: ApplyPoLMessage is used to apply the PoL tx to the EVM, skipping the
|
||||||
|
// normal state transition checks.
|
||||||
|
if msg.IsPoLTx {
|
||||||
|
return ApplyPoLMessage(msg, evm), nil
|
||||||
|
}
|
||||||
|
|
||||||
return newStateTransition(evm, msg, gp).execute()
|
return newStateTransition(evm, msg, gp).execute()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Berachain: ApplyPoLMessage applies the BRIP-0004 PoL tx to the EVM. No gas is consumed.
|
||||||
|
func ApplyPoLMessage(msg *Message, evm *vm.EVM) *ExecutionResult {
|
||||||
|
evm.StateDB.AddAddressToAccessList(*msg.To)
|
||||||
|
|
||||||
|
result := &ExecutionResult{}
|
||||||
|
ret, leftOverGas, err := evm.Call(msg.From, *msg.To, msg.Data, msg.GasLimit, common.U2560)
|
||||||
|
if err != nil {
|
||||||
|
result.Err = fmt.Errorf("PoL tx failed to execute: %w", err)
|
||||||
|
}
|
||||||
|
result.ReturnData = ret
|
||||||
|
result.MaxUsedGas = msg.GasLimit - leftOverGas // To inform how much gas was needed to run the msg.
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// stateTransition represents a state transition.
|
// stateTransition represents a state transition.
|
||||||
//
|
//
|
||||||
// == The State Transitioning Model
|
// == The State Transitioning Model
|
||||||
|
|
|
||||||
|
|
@ -327,6 +327,11 @@ func (p *TxPool) Add(txs []*types.Transaction, sync bool) []error {
|
||||||
// Mark this transaction belonging to no-subpool
|
// Mark this transaction belonging to no-subpool
|
||||||
splits[i] = -1
|
splits[i] = -1
|
||||||
|
|
||||||
|
// Berachain: PoL txs are rejected.
|
||||||
|
if tx.Type() == types.PoLTxType {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
// Try to find a subpool that accepts the transaction
|
// Try to find a subpool that accepts the transaction
|
||||||
for j, subpool := range p.subpools {
|
for j, subpool := range p.subpools {
|
||||||
if subpool.Filter(tx) {
|
if subpool.Filter(tx) {
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,9 @@ type Header struct {
|
||||||
|
|
||||||
// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
|
// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
|
||||||
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
||||||
|
|
||||||
|
// ParentProposerPubkey was added by BRIP-0004 and is ignored in legacy headers.
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// field type overrides for gencodec
|
// field type overrides for gencodec
|
||||||
|
|
@ -329,6 +332,10 @@ func CopyHeader(h *Header) *Header {
|
||||||
cpy.RequestsHash = new(common.Hash)
|
cpy.RequestsHash = new(common.Hash)
|
||||||
*cpy.RequestsHash = *h.RequestsHash
|
*cpy.RequestsHash = *h.RequestsHash
|
||||||
}
|
}
|
||||||
|
if h.ParentProposerPubkey != nil {
|
||||||
|
cpy.ParentProposerPubkey = new(common.Pubkey)
|
||||||
|
*cpy.ParentProposerPubkey = *h.ParentProposerPubkey
|
||||||
|
}
|
||||||
return &cpy
|
return &cpy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -410,6 +417,7 @@ func (b *Block) BaseFee() *big.Int {
|
||||||
|
|
||||||
func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot }
|
func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot }
|
||||||
func (b *Block) RequestsHash() *common.Hash { return b.header.RequestsHash }
|
func (b *Block) RequestsHash() *common.Hash { return b.header.RequestsHash }
|
||||||
|
func (b *Block) ProposerPubkey() *common.Pubkey { return b.header.ParentProposerPubkey }
|
||||||
|
|
||||||
func (b *Block) ExcessBlobGas() *uint64 {
|
func (b *Block) ExcessBlobGas() *uint64 {
|
||||||
var excessBlobGas *uint64
|
var excessBlobGas *uint64
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
|
||||||
Hash common.Hash `json:"hash"`
|
Hash common.Hash `json:"hash"`
|
||||||
}
|
}
|
||||||
var enc Header
|
var enc Header
|
||||||
|
|
@ -61,6 +62,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
|
||||||
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
|
||||||
enc.ParentBeaconRoot = h.ParentBeaconRoot
|
enc.ParentBeaconRoot = h.ParentBeaconRoot
|
||||||
enc.RequestsHash = h.RequestsHash
|
enc.RequestsHash = h.RequestsHash
|
||||||
|
enc.ParentProposerPubkey = h.ParentProposerPubkey
|
||||||
enc.Hash = h.Hash()
|
enc.Hash = h.Hash()
|
||||||
return json.Marshal(&enc)
|
return json.Marshal(&enc)
|
||||||
}
|
}
|
||||||
|
|
@ -89,6 +91,7 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
||||||
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
|
||||||
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
|
||||||
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
|
||||||
|
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
|
||||||
}
|
}
|
||||||
var dec Header
|
var dec Header
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
if err := json.Unmarshal(input, &dec); err != nil {
|
||||||
|
|
@ -169,5 +172,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
|
||||||
if dec.RequestsHash != nil {
|
if dec.RequestsHash != nil {
|
||||||
h.RequestsHash = dec.RequestsHash
|
h.RequestsHash = dec.RequestsHash
|
||||||
}
|
}
|
||||||
|
if dec.ParentProposerPubkey != nil {
|
||||||
|
h.ParentProposerPubkey = dec.ParentProposerPubkey
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -43,7 +43,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
||||||
_tmp4 := obj.ExcessBlobGas != nil
|
_tmp4 := obj.ExcessBlobGas != nil
|
||||||
_tmp5 := obj.ParentBeaconRoot != nil
|
_tmp5 := obj.ParentBeaconRoot != nil
|
||||||
_tmp6 := obj.RequestsHash != nil
|
_tmp6 := obj.RequestsHash != nil
|
||||||
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
_tmp7 := obj.ParentProposerPubkey != nil
|
||||||
|
if _tmp1 || _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
|
||||||
if obj.BaseFee == nil {
|
if obj.BaseFee == nil {
|
||||||
w.Write(rlp.EmptyString)
|
w.Write(rlp.EmptyString)
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -53,41 +54,48 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
|
||||||
w.WriteBigInt(obj.BaseFee)
|
w.WriteBigInt(obj.BaseFee)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
|
||||||
if obj.WithdrawalsHash == nil {
|
if obj.WithdrawalsHash == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteBytes(obj.WithdrawalsHash[:])
|
w.WriteBytes(obj.WithdrawalsHash[:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp3 || _tmp4 || _tmp5 || _tmp6 {
|
if _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
|
||||||
if obj.BlobGasUsed == nil {
|
if obj.BlobGasUsed == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteUint64((*obj.BlobGasUsed))
|
w.WriteUint64((*obj.BlobGasUsed))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp4 || _tmp5 || _tmp6 {
|
if _tmp4 || _tmp5 || _tmp6 || _tmp7 {
|
||||||
if obj.ExcessBlobGas == nil {
|
if obj.ExcessBlobGas == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteUint64((*obj.ExcessBlobGas))
|
w.WriteUint64((*obj.ExcessBlobGas))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp5 || _tmp6 {
|
if _tmp5 || _tmp6 || _tmp7 {
|
||||||
if obj.ParentBeaconRoot == nil {
|
if obj.ParentBeaconRoot == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteBytes(obj.ParentBeaconRoot[:])
|
w.WriteBytes(obj.ParentBeaconRoot[:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if _tmp6 {
|
if _tmp6 || _tmp7 {
|
||||||
if obj.RequestsHash == nil {
|
if obj.RequestsHash == nil {
|
||||||
w.Write([]byte{0x80})
|
w.Write([]byte{0x80})
|
||||||
} else {
|
} else {
|
||||||
w.WriteBytes(obj.RequestsHash[:])
|
w.WriteBytes(obj.RequestsHash[:])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if _tmp7 {
|
||||||
|
if obj.ParentProposerPubkey == nil {
|
||||||
|
w.Write([]byte{0x80})
|
||||||
|
} else {
|
||||||
|
w.WriteBytes(obj.ParentProposerPubkey[:])
|
||||||
|
}
|
||||||
|
}
|
||||||
w.ListEnd(_tmp0)
|
w.ListEnd(_tmp0)
|
||||||
return w.Flush()
|
return w.Flush()
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,7 @@ func (r *Receipt) decodeTyped(b []byte) error {
|
||||||
return errShortTypedReceipt
|
return errShortTypedReceipt
|
||||||
}
|
}
|
||||||
switch b[0] {
|
switch b[0] {
|
||||||
case DynamicFeeTxType, AccessListTxType, BlobTxType, SetCodeTxType:
|
case DynamicFeeTxType, AccessListTxType, BlobTxType, SetCodeTxType, PoLTxType:
|
||||||
var data receiptRLP
|
var data receiptRLP
|
||||||
err := rlp.DecodeBytes(b[1:], &data)
|
err := rlp.DecodeBytes(b[1:], &data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
@ -368,7 +368,7 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
|
||||||
}
|
}
|
||||||
w.WriteByte(r.Type)
|
w.WriteByte(r.Type)
|
||||||
switch r.Type {
|
switch r.Type {
|
||||||
case AccessListTxType, DynamicFeeTxType, BlobTxType, SetCodeTxType:
|
case AccessListTxType, DynamicFeeTxType, BlobTxType, SetCodeTxType, PoLTxType:
|
||||||
rlp.Encode(w, data)
|
rlp.Encode(w, data)
|
||||||
default:
|
default:
|
||||||
// For unsupported types, write nothing. Since this is for
|
// For unsupported types, write nothing. Since this is for
|
||||||
|
|
|
||||||
|
|
@ -51,6 +51,9 @@ const (
|
||||||
DynamicFeeTxType = 0x02
|
DynamicFeeTxType = 0x02
|
||||||
BlobTxType = 0x03
|
BlobTxType = 0x03
|
||||||
SetCodeTxType = 0x04
|
SetCodeTxType = 0x04
|
||||||
|
|
||||||
|
// Berachain specific.
|
||||||
|
PoLTxType = 0x7E
|
||||||
)
|
)
|
||||||
|
|
||||||
// Transaction is an Ethereum transaction.
|
// Transaction is an Ethereum transaction.
|
||||||
|
|
@ -213,6 +216,8 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
|
||||||
inner = new(BlobTx)
|
inner = new(BlobTx)
|
||||||
case SetCodeTxType:
|
case SetCodeTxType:
|
||||||
inner = new(SetCodeTx)
|
inner = new(SetCodeTx)
|
||||||
|
case PoLTxType:
|
||||||
|
inner = new(PoLTx)
|
||||||
default:
|
default:
|
||||||
return nil, ErrTxTypeNotSupported
|
return nil, ErrTxTypeNotSupported
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue