Merge branch 'main' into update-main

This commit is contained in:
Cal Bera 2025-09-09 13:55:23 -07:00
commit 16b72db3ba
135 changed files with 3390 additions and 894 deletions

View file

@ -0,0 +1,10 @@
{
"permissions": {
"allow": [
"Bash(git add:*)",
"Bash(git commit:*)",
"Bash(git push:*)"
],
"deny": []
}
}

View file

@ -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 }}

View file

@ -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 }}

View file

@ -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
View file

@ -1,33 +1,4 @@
# Lines starting with '#' are comments.
# Each line is a file pattern followed by one or more owners.
accounts/usbwallet/ @gballet
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
* @calbera

View file

@ -21,7 +21,7 @@ Please make sure your contributions adhere to our coding guidelines:
(i.e. uses [gofmt](https://golang.org/cmd/gofmt/)).
* Code must be documented adhering to the official Go
[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.
* E.g. "eth, rpc: make trace configs optional"

11
.github/dependabot.yml vendored Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

View file

@ -1,5 +1,5 @@
# Number of days of inactivity before an Issue is closed for lack of response
daysUntilClose: 30
daysUntilClose: 366
# Label requiring a response
responseRequiredLabel: "need:more-information"
# 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
View 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
View 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
View 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"

View file

@ -1,16 +1,16 @@
name: CI
on:
push:
branches:
- master
branches: [ main, "release/*" ]
pull_request:
branches:
- master
branches: [ main ]
workflow_dispatch:
jobs:
lint:
name: Lint
runs-on: self-hosted-ghr
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
@ -25,7 +25,7 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: 1.25
go-version: 1.24
cache: false
- name: Run linters
@ -34,15 +34,9 @@ jobs:
go run build/ci.go check_generate
go run build/ci.go check_baddeps
test:
name: Test
needs: lint
runs-on: self-hosted-ghr
strategy:
matrix:
go:
- '1.25'
- '1.24'
tests:
name: Tests
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
@ -51,8 +45,8 @@ jobs:
- name: Set up Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
go-version: 1.24.0
cache: false
- name: Run tests
run: go test ./...
run: go test -short ./...

118
.github/workflows/docker.yml vendored Normal file
View 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
View 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
View 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'
![image](https://raw.githubusercontent.com/berachain/bera-geth/main/.github/meta/bera-geth.png)
## 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[@]}"

8
.gitignore vendored
View file

@ -55,4 +55,10 @@ cmd/ethkey/ethkey
cmd/evm/evm
cmd/geth/geth
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
View 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
View 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
```

View file

@ -6,24 +6,36 @@ ARG BUILDNUM=""
# Build Geth in a stock Go builder container
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
# Get dependencies - will also be cached if we won't change go.mod/go.sum
COPY go.mod /go-ethereum/
COPY go.sum /go-ethereum/
RUN cd /go-ethereum && go mod download
COPY go.mod /bera-geth/
COPY go.sum /bera-geth/
RUN cd /bera-geth && go mod download
ADD . /go-ethereum
RUN cd /go-ethereum && go run build/ci.go install -static ./cmd/geth
ADD . /bera-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
FROM alpine:latest
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
ENTRYPOINT ["geth"]
ENTRYPOINT ["bera-geth"]
# Add some metadata labels to help programmatic image consumption
ARG COMMIT=""

View file

@ -6,28 +6,44 @@ ARG BUILDNUM=""
# Build Geth in a stock Go builder container
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
# Get dependencies - will also be cached if we won't change go.mod/go.sum
COPY go.mod /go-ethereum/
COPY go.sum /go-ethereum/
RUN cd /go-ethereum && go mod download
COPY go.mod /bera-geth/
COPY go.sum /bera-geth/
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
# 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.
#
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
FROM alpine:latest
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

View file

@ -2,17 +2,17 @@
# with Go source code. If you know what GOPATH is then you probably
# 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
GO ?= latest
GORUN = go run
#? geth: Build geth.
geth:
$(GORUN) build/ci.go install ./cmd/geth
#? bera-geth: Build bera-geth.
bera-geth:
$(GORUN) build/ci.go install ./cmd/bera-geth
@echo "Done building."
@echo "Run \"$(GOBIN)/geth\" to launch geth."
@echo "Run \"$(GOBIN)/bera-geth\" to launch bera-geth."
#? evm: Build evm.
evm:

View file

@ -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).
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
```shell
make geth
make bera-geth
```
or, to build the full suite of utilities:
@ -37,19 +37,19 @@ directory.
| 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. |
| `clef` | Stand-alone signing tool, which can be used as a backend signer for `geth`. |
| **`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 `bera-geth`. |
| `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. |
| `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`). |
## Running `geth`
## Running `bera-geth`
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)),
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
@ -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:
```shell
$ geth console
$ bera-geth console
```
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
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),
(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),
as well as `geth`'s own [management APIs](https://geth.ethereum.org/docs/interacting-with-geth/rpc).
(note: the `web3` version bundled within `bera-geth` is very old, and not up to date with official docs),
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
`geth` instance with `geth attach`.
`bera-geth` instance with `bera-geth attach`.
### 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.
```shell
$ geth --holesky console
$ bera-geth --holesky console
```
The `console` subcommand has the same meaning as above and is equally
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
test network, which uses different P2P bootnodes, different network IDs and genesis
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
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.,
`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.
*Note: Although some internal protective measures prevent transactions from
crossing over between the main network and test network, you should always
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.*
### 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:
```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
export your existing configuration:
```shell
$ geth --your-favourite-flags dumpconfig
$ bera-geth --your-favourite-flags dumpconfig
```
#### Docker quick start
@ -150,25 +150,25 @@ docker run -d --name ethereum-node -v /Users/alice/ethereum:/root \
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
saving your blockchain as well as map the default ports. There is also an `alpine` tag
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
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.
### 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
this, `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)).
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 [`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
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
subset of APIs due to security reasons. These can be turned on/off and configured as
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)
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
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.
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:

View file

@ -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

View file

@ -101,6 +101,17 @@ func (ec *engineClient) callNewPayload(fork string, event types.ChainHeadEvent)
params = []any{execData}
)
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":
method = "engine_newPayloadV4"
parentBeaconRoot := event.BeaconHead.ParentRoot
@ -145,6 +156,8 @@ func (ec *engineClient) callForkchoiceUpdated(fork string, event types.ChainHead
var method string
switch fork {
case "electra1":
method = "engine_forkchoiceUpdatedV3P11"
case "deneb", "electra":
method = "engine_forkchoiceUpdatedV3"
case "capella":

View file

@ -21,6 +21,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
ProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
}
var enc PayloadAttributes
enc.Timestamp = hexutil.Uint64(p.Timestamp)
@ -28,6 +29,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) {
enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient
enc.Withdrawals = p.Withdrawals
enc.BeaconRoot = p.BeaconRoot
enc.ProposerPubkey = p.ProposerPubkey
return json.Marshal(&enc)
}
@ -39,6 +41,7 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
ProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
}
var dec PayloadAttributes
if err := json.Unmarshal(input, &dec); err != nil {
@ -62,5 +65,8 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error {
if dec.BeaconRoot != nil {
p.BeaconRoot = dec.BeaconRoot
}
if dec.ProposerPubkey != nil {
p.ProposerPubkey = dec.ProposerPubkey
}
return nil
}

View file

@ -33,9 +33,10 @@ import (
type PayloadVersion byte
var (
PayloadV1 PayloadVersion = 0x1
PayloadV2 PayloadVersion = 0x2
PayloadV3 PayloadVersion = 0x3
PayloadV1 PayloadVersion = 0x1
PayloadV2 PayloadVersion = 0x2
PayloadV3 PayloadVersion = 0x3
PayloadV3P11 PayloadVersion = 0x31
)
//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"`
Withdrawals []*types.Withdrawal `json:"withdrawals"`
BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"`
ProposerPubkey *common.Pubkey `json:"parentProposerPubkey"` // Berachain: only used prague1 and onwards
}
// 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
// Withdrawals value will propagate through the returned block. Empty
// 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) {
block, err := ExecutableDataToBlockNoHash(data, versionedHashes, beaconRoot, requests)
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, proposerPubkey)
if err != nil {
return nil, err
}
@ -232,7 +234,7 @@ func ExecutableDataToBlock(data ExecutableData, versionedHashes []common.Hash, b
// ExecutableDataToBlockNoHash is analogous to ExecutableDataToBlock, but is used
// 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).
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)
if err != nil {
return nil, err
@ -275,26 +277,27 @@ func ExecutableDataToBlockNoHash(data ExecutableData, versionedHashes []common.H
}
header := &types.Header{
ParentHash: data.ParentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: data.FeeRecipient,
Root: data.StateRoot,
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
ReceiptHash: data.ReceiptsRoot,
Bloom: types.BytesToBloom(data.LogsBloom),
Difficulty: common.Big0,
Number: new(big.Int).SetUint64(data.Number),
GasLimit: data.GasLimit,
GasUsed: data.GasUsed,
Time: data.Timestamp,
BaseFee: data.BaseFeePerGas,
Extra: data.ExtraData,
MixDigest: data.Random,
WithdrawalsHash: withdrawalsRoot,
ExcessBlobGas: data.ExcessBlobGas,
BlobGasUsed: data.BlobGasUsed,
ParentBeaconRoot: beaconRoot,
RequestsHash: requestsHash,
ParentHash: data.ParentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: data.FeeRecipient,
Root: data.StateRoot,
TxHash: types.DeriveSha(types.Transactions(txs), trie.NewStackTrie(nil)),
ReceiptHash: data.ReceiptsRoot,
Bloom: types.BytesToBloom(data.LogsBloom),
Difficulty: common.Big0,
Number: new(big.Int).SetUint64(data.Number),
GasLimit: data.GasLimit,
GasUsed: data.GasUsed,
Time: data.Timestamp,
BaseFee: data.BaseFeePerGas,
Extra: data.ExtraData,
MixDigest: data.Random,
WithdrawalsHash: withdrawalsRoot,
ExcessBlobGas: data.ExcessBlobGas,
BlobGasUsed: data.BlobGasUsed,
ParentBeaconRoot: beaconRoot,
RequestsHash: requestsHash,
ParentProposerPubkey: proposerPubkey,
}
return types.NewBlockWithHeader(header).
WithBody(types.Body{Transactions: txs, Uncles: nil, Withdrawals: data.Withdrawals}).
@ -359,8 +362,8 @@ type ExecutionPayloadBody struct {
// Client identifiers to support ClientVersionV1.
const (
ClientCode = "GE"
ClientName = "go-ethereum"
ClientCode = "BG"
ClientName = "bera-geth"
)
// ClientVersionV1 contains information which identifies a client implementation.

View file

@ -5,54 +5,54 @@
# https://github.com/ethereum/execution-spec-tests/releases/download/fusaka-devnet-3%40v1.0.0
576261e1280e5300c458aa9b05eccb2fec5ff80a0005940dc52fa03fdd907249 fixtures_fusaka-devnet-3.tar.gz
# version:golang 1.25.0
# version:golang 1.24.4
# https://go.dev/dl/
4bd01e91297207bfa450ea40d4d5a93b1b531a5e438473b2a06e18e077227225 go1.25.0.src.tar.gz
e5234a7dac67bc86c528fe9752fc9d63557918627707a733ab4cac1a6faed2d4 go1.25.0.aix-ppc64.tar.gz
5bd60e823037062c2307c71e8111809865116714d6f6b410597cf5075dfd80ef go1.25.0.darwin-amd64.tar.gz
95e836238bcf8f9a71bffea43344cbd35ee1f16db3aaced2f98dbac045d102db go1.25.0.darwin-amd64.pkg
544932844156d8172f7a28f77f2ac9c15a23046698b6243f633b0a0b00c0749c go1.25.0.darwin-arm64.tar.gz
202a0d8338c152cb4c9f04782429e9ba8bef31d9889272380837e4043c9d800a go1.25.0.darwin-arm64.pkg
5ed3cf9a810a1483822538674f1336c06b51aa1b94d6d545a1a0319a48177120 go1.25.0.dragonfly-amd64.tar.gz
abea5d5c6697e6b5c224731f2158fe87c602996a2a233ac0c4730cd57bf8374e go1.25.0.freebsd-386.tar.gz
86e6fe0a29698d7601c4442052dac48bd58d532c51cccb8f1917df648138730b go1.25.0.freebsd-amd64.tar.gz
d90b78e41921f72f30e8bbc81d9dec2cff7ff384a33d8d8debb24053e4336bfe go1.25.0.freebsd-arm.tar.gz
451d0da1affd886bfb291b7c63a6018527b269505db21ce6e14724f22ab0662e go1.25.0.freebsd-arm64.tar.gz
7b565f76bd8bda46549eeaaefe0e53b251e644c230577290c0f66b1ecdb3cdbe go1.25.0.freebsd-riscv64.tar.gz
b1e1fdaab1ad25aa1c08d7a36c97d45d74b98b89c3f78c6d2145f77face54a2c go1.25.0.illumos-amd64.tar.gz
8c602dd9d99bc9453b3995d20ce4baf382cc50855900a0ece5de9929df4a993a go1.25.0.linux-386.tar.gz
2852af0cb20a13139b3448992e69b868e50ed0f8a1e5940ee1de9e19a123b613 go1.25.0.linux-amd64.tar.gz
05de75d6994a2783699815ee553bd5a9327d8b79991de36e38b66862782f54ae go1.25.0.linux-arm64.tar.gz
a5a8f8198fcf00e1e485b8ecef9ee020778bf32a408a4e8873371bfce458cd09 go1.25.0.linux-armv6l.tar.gz
cab86b1cf761b1cb3bac86a8877cfc92e7b036fc0d3084123d77013d61432afc go1.25.0.linux-loong64.tar.gz
d66b6fb74c3d91b9829dc95ec10ca1f047ef5e89332152f92e136cf0e2da5be1 go1.25.0.linux-mips.tar.gz
4082e4381a8661bc2a839ff94ba3daf4f6cde20f8fb771b5b3d4762dc84198a2 go1.25.0.linux-mips64.tar.gz
70002c299ec7f7175ac2ef673b1b347eecfa54ae11f34416a6053c17f855afcc go1.25.0.linux-mips64le.tar.gz
b00a3a39eff099f6df9f1c7355bf28e4589d0586f42d7d4a394efb763d145a73 go1.25.0.linux-mipsle.tar.gz
df166f33bd98160662560a72ff0b4ba731f969a80f088922bddcf566a88c1ec1 go1.25.0.linux-ppc64.tar.gz
0f18a89e7576cf2c5fa0b487a1635d9bcbf843df5f110e9982c64df52a983ad0 go1.25.0.linux-ppc64le.tar.gz
c018ff74a2c48d55c8ca9b07c8e24163558ffec8bea08b326d6336905d956b67 go1.25.0.linux-riscv64.tar.gz
34e5a2e19f2292fbaf8783e3a241e6e49689276aef6510a8060ea5ef54eee408 go1.25.0.linux-s390x.tar.gz
f8586cdb7aa855657609a5c5f6dbf523efa00c2bbd7c76d3936bec80aa6c0aba go1.25.0.netbsd-386.tar.gz
ae8dc1469385b86a157a423bb56304ba45730de8a897615874f57dd096db2c2a go1.25.0.netbsd-amd64.tar.gz
1ff7e4cc764425fc9dd6825eaee79d02b3c7cafffbb3691687c8d672ade76cb7 go1.25.0.netbsd-arm.tar.gz
e1b310739f26724216aa6d7d7208c4031f9ff54c9b5b9a796ddc8bebcb4a5f16 go1.25.0.netbsd-arm64.tar.gz
4802a9b20e533da91adb84aab42e94aa56cfe3e5475d0550bed3385b182e69d8 go1.25.0.openbsd-386.tar.gz
c016cd984bebe317b19a4f297c4f50def120dc9788490540c89f28e42f1dabe1 go1.25.0.openbsd-amd64.tar.gz
a1e31d0bf22172ddde42edf5ec811ef81be43433df0948ece52fecb247ccfd8d go1.25.0.openbsd-arm.tar.gz
343ea8edd8c218196e15a859c6072d0dd3246fbbb168481ab665eb4c4140458d go1.25.0.openbsd-arm64.tar.gz
694c14da1bcaeb5e3332d49bdc2b6d155067648f8fe1540c5de8f3cf8e157154 go1.25.0.openbsd-ppc64.tar.gz
aa510ad25cf54c06cd9c70b6d80ded69cb20188ac6e1735655eef29ff7e7885f go1.25.0.openbsd-riscv64.tar.gz
46f8cef02086cf04bf186c5912776b56535178d4cb319cd19c9fdbdd29231986 go1.25.0.plan9-386.tar.gz
29b34391d84095e44608a228f63f2f88113a37b74a79781353ec043dfbcb427b go1.25.0.plan9-amd64.tar.gz
0a047107d13ebe7943aaa6d54b1d7bbd2e45e68ce449b52915a818da715799c2 go1.25.0.plan9-arm.tar.gz
9977f9e4351984364a3b2b78f8b88bfd1d339812356d5237678514594b7d3611 go1.25.0.solaris-amd64.tar.gz
df9f39db82a803af0db639e3613a36681ab7a42866b1384b3f3a1045663961a7 go1.25.0.windows-386.zip
afd9e0a8d2665ff122c8302bb4a3ce4a5331e4e630ddc388be1f9238adfa8fe3 go1.25.0.windows-386.msi
89efb4f9b30812eee083cc1770fdd2913c14d301064f6454851428f9707d190b go1.25.0.windows-amd64.zip
936bd87109da515f79d80211de5bc6cbda071f2cc577f7e6af1a9e754ea34819 go1.25.0.windows-amd64.msi
27bab004c72b3d7bd05a69b6ec0fc54a309b4b78cc569dd963d8b3ec28bfdb8c go1.25.0.windows-arm64.zip
357d030b217ff68e700b6cfc56097bc21ad493bb45b79733a052d112f5031ed9 go1.25.0.windows-arm64.msi
5a86a83a31f9fa81490b8c5420ac384fd3d95a3e71fba665c7b3f95d1dfef2b4 go1.24.4.src.tar.gz
0d2af78e3b6e08f8013dbbdb26ae33052697b6b72e03ec17d496739c2a1aed68 go1.24.4.aix-ppc64.tar.gz
69bef555e114b4a2252452b6e7049afc31fbdf2d39790b669165e89525cd3f5c go1.24.4.darwin-amd64.tar.gz
c4d74453a26f488bdb4b0294da4840d9020806de4661785334eb6d1803ee5c27 go1.24.4.darwin-amd64.pkg
27973684b515eaf461065054e6b572d9390c05e69ba4a423076c160165336470 go1.24.4.darwin-arm64.tar.gz
2fe1f8746745c4bfebd494583aaef24cad42594f6d25ed67856879d567ee66e7 go1.24.4.darwin-arm64.pkg
70b2de9c1cafe5af7be3eb8f80753cce0501ef300db3f3bd59be7ccc464234e1 go1.24.4.dragonfly-amd64.tar.gz
8d529839db29ee171505b89dc9c3de76003a4ab56202d84bddbbecacbfb6d7c9 go1.24.4.freebsd-386.tar.gz
6cbc3ad6cc21bdcc7283824d3ac0e85512c02022f6a35eb2e844882ea6e8448c go1.24.4.freebsd-amd64.tar.gz
d49ae050c20aff646a7641dd903f03eb674570790b90ffb298076c4d41e36655 go1.24.4.freebsd-arm.tar.gz
e31924abef2a28456b7103c0a5d333dcc11ecf19e76d5de1a383ad5fe0b42457 go1.24.4.freebsd-arm64.tar.gz
b5bca135eae8ebddf22972611ac1c58ae9fbb5979fd953cc5245c5b1b2517546 go1.24.4.freebsd-riscv64.tar.gz
7d5efda511ff7e3114b130acee5d0bffbb078fedbfa9b2c1b6a807107e1ca23a go1.24.4.illumos-amd64.tar.gz
130c9b061082eca15513e595e9952a2ded32e737e609dd0e49f7dfa74eba026d go1.24.4.linux-386.tar.gz
77e5da33bb72aeaef1ba4418b6fe511bc4d041873cbf82e5aa6318740df98717 go1.24.4.linux-amd64.tar.gz
d5501ee5aca0f258d5fe9bfaed401958445014495dc115f202d43d5210b45241 go1.24.4.linux-arm64.tar.gz
6a554e32301cecae3162677e66d4264b81b3b1a89592dd1b7b5c552c7a49fe37 go1.24.4.linux-armv6l.tar.gz
b208eb25fe244408cbe269ed426454bc46e59d0e0a749b6240d39e884e969875 go1.24.4.linux-loong64.tar.gz
fddfcb28fd36fe63d2ae181026798f86f3bbd3a7bb0f1e1f617dd3d604bf3fe4 go1.24.4.linux-mips.tar.gz
7934b924d5ab8c8ae3134a09a6ae74d3c39f63f6c4322ec289364dbbf0bac3ca go1.24.4.linux-mips64.tar.gz
fa763d8673f94d6e534bb72c3cf675d4c2b8da4a6da42a89f08c5586106db39c go1.24.4.linux-mips64le.tar.gz
84363dbfe49b41d43df84420a09bd53a4770053d63bfa509868c46a5f8eb3ff7 go1.24.4.linux-mipsle.tar.gz
28fcbd5d3b56493606873c33f2b4bdd84ba93c633f37313613b5a1e6495c6fe5 go1.24.4.linux-ppc64.tar.gz
9ca4afef813a2578c23843b640ae0290aa54b2e3c950a6cc4c99e16a57dec2ec go1.24.4.linux-ppc64le.tar.gz
1d7034f98662d8f2c8abd7c700ada4093acb4f9c00e0e51a30344821d0785c77 go1.24.4.linux-riscv64.tar.gz
0449f3203c39703ab27684be763e9bb78ca9a051e0e4176727aead9461b6deb5 go1.24.4.linux-s390x.tar.gz
954b49ccc2cfcf4b5f7cd33ff662295e0d3b74e7590c8e25fc2abb30bce120ba go1.24.4.netbsd-386.tar.gz
370fabcdfee7c18857c96fdd5b706e025d4fb86a208da88ba56b1493b35498e9 go1.24.4.netbsd-amd64.tar.gz
7935ef95d4d1acc48587b1eb4acab98b0a7d9569736a32398b9c1d2e89026865 go1.24.4.netbsd-arm.tar.gz
ead78fd0fa29fbb176cc83f1caa54032e1a44f842affa56a682c647e0759f237 go1.24.4.netbsd-arm64.tar.gz
913e217394b851a636b99de175f0c2f9ab9938b41c557f047168f77ee485d776 go1.24.4.openbsd-386.tar.gz
24568da3dcbcdb24ec18b631f072faf0f3763e3d04f79032dc56ad9ec35379c4 go1.24.4.openbsd-amd64.tar.gz
45abf523f870632417ab007de3841f64dd906bde546ffc8c6380ccbe91c7fb73 go1.24.4.openbsd-arm.tar.gz
7c57c69b5dd1e946b28a3034c285240a48e2861bdcb50b7d9c0ed61bcf89c879 go1.24.4.openbsd-arm64.tar.gz
91ed711f704829372d6931e1897631ef40288b8f9e3cd6ef4a24df7126d1066a go1.24.4.openbsd-ppc64.tar.gz
de5e270d971c8790e8880168d56a2ea103979927c10ded136d792bbdf9bce3d3 go1.24.4.openbsd-riscv64.tar.gz
ff429d03f00bcd32a50f445320b8329d0fadb2a2fff899c11e95e0922a82c543 go1.24.4.plan9-386.tar.gz
39d6363a43fd16b60ae9ad7346a264e982e4fa653dee3b45f83e03cd2f7a6647 go1.24.4.plan9-amd64.tar.gz
1964ae2571259de77b930e97f2891aa92706ff81aac9909d45bb107b0fab16c8 go1.24.4.plan9-arm.tar.gz
a7f9af424e8fb87886664754badca459513f64f6a321d17f1d219b8edf519821 go1.24.4.solaris-amd64.tar.gz
d454d3cb144432f1726bf00e28c6017e78ccb256a8d01b8e3fb1b2e6b5650f28 go1.24.4.windows-386.zip
966ecace1cdbb3497a2b930bdb0f90c3ad32922fa1a7c655b2d4bbeb7e4ac308 go1.24.4.windows-386.msi
b751a1136cb9d8a2e7ebb22c538c4f02c09b98138c7c8bfb78a54a4566c013b1 go1.24.4.windows-amd64.zip
0cbb6e83865747dbe69b3d4155f92e88fcf336ff5d70182dba145e9d7bd3d8f6 go1.24.4.windows-amd64.msi
d17da51bc85bd010754a4063215d15d2c033cc289d67ca9201a03c9041b2969d go1.24.4.windows-arm64.zip
47dbe734b6a829de45654648a7abcf05bdceef5c80e03ea0b208eeebef75a852 go1.24.4.windows-arm64.msi
# version:golangci 2.0.2
# https://github.com/golangci/golangci-lint/releases/

View file

@ -64,18 +64,18 @@ import (
)
var (
// Files that end up in the geth*.zip archive.
// Files that end up in the bera-geth*.zip archive.
gethArchiveFiles = []string{
"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{
"COPYING",
executablePath("abigen"),
executablePath("evm"),
executablePath("geth"),
executablePath("bera-geth"),
executablePath("rlpdump"),
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.",
},
{
BinaryName: "geth",
BinaryName: "bera-geth",
Description: "Ethereum CLI client.",
},
{
@ -238,6 +238,7 @@ func buildFlags(env build.Environment, staticLinking bool, buildTags []string) (
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.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,
// 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)")
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)`)
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
)
flag.CommandLine.Parse(cmdline)
@ -569,9 +570,9 @@ func doArchive(cmdline []string) {
var (
env = build.Env()
basegeth = archiveBasename(*arch, version.Archive(env.Commit))
geth = "geth-" + basegeth + ext
alltools = "geth-alltools-" + basegeth + ext
basegeth = archiveBasename(*arch, version.Archive(env.Tag, env.Commit))
geth = "bera-geth-" + basegeth + ext
alltools = "bera-geth-alltools-" + basegeth + ext
)
maybeSkipArchive(env)
if err := build.WriteArchive(geth, gethArchiveFiles); err != nil {
@ -611,7 +612,7 @@ func archiveUpload(archive string, blobstore string, signer string, signifyVar s
}
if 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))
if err := signify.SignFile(archive, archive+".sig", key, untrustedComment, trustedComment); err != nil {
return err
@ -647,17 +648,17 @@ func maybeSkipArchive(env build.Environment) {
log.Printf("skipping archive creation because this is a PR build")
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)
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) {
var (
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`)
)
flag.CommandLine.Parse(cmdline)
@ -676,21 +677,16 @@ func doDockerBuildx(cmdline []string) {
build.MustRun(auther)
}
// 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:stable - Version tag publish on GitHub, Geth only
// - 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:latest - Pushes to the main branch, Geth only
// - ethereum/client-go:alltools-latest - Pushes to the main branch, Geth & tools
// - 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
var tags []string
var tag string
switch {
case env.Branch == "master":
tags = []string{"latest"}
case env.Branch == "main":
tag = "latest"
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
check := exec.Command("docker", "buildx", "inspect", "multi-arch-builder")
@ -705,22 +701,25 @@ func doDockerBuildx(cmdline []string) {
{file: "Dockerfile", base: fmt.Sprintf("%s:", *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)
cmd := exec.Command("docker", "buildx", "build",
"--build-arg", "COMMIT="+env.Commit,
"--build-arg", "VERSION="+version.WithMeta,
"--build-arg", "BUILDNUM="+env.Buildnum,
"--tag", gethImage,
"--platform", *platform,
"--file", spec.file,
)
if *upload {
cmd.Args = append(cmd.Args, "--push")
}
cmd.Args = append(cmd.Args, ".")
build.MustRun(cmd)
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",
"--build-arg", "COMMIT="+env.Commit,
"--build-arg", "VERSION="+dockerVersion,
"--build-arg", "BUILDNUM="+env.Buildnum,
"--tag", gethImage,
"--platform", *platform,
"--file", spec.file,
)
if *upload {
cmd.Args = append(cmd.Args, "--push")
}
cmd.Args = append(cmd.Args, ".")
build.MustRun(cmd)
}
}
@ -730,7 +729,7 @@ func doDebianSource(cmdline []string) {
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`)
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)`)
now = time.Now()
)
@ -889,7 +888,7 @@ func makeWorkdir(wdflag string) string {
if wdflag != "" {
err = os.MkdirAll(wdflag, 0744)
} else {
wdflag, err = os.MkdirTemp("", "geth-build-")
wdflag, err = os.MkdirTemp("", "bera-geth-build-")
}
if err != nil {
log.Fatal(err)
@ -1043,7 +1042,7 @@ func doWindowsInstaller(cmdline []string) {
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)`)
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)`)
)
flag.CommandLine.Parse(cmdline)
@ -1062,7 +1061,7 @@ func doWindowsInstaller(cmdline []string) {
continue
}
allTools = append(allTools, filepath.Base(file))
if filepath.Base(file) == "geth.exe" {
if filepath.Base(file) == "bera-geth.exe" {
gethTool = file
} else {
devTools = append(devTools, file)
@ -1076,7 +1075,7 @@ func doWindowsInstaller(cmdline []string) {
"Geth": gethTool,
"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.uninstall.nsh", filepath.Join(*workdir, "uninstall.nsh"), 0644, allTools)
build.Render("build/nsis.pathupdate.nsh", filepath.Join(*workdir, "PathUpdate.nsh"), 0644, nil)
@ -1094,7 +1093,7 @@ func doWindowsInstaller(cmdline []string) {
if env.Commit != "" {
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 {
log.Fatalf("Failed to convert installer file path: %v", err)
}
@ -1104,7 +1103,7 @@ func doWindowsInstaller(cmdline []string) {
"/DMINORVERSION="+ver[1],
"/DBUILDVERSION="+ver[2],
"/DARCH="+*arch,
filepath.Join(*workdir, "geth.nsi"),
filepath.Join(*workdir, "bera-geth.nsi"),
)
// Sign and publish installer.
if err := archiveUpload(installer, *upload, *signer, *signify); err != nil {
@ -1116,7 +1115,7 @@ func doWindowsInstaller(cmdline []string) {
func doPurge(cmdline []string) {
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`)
)
flag.CommandLine.Parse(cmdline)

View file

@ -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

View file

@ -47,6 +47,7 @@ import (
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/node"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/triedb"
"github.com/urfave/cli/v2"
)
@ -282,8 +283,19 @@ func initGenesis(ctx *cli.Context) error {
chaindb := utils.MakeChainDatabase(ctx, stack, false)
defer chaindb.Close()
triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle())
defer triedb.Close()
// 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()
}
_, hash, compatErr, err := core.SetupGenesisBlockWithOverride(chaindb, triedb, genesis, &overrides)
if err != nil {
@ -480,6 +492,10 @@ func importHistory(ctx *cli.Context) error {
network = "holesky"
case ctx.Bool(utils.HoodiFlag.Name):
network = "hoodi"
case ctx.Bool(utils.BerachainFlag.Name):
network = "berachain"
case ctx.Bool(utils.BepoliaFlag.Name):
network = "bepolia"
}
} else {
// 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.SepoliaFlag.Name):
network = "sepolia"
case ctx.IsSet(utils.BerachainFlag.Name):
network = "berachain"
case ctx.IsSet(utils.BepoliaFlag.Name):
network = "bepolia"
default:
return errors.New("unsupported network, no known era1 checksums")
}

View file

@ -131,7 +131,13 @@ func defaultNodeConfig() node.Config {
git, _ := version.VCS()
cfg := node.DefaultConfig
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.WSModules = append(cfg.WSModules, "eth")
cfg.IPCPath = clientIdentifier + ".ipc"

View file

@ -69,7 +69,7 @@ func TestConsoleWelcome(t *testing.T) {
geth.Expect(`
Welcome to the Geth JavaScript console!
instance: Geth/v{{gethver}}/{{goos}}-{{goarch}}/{{gover}}
instance: BeraGeth/v{{gethver}}/{{goos}}-{{goarch}}/{{gover}}
at block: 0 ({{niltime}})
datadir: {{.Datadir}}
modules: {{apis}}
@ -89,9 +89,9 @@ func TestAttachWelcome(t *testing.T) {
)
// Configure the instance for IPC attachment
if runtime.GOOS == "windows" {
ipc = `\\.\pipe\geth` + strconv.Itoa(trulyRandInt(100000, 999999))
ipc = `\\.\pipe\bera-geth` + strconv.Itoa(trulyRandInt(100000, 999999))
} else {
ipc = filepath.Join(t.TempDir(), "geth.ipc")
ipc = filepath.Join(t.TempDir(), "bera-geth.ipc")
}
// And HTTP + WS attachment
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(`
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}}
datadir: {{datadir}}{{end}}
modules: {{apis}}

View file

@ -21,6 +21,7 @@ import (
"os"
"path/filepath"
"strconv"
"strings"
"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.
func TestCustomBackend(t *testing.T) {
t.Parallel()
@ -186,9 +323,9 @@ func TestCustomBackend(t *testing.T) {
{ // Reject invalid backend choice
initArgs: []string{"--db.engine", "mssql"},
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
execExpect: `0x0000000000000042`,
execExpect: `0x0000000000001234`,
},
} {
if err := testfunc(t, tt); err != nil {

View file

@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// 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
import (
@ -46,7 +46,7 @@ import (
)
const (
clientIdentifier = "geth" // Client identifier to advertise over the network
clientIdentifier = "bera-geth" // Client identifier to advertise over the network
)
var (
@ -208,7 +208,7 @@ var app = flags.NewApp("the go-ethereum command line interface")
func init() {
// Initialize the CLI app and start Geth
app.Action = geth
app.Action = berageth
app.Commands = []*cli.Command{
// See chaincmd.go:
initCommand,
@ -256,7 +256,7 @@ func init() {
debug.Flags,
metricsFlags,
)
flags.AutoEnvVars(app.Flags, "GETH")
flags.AutoEnvVars(app.Flags, "BERA_GETH")
app.Before = func(ctx *cli.Context) error {
maxprocs.Set() // Automatically set GOMAXPROCS to match Linux container CPU quota.
@ -264,7 +264,7 @@ func init() {
if err := debug.Setup(ctx); err != nil {
return err
}
flags.CheckEnvVars(ctx, app.Flags, "GETH")
flags.CheckEnvVars(ctx, app.Flags, "BERA_GETH")
return nil
}
app.After = func(ctx *cli.Context) error {
@ -286,24 +286,32 @@ func main() {
func prepare(ctx *cli.Context) {
// If we're running a known preset, log it for convenience.
switch {
case ctx.IsSet(utils.MainnetFlag.Name):
log.Info("Starting bera-geth on Ethereum mainnet...")
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):
log.Info("Starting Geth on Holesky testnet...")
log.Info("Starting bera-geth on Holesky testnet...")
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):
log.Info("Starting Geth on Ethereum mainnet...")
case ctx.IsSet(utils.BepoliaFlag.Name):
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) {
// Make sure we're not on any supported preconfigured testnet either
if !ctx.IsSet(utils.HoleskyFlag.Name) &&
!ctx.IsSet(utils.SepoliaFlag.Name) &&
!ctx.IsSet(utils.HoodiFlag.Name) &&
!ctx.IsSet(utils.BepoliaFlag.Name) &&
!ctx.IsSet(utils.DeveloperFlag.Name) {
// 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)
@ -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
// 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 {
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)
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()
ethClient := ethclient.NewClient(rpcClient)

View file

@ -72,7 +72,12 @@ func printVersion(ctx *cli.Context) error {
git, _ := version.VCS()
fmt.Println(strings.Title(clientIdentifier))
fmt.Println("Version:", version.WithMeta)
// 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)
}
if git.Commit != "" {
fmt.Println("Git Commit:", git.Commit)
}

View file

@ -236,6 +236,10 @@ func ethFilter(args []string) (nodeFilter, error) {
filter = forkid.NewStaticFilter(params.HoleskyChainConfig, core.DefaultHoleskyGenesisBlock().ToBlock())
case "hoodi":
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:
return nil, fmt.Errorf("unknown network %q", args[0])
}

View file

@ -56,6 +56,7 @@ type header struct {
BlobGasUsed *uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
}
type headerMarshaling struct {
@ -117,25 +118,26 @@ func (c *cliqueInput) UnmarshalJSON(input []byte) error {
// ToBlock converts i into a *types.Block
func (i *bbInput) ToBlock() *types.Block {
header := &types.Header{
ParentHash: i.Header.ParentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: common.Address{},
Root: i.Header.Root,
TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyReceiptsHash,
Bloom: i.Header.Bloom,
Difficulty: common.Big0,
Number: i.Header.Number,
GasLimit: i.Header.GasLimit,
GasUsed: i.Header.GasUsed,
Time: i.Header.Time,
Extra: i.Header.Extra,
MixDigest: i.Header.MixDigest,
BaseFee: i.Header.BaseFee,
WithdrawalsHash: i.Header.WithdrawalsHash,
BlobGasUsed: i.Header.BlobGasUsed,
ExcessBlobGas: i.Header.ExcessBlobGas,
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
ParentHash: i.Header.ParentHash,
UncleHash: types.EmptyUncleHash,
Coinbase: common.Address{},
Root: i.Header.Root,
TxHash: types.EmptyTxsHash,
ReceiptHash: types.EmptyReceiptsHash,
Bloom: i.Header.Bloom,
Difficulty: common.Big0,
Number: i.Header.Number,
GasLimit: i.Header.GasLimit,
GasUsed: i.Header.GasUsed,
Time: i.Header.Time,
Extra: i.Header.Extra,
MixDigest: i.Header.MixDigest,
BaseFee: i.Header.BaseFee,
WithdrawalsHash: i.Header.WithdrawalsHash,
BlobGasUsed: i.Header.BlobGasUsed,
ExcessBlobGas: i.Header.ExcessBlobGas,
ParentBeaconRoot: i.Header.ParentBeaconBlockRoot,
ParentProposerPubkey: i.Header.ParentProposerPubkey,
}
// Fill optional values.

View file

@ -101,6 +101,7 @@ type stEnv struct {
ParentExcessBlobGas *uint64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *uint64 `json:"parentBlobGasUsed,omitempty"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
}
type stEnvMarshaling struct {
@ -220,6 +221,7 @@ func (pre *Prestate) Apply(vmConfig vm.Config, chainConfig *params.ChainConfig,
)
core.ProcessParentBlockHash(prevHash, evm)
}
// TODO(BRIP-4): Validate Prague1 block rules.
for i := 0; txIt.Next(); i++ {
tx, err := txIt.Tx()
if err != nil {

View file

@ -38,6 +38,7 @@ func (h header) MarshalJSON() ([]byte, error) {
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
}
var enc header
enc.ParentHash = h.ParentHash
@ -60,6 +61,7 @@ func (h header) MarshalJSON() ([]byte, error) {
enc.BlobGasUsed = (*math.HexOrDecimal64)(h.BlobGasUsed)
enc.ExcessBlobGas = (*math.HexOrDecimal64)(h.ExcessBlobGas)
enc.ParentBeaconBlockRoot = h.ParentBeaconBlockRoot
enc.ParentProposerPubkey = h.ParentProposerPubkey
return json.Marshal(&enc)
}
@ -86,6 +88,7 @@ func (h *header) UnmarshalJSON(input []byte) error {
BlobGasUsed *math.HexOrDecimal64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *math.HexOrDecimal64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
}
var dec header
if err := json.Unmarshal(input, &dec); err != nil {
@ -155,5 +158,8 @@ func (h *header) UnmarshalJSON(input []byte) error {
if dec.ParentBeaconBlockRoot != nil {
h.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
}
if dec.ParentProposerPubkey != nil {
h.ParentProposerPubkey = dec.ParentProposerPubkey
}
return nil
}

View file

@ -37,6 +37,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
}
var enc stEnv
enc.Coinbase = common.UnprefixedAddress(s.Coinbase)
@ -59,6 +60,7 @@ func (s stEnv) MarshalJSON() ([]byte, error) {
enc.ParentExcessBlobGas = (*math.HexOrDecimal64)(s.ParentExcessBlobGas)
enc.ParentBlobGasUsed = (*math.HexOrDecimal64)(s.ParentBlobGasUsed)
enc.ParentBeaconBlockRoot = s.ParentBeaconBlockRoot
enc.ParentProposerPubkey = s.ParentProposerPubkey
return json.Marshal(&enc)
}
@ -85,6 +87,7 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
ParentExcessBlobGas *math.HexOrDecimal64 `json:"parentExcessBlobGas,omitempty"`
ParentBlobGasUsed *math.HexOrDecimal64 `json:"parentBlobGasUsed,omitempty"`
ParentBeaconBlockRoot *common.Hash `json:"parentBeaconBlockRoot"`
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey"`
}
var dec stEnv
if err := json.Unmarshal(input, &dec); err != nil {
@ -154,5 +157,8 @@ func (s *stEnv) UnmarshalJSON(input []byte) error {
if dec.ParentBeaconBlockRoot != nil {
s.ParentBeaconBlockRoot = dec.ParentBeaconBlockRoot
}
if dec.ParentProposerPubkey != nil {
s.ParentProposerPubkey = dec.ParentProposerPubkey
}
return nil
}

View file

@ -150,6 +150,9 @@ func Transition(ctx *cli.Context) error {
if err := applyCancunChecks(&prestate.Env, chainConfig); err != nil {
return err
}
if err := applyPrague1Checks(&prestate.Env, chainConfig); err != nil {
return err
}
// Configure tracer
if ctx.IsSet(TraceTracerFlag.Name) { // Custom tracing
@ -265,6 +268,19 @@ func applyCancunChecks(env *stEnv, chainConfig *params.ChainConfig) error {
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
func (g Alloc) OnRoot(common.Hash) {}

View file

@ -139,7 +139,7 @@ var (
}
NetworkIdFlag = &cli.Uint64Flag{
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,
Category: flags.EthCategory,
}
@ -163,6 +163,17 @@ var (
Usage: "Hoodi network: pre-configured proof-of-stake test network",
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
DeveloperFlag = &cli.BoolFlag{
Name: "dev",
@ -455,7 +466,7 @@ var (
// Performance tuning settings
CacheFlag = &cli.IntFlag{
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,
Category: flags.PerfCategory,
}
@ -1062,9 +1073,9 @@ func setNodeUserIdent(ctx *cli.Context, cfg *node.Config) {
// 1. --bootnodes flag
// 2. Config file
// 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) {
urls := params.MainnetBootnodes
urls := params.BerachainBootnodes
if ctx.IsSet(BootnodesFlag.Name) {
urls = SplitAndTrim(ctx.String(BootnodesFlag.Name))
} else {
@ -1072,12 +1083,16 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
return // Already set by config file, don't apply defaults.
}
switch {
case ctx.Bool(MainnetFlag.Name):
urls = params.MainnetBootnodes
case ctx.Bool(HoleskyFlag.Name):
urls = params.HoleskyBootnodes
case ctx.Bool(SepoliaFlag.Name):
urls = params.SepoliaBootnodes
case ctx.Bool(HoodiFlag.Name):
urls = params.HoodiBootnodes
case ctx.Bool(BepoliaFlag.Name):
urls = params.BepoliaBootnodes
}
}
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.
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
// 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
// Set configurations from CLI flags

View file

@ -37,6 +37,8 @@ var (
Flags: []cli.Flag{
testSepoliaFlag,
testMainnetFlag,
testBepoliaFlag,
testBerachainFlag,
filterQueryFileFlag,
filterErrorFileFlag,
},

View file

@ -85,6 +85,16 @@ var (
Usage: "Use test cases for mainnet network",
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.
@ -117,10 +127,13 @@ func validateHistoryPruneErr(err error, blockNum uint64, historyPruneBlock *uint
return err
}
// TODO(bera): Add test filter & history queries for Berachain mainnet & Bepolia in queries/ folder
func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) {
flags.CheckExclusive(ctx, testMainnetFlag, testSepoliaFlag)
if (ctx.IsSet(testMainnetFlag.Name) || ctx.IsSet(testSepoliaFlag.Name)) && ctx.IsSet(filterQueryFileFlag.Name) {
exit(filterQueryFileFlag.Name + " cannot be used with " + testMainnetFlag.Name + " or " + testSepoliaFlag.Name)
flags.CheckExclusive(ctx, testMainnetFlag, testSepoliaFlag, testBerachainFlag, testBepoliaFlag)
if (ctx.IsSet(testMainnetFlag.Name) || ctx.IsSet(testSepoliaFlag.Name) || ctx.IsSet(testBerachainFlag.Name) || ctx.IsSet(testBepoliaFlag.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
@ -166,6 +179,44 @@ func testConfigFromCLI(ctx *cli.Context) (cfg testConfig) {
}
cfg.historyPruneBlock = new(uint64)
*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:
cfg.fsys = os.DirFS(".")
cfg.filterQueryFile = ctx.String(filterQueryFileFlag.Name)

View file

@ -39,11 +39,16 @@ const (
HashLength = 32
// AddressLength is the expected length of the address
AddressLength = 20
// Berachain: PubkeyLength represents the expected byte length of a BLS12-381 public key
// as used by the beacon chain.
PubkeyLength = 48
)
var (
hashT = reflect.TypeFor[Hash]()
addressT = reflect.TypeFor[Address]()
hashT = reflect.TypeOf(Hash{})
addressT = reflect.TypeOf(Address{})
pubkeyT = reflect.TypeOf(Pubkey{})
// MaxAddress represents the maximum possible address value.
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))
}
/////////// 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[:])
}

View file

@ -282,6 +282,17 @@ func (beacon *Beacon) verifyHeader(chain consensus.ChainHeaderReader, header, pa
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
}

View file

@ -54,6 +54,21 @@ func VerifyEIP1559Header(config *params.ChainConfig, parent, header *types.Heade
// CalcBaseFee calculates the basefee of the header.
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 !config.IsLondon(parent.Number) {
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.Mul(num, parent.BaseFee)
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 {
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.Mul(num, parent.BaseFee)
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)
if baseFee.Cmp(common.Big0) < 0 {

View file

@ -20,9 +20,11 @@ import (
"errors"
"fmt"
"github.com/davecgh/go-spew/spew"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"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
// 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 {
// check EIP 7934 RLP-encoded block size cap
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 {
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)
}
@ -85,9 +88,48 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
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.
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
blobs += len(tx.BlobHashes())

View file

@ -30,8 +30,131 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"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.
func TestHeaderVerification(t *testing.T) {
testHeaderVerification(t, rawdb.HashScheme)

View file

@ -102,6 +102,25 @@ func (b *BlockGen) SetParentBeaconRoot(root common.Hash) {
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
// 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 (
blockContext = NewEVMBlockContext(b.header, bc, &b.header.Coinbase)
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))
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 {
panic(err)
}
@ -619,6 +643,9 @@ func (cm *chainMaker) makeHeader(parent *types.Block, state *state.StateDB, engi
header.BlobGasUsed = new(uint64)
header.ParentBeaconRoot = new(common.Hash)
}
if cm.config.IsPrague1(header.Number, header.Time) {
header.ParentProposerPubkey = new(common.Pubkey)
}
return header
}

View file

@ -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(forksByTime)

View file

@ -223,6 +223,10 @@ func getGenesisState(db ethdb.Database, blockhash common.Hash) (alloc types.Gene
genesis = DefaultHoleskyGenesisBlock()
case params.HoodiGenesisHash:
genesis = DefaultHoodiGenesisBlock()
case params.BerachainGenesisHash:
genesis = DefaultBerachainGenesisBlock()
case params.BepoliaGenesisHash:
genesis = DefaultBepoliaGenesisBlock()
}
if genesis != nil {
return genesis.Alloc, nil
@ -303,8 +307,8 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
ghash := rawdb.ReadCanonicalHash(db, 0)
if (ghash == common.Hash{}) {
if genesis == nil {
log.Info("Writing default main-net genesis block")
genesis = DefaultGenesisBlock()
log.Info("Writing default berachain mainnet genesis block")
genesis = DefaultBerachainGenesisBlock()
} else {
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
// genesis will be used as default and the initialization will always fail.
if genesis == nil {
log.Info("Writing default main-net genesis block")
genesis = DefaultGenesisBlock()
log.Info("Writing default berachain mainnet genesis block")
genesis = DefaultBerachainGenesisBlock()
} else {
log.Info("Writing custom genesis block")
}
@ -381,9 +385,11 @@ func SetupGenesisBlockWithOverride(db ethdb.Database, triedb *triedb.Database, g
return newCfg, ghash, compatErr, nil
}
// 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)
if newData, _ := json.Marshal(newCfg); !bytes.Equal(storedData, newData) {
log.Info("Writing new chain config")
rawdb.WriteChainConfig(db, ghash, newCfg)
}
return newCfg, ghash, nil, nil
@ -419,8 +425,8 @@ func LoadChainConfig(db ethdb.Database, genesis *Genesis) (cfg *params.ChainConf
return genesis.Config, ghash, nil
}
// There is no stored chain config and no new config provided,
// In this case the default chain config(mainnet) will be used
return params.MainnetChainConfig, params.MainnetGenesisHash, nil
// In this case the default chain config(berachain mainnet) will be used
return params.BerachainChainConfig, params.BerachainGenesisHash, nil
}
// 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
case ghash == params.HoodiGenesisHash:
return params.HoodiChainConfig
case ghash == params.BerachainGenesisHash:
return params.BerachainChainConfig
case ghash == params.BepoliaGenesisHash:
return params.BepoliaChainConfig
default:
return stored
}
@ -518,6 +528,12 @@ func (g *Genesis) toBlockWithRoot(root common.Hash) *types.Block {
if conf.IsPrague(num, g.Timestamp) {
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))
}
@ -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.
func DeveloperGenesisBlock(gasLimit uint64, faucet *common.Address) *Genesis {
// Override the default period to the user requested one

File diff suppressed because one or more lines are too long

View file

@ -72,8 +72,8 @@ func testSetupGenesis(t *testing.T, scheme string) {
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
return SetupGenesisBlock(db, triedb.NewDatabase(db, newDbConfig(scheme)), nil)
},
wantHash: params.MainnetGenesisHash,
wantConfig: params.MainnetChainConfig,
wantHash: params.BerachainGenesisHash,
wantConfig: params.BerachainChainConfig,
},
{
name: "mainnet block in DB, genesis == nil",
@ -84,6 +84,15 @@ func testSetupGenesis(t *testing.T, scheme string) {
wantHash: params.MainnetGenesisHash,
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",
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},
},
{
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",
fn: func(db ethdb.Database) (*params.ChainConfig, common.Hash, *params.ConfigCompatError, error) {
@ -188,6 +206,8 @@ func TestGenesisHashes(t *testing.T) {
{DefaultSepoliaGenesisBlock(), params.SepoliaGenesisHash},
{DefaultHoleskyGenesisBlock(), params.HoleskyGenesisHash},
{DefaultHoodiGenesisBlock(), params.HoodiGenesisHash},
{DefaultBerachainGenesisBlock(), params.BerachainGenesisHash},
{DefaultBepoliaGenesisBlock(), params.BepoliaGenesisHash},
} {
// Test via MustCommit
db := rawdb.NewMemoryDatabase()

View file

@ -413,6 +413,10 @@ func GenerateBadBlock(parent *types.Block, engine consensus.Engine, txs types.Tr
nBlobs += len(tx.BlobHashes())
}
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) {
excess := eip4844.CalcExcessBlobGas(config, parent.Header(), header.Time)
used := uint64(nBlobs * params.BlobTxBlobGasPerBlob)

View file

@ -166,6 +166,9 @@ type Message struct {
// When SkipFromEOACheck is true, the message sender is not checked to be an EOA.
SkipFromEOACheck bool
// Berachain:IsPoLTx is true if the message is a PoL tx.
IsPoLTx bool
}
// TransactionToMessage converts a transaction into a Message.
@ -185,6 +188,7 @@ func TransactionToMessage(tx *types.Transaction, s types.Signer, baseFee *big.In
SkipFromEOACheck: false,
BlobHashes: tx.BlobHashes(),
BlobGasFeeCap: tx.BlobGasFeeCap(),
IsPoLTx: tx.Type() == types.PoLTxType,
}
// If baseFee provided, set gasPrice to effectiveGasPrice.
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.
func ApplyMessage(evm *vm.EVM, msg *Message, gp *GasPool) (*ExecutionResult, error) {
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()
}
// 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.
//
// == The State Transitioning Model

View file

@ -327,6 +327,11 @@ func (p *TxPool) Add(txs []*types.Transaction, sync bool) []error {
// Mark this transaction belonging to no-subpool
splits[i] = -1
// Berachain: PoL txs are rejected.
if tx.Type() == types.PoLTxType {
continue
}
// Try to find a subpool that accepts the transaction
for j, subpool := range p.subpools {
if subpool.Filter(tx) {

View file

@ -106,6 +106,9 @@ type Header struct {
// RequestsHash was added by EIP-7685 and is ignored in legacy headers.
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
@ -329,6 +332,10 @@ func CopyHeader(h *Header) *Header {
cpy.RequestsHash = new(common.Hash)
*cpy.RequestsHash = *h.RequestsHash
}
if h.ParentProposerPubkey != nil {
cpy.ParentProposerPubkey = new(common.Pubkey)
*cpy.ParentProposerPubkey = *h.ParentProposerPubkey
}
return &cpy
}
@ -408,8 +415,9 @@ func (b *Block) BaseFee() *big.Int {
return new(big.Int).Set(b.header.BaseFee)
}
func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot }
func (b *Block) RequestsHash() *common.Hash { return b.header.RequestsHash }
func (b *Block) BeaconRoot() *common.Hash { return b.header.ParentBeaconRoot }
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 {
var excessBlobGas *uint64

View file

@ -16,28 +16,29 @@ var _ = (*headerMarshaling)(nil)
// MarshalJSON marshals as JSON.
func (h Header) MarshalJSON() ([]byte, error) {
type Header struct {
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
Hash common.Hash `json:"hash"`
ParentHash common.Hash `json:"parentHash" gencodec:"required"`
UncleHash common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase common.Address `json:"miner"`
Root common.Hash `json:"stateRoot" gencodec:"required"`
TxHash common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest common.Hash `json:"mixHash"`
Nonce BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
Hash common.Hash `json:"hash"`
}
var enc Header
enc.ParentHash = h.ParentHash
@ -61,6 +62,7 @@ func (h Header) MarshalJSON() ([]byte, error) {
enc.ExcessBlobGas = (*hexutil.Uint64)(h.ExcessBlobGas)
enc.ParentBeaconRoot = h.ParentBeaconRoot
enc.RequestsHash = h.RequestsHash
enc.ParentProposerPubkey = h.ParentProposerPubkey
enc.Hash = h.Hash()
return json.Marshal(&enc)
}
@ -68,27 +70,28 @@ func (h Header) MarshalJSON() ([]byte, error) {
// UnmarshalJSON unmarshals from JSON.
func (h *Header) UnmarshalJSON(input []byte) error {
type Header struct {
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase *common.Address `json:"miner"`
Root *common.Hash `json:"stateRoot" gencodec:"required"`
TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash"`
Nonce *BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
ParentHash *common.Hash `json:"parentHash" gencodec:"required"`
UncleHash *common.Hash `json:"sha3Uncles" gencodec:"required"`
Coinbase *common.Address `json:"miner"`
Root *common.Hash `json:"stateRoot" gencodec:"required"`
TxHash *common.Hash `json:"transactionsRoot" gencodec:"required"`
ReceiptHash *common.Hash `json:"receiptsRoot" gencodec:"required"`
Bloom *Bloom `json:"logsBloom" gencodec:"required"`
Difficulty *hexutil.Big `json:"difficulty" gencodec:"required"`
Number *hexutil.Big `json:"number" gencodec:"required"`
GasLimit *hexutil.Uint64 `json:"gasLimit" gencodec:"required"`
GasUsed *hexutil.Uint64 `json:"gasUsed" gencodec:"required"`
Time *hexutil.Uint64 `json:"timestamp" gencodec:"required"`
Extra *hexutil.Bytes `json:"extraData" gencodec:"required"`
MixDigest *common.Hash `json:"mixHash"`
Nonce *BlockNonce `json:"nonce"`
BaseFee *hexutil.Big `json:"baseFeePerGas" rlp:"optional"`
WithdrawalsHash *common.Hash `json:"withdrawalsRoot" rlp:"optional"`
BlobGasUsed *hexutil.Uint64 `json:"blobGasUsed" rlp:"optional"`
ExcessBlobGas *hexutil.Uint64 `json:"excessBlobGas" rlp:"optional"`
ParentBeaconRoot *common.Hash `json:"parentBeaconBlockRoot" rlp:"optional"`
RequestsHash *common.Hash `json:"requestsHash" rlp:"optional"`
ParentProposerPubkey *common.Pubkey `json:"parentProposerPubkey" rlp:"optional"`
}
var dec Header
if err := json.Unmarshal(input, &dec); err != nil {
@ -169,5 +172,8 @@ func (h *Header) UnmarshalJSON(input []byte) error {
if dec.RequestsHash != nil {
h.RequestsHash = dec.RequestsHash
}
if dec.ParentProposerPubkey != nil {
h.ParentProposerPubkey = dec.ParentProposerPubkey
}
return nil
}

View file

@ -43,7 +43,8 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
_tmp4 := obj.ExcessBlobGas != nil
_tmp5 := obj.ParentBeaconRoot != 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 {
w.Write(rlp.EmptyString)
} else {
@ -53,41 +54,48 @@ func (obj *Header) EncodeRLP(_w io.Writer) error {
w.WriteBigInt(obj.BaseFee)
}
}
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 {
if _tmp2 || _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if obj.WithdrawalsHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.WithdrawalsHash[:])
}
}
if _tmp3 || _tmp4 || _tmp5 || _tmp6 {
if _tmp3 || _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if obj.BlobGasUsed == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.BlobGasUsed))
}
}
if _tmp4 || _tmp5 || _tmp6 {
if _tmp4 || _tmp5 || _tmp6 || _tmp7 {
if obj.ExcessBlobGas == nil {
w.Write([]byte{0x80})
} else {
w.WriteUint64((*obj.ExcessBlobGas))
}
}
if _tmp5 || _tmp6 {
if _tmp5 || _tmp6 || _tmp7 {
if obj.ParentBeaconRoot == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.ParentBeaconRoot[:])
}
}
if _tmp6 {
if _tmp6 || _tmp7 {
if obj.RequestsHash == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.RequestsHash[:])
}
}
if _tmp7 {
if obj.ParentProposerPubkey == nil {
w.Write([]byte{0x80})
} else {
w.WriteBytes(obj.ParentProposerPubkey[:])
}
}
w.ListEnd(_tmp0)
return w.Flush()
}

View file

@ -205,7 +205,7 @@ func (r *Receipt) decodeTyped(b []byte) error {
return errShortTypedReceipt
}
switch b[0] {
case DynamicFeeTxType, AccessListTxType, BlobTxType, SetCodeTxType:
case DynamicFeeTxType, AccessListTxType, BlobTxType, SetCodeTxType, PoLTxType:
var data receiptRLP
err := rlp.DecodeBytes(b[1:], &data)
if err != nil {
@ -368,7 +368,7 @@ func (rs Receipts) EncodeIndex(i int, w *bytes.Buffer) {
}
w.WriteByte(r.Type)
switch r.Type {
case AccessListTxType, DynamicFeeTxType, BlobTxType, SetCodeTxType:
case AccessListTxType, DynamicFeeTxType, BlobTxType, SetCodeTxType, PoLTxType:
rlp.Encode(w, data)
default:
// For unsupported types, write nothing. Since this is for

View file

@ -51,6 +51,9 @@ const (
DynamicFeeTxType = 0x02
BlobTxType = 0x03
SetCodeTxType = 0x04
// Berachain specific.
PoLTxType = 0x7E
)
// Transaction is an Ethereum transaction.
@ -213,6 +216,8 @@ func (tx *Transaction) decodeTyped(b []byte) (TxData, error) {
inner = new(BlobTx)
case SetCodeTxType:
inner = new(SetCodeTx)
case PoLTxType:
inner = new(PoLTx)
default:
return nil, ErrTxTypeNotSupported
}

Some files were not shown because too many files have changed in this diff Show more