Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
c4cd3f6
cmd/jsutils: adjust nodereal builders (#3447)
allformless Nov 13, 2025
03f168d
cmd/utils: define OverrideOsaka (#3446)
allformless Nov 17, 2025
ac08602
consensus/parlia: filter by source number when fetching votes (#3449)
allformless Nov 17, 2025
8a3d205
TxPool: change lifetime back to 3 hours (#3448)
zzzckck Nov 19, 2025
31dcdb8
cmd/geth: stop supporting multidatabase flag (#3457)
allformless Nov 20, 2025
9752050
build(deps): bump golang.org/x/crypto from 0.36.0 to 0.45.0 (#3456)
dependabot[bot] Nov 20, 2025
d550840
params: define MendelTime (#3458)
allformless Nov 21, 2025
e9f5535
eth: support fetch commit id info from extra data (#3454)
flywukong Nov 25, 2025
554f7e8
eth: improve prefetch by using cached reader (#3445)
flywukong Nov 25, 2025
b135fd9
eth: fix stuck when starting up a new network (#3460)
allformless Nov 26, 2025
a35c6d2
feat: transactionReceipts auto-unsubscribe implementation (#3459)
zlacfzy Nov 26, 2025
57e3e97
cmd/geth: config staticnodes for fullnode when init-network (#3462)
allformless Nov 26, 2025
032ccc7
refactor: replace context.WithCancel with t.Context (#3285)
hongmengning Nov 28, 2025
d3157ef
refactor: use slices.Contains to simplify code (#3245)
stellrust Nov 28, 2025
313c220
refactor: replace Split in loops with more efficient SplitSeq (#3262)
pinglanlu Nov 28, 2025
713eb44
refactor: drop legacy // +build comment (#3464)
rifeplight Nov 28, 2025
2a26745
config: update BSC Mainnet hardfork time: Fermi (#3466)
allformless Nov 28, 2025
23324ff
metric: add metric for vote count (#3468)
zlacfzy Dec 1, 2025
5e1ded9
.github/workflows: replace BLS for Windows (#3467)
allformless Dec 1, 2025
6d3c89e
release: prepare for release v1.6.4 (#3470)
allformless Dec 2, 2025
e003767
fix: fix the flag docment (#3472)
flywukong Dec 2, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .github/workflows/pre-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,11 @@ jobs:
GIT_COMMIT_DATE=$(git log -n1 --pretty='format:%cd' --date=format:'%Y%m%d')
GOOS=linux GOARCH=amd64 CGO_ENABLED=1 CC=$(pwd)/x86_64-linux-musl-cross/bin/x86_64-linux-musl-gcc go build -ldflags "-X main.gitCommit=$GIT_COMMIT -X main.gitDate=$GIT_COMMIT_DATE -extldflags=-static" -o ./build/bin/geth -a ./cmd/geth

- name: Temporary replace BLS for Windows
if: matrix.os == 'windows-latest'
shell: cmd
run: go mod edit -replace=github.com/herumi/bls-eth-go-binary=github.com/herumi/bls-eth-go-binary@v0.0.0-20210917013441-d37c07cfda4e && go mod tidy

- name: Build Binary for ${{matrix.os}}
if: matrix.os != 'ubuntu-latest'
run: |
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@ jobs:
GIT_COMMIT_DATE=$(git log -n1 --pretty='format:%cd' --date=format:'%Y%m%d')
GOOS=linux GOARCH=amd64 CGO_ENABLED=1 CC=$(pwd)/x86_64-linux-musl-cross/bin/x86_64-linux-musl-gcc go build -ldflags "-X main.gitCommit=$GIT_COMMIT -X main.gitDate=$GIT_COMMIT_DATE -extldflags=-static" -o ./build/bin/geth -a ./cmd/geth

# ==============================
- name: Temporary replace BLS for Windows
if: matrix.os == 'windows-latest'
shell: cmd
run: go mod edit -replace=github.com/herumi/bls-eth-go-binary=github.com/herumi/bls-eth-go-binary@v0.0.0-20210917013441-d37c07cfda4e && go mod tidy

- name: Build Binary for ${{matrix.os}}
if: matrix.os != 'ubuntu-latest'
run: |
Expand Down
15 changes: 15 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,19 @@
# Changelog
## v1.6.4
### FEATURE
[\#3466](https://github.com/bnb-chain/bsc/pull/3466) config: update BSC Mainnet hardfork time: Fermi
[\#3454](https://github.com/bnb-chain/bsc/pull/3454) eth: support fetch commit id info from extra data

### BUGFIX
[\#3448](https://github.com/bnb-chain/bsc/pull/3448) TxPool: change lifetime back to 3 hours
[\#3457](https://github.com/bnb-chain/bsc/pull/3457) cmd/geth: stop supporting multidatabase flag
[\#3467](https://github.com/bnb-chain/bsc/pull/3467) go.mod: downgrade bls-eth-go-binary to run on windows

### IMPROVEMENT
[\#3445](https://github.com/bnb-chain/bsc/pull/3445) eth: improve prefetch by using cached reader
[\#3459](https://github.com/bnb-chain/bsc/pull/3459) feat: transactionReceipts auto-unsubscribe implementation
[\#3468](https://github.com/bnb-chain/bsc/pull/3468) metric: add metric for vote count

## v1.6.3
### FEATURE
NA
Expand Down
1 change: 0 additions & 1 deletion accounts/keystore/watch.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

//go:build (darwin && !ios && cgo) || freebsd || (linux && !arm64) || netbsd || solaris
// +build darwin,!ios,cgo freebsd linux,!arm64 netbsd solaris

package keystore

Expand Down
1 change: 0 additions & 1 deletion accounts/keystore/watch_fallback.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

//go:build (darwin && !cgo) || ios || (linux && arm64) || windows || (!darwin && !freebsd && !linux && !netbsd && !solaris)
// +build darwin,!cgo ios linux,arm64 windows !darwin,!freebsd,!linux,!netbsd,!solaris

// This is the fallback implementation of directory watching.
// It is used on unsupported platforms.
Expand Down
31 changes: 21 additions & 10 deletions cmd/geth/chaincmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,8 +71,10 @@ var (
utils.OverrideLorentz,
utils.OverrideMaxwell,
utils.OverrideFermi,
utils.OverrideOsaka,
utils.OverrideMendel,
utils.OverrideVerkle,
utils.MultiDataBaseFlag,
// utils.MultiDataBaseFlag,
}, utils.DatabaseFlags),
Description: `
The init command initializes a new genesis block and definition for the network.
Expand Down Expand Up @@ -344,6 +346,14 @@ func initGenesis(ctx *cli.Context) error {
v := ctx.Uint64(utils.OverrideFermi.Name)
overrides.OverrideFermi = &v
}
if ctx.IsSet(utils.OverrideOsaka.Name) {
v := ctx.Uint64(utils.OverrideOsaka.Name)
overrides.OverrideOsaka = &v
}
if ctx.IsSet(utils.OverrideMendel.Name) {
v := ctx.Uint64(utils.OverrideMendel.Name)
overrides.OverrideMendel = &v
}
if ctx.IsSet(utils.OverrideVerkle.Name) {
v := ctx.Uint64(utils.OverrideVerkle.Name)
overrides.OverrideVerkle = &v
Expand Down Expand Up @@ -446,7 +456,7 @@ func createPorts(ipStr string, port int, size int) []int {
}

// Create config for node i in the cluster
func createNodeConfig(baseConfig gethConfig, ip string, port int, enodes []*enode.Node, index int, staticConnect bool) gethConfig {
func createNodeConfig(baseConfig gethConfig, prefix string, ip string, port int, enodes []*enode.Node, index int) gethConfig {
baseConfig.Node.HTTPHost = ip
baseConfig.Node.P2P.ListenAddr = fmt.Sprintf(":%d", port)
connectEnodes := make([]*enode.Node, 0, len(enodes)-1)
Expand All @@ -457,9 +467,10 @@ func createNodeConfig(baseConfig gethConfig, ip string, port int, enodes []*enod
connectEnodes = append(connectEnodes, enodes[j])
}
// Set the P2P connections between this node and the other nodes
if staticConnect {
baseConfig.Node.P2P.StaticNodes = connectEnodes
} else {
baseConfig.Node.P2P.StaticNodes = connectEnodes
if prefix == "fullnode" {
// Fullnodes may reside in different regions than the `enodes`.
// StaticNodes cannot connect to them directly, but can still discover them.
baseConfig.Node.P2P.BootstrapNodes = connectEnodes
}
return baseConfig
Expand Down Expand Up @@ -534,7 +545,7 @@ func initNetwork(ctx *cli.Context) error {
connectOneExtraEnodes = true
}

configs, enodes, accounts, err := createConfigs(config, initDir, "node", ips, ports, sentryEnodes, connectOneExtraEnodes, true)
configs, enodes, accounts, err := createConfigs(config, initDir, "node", ips, ports, sentryEnodes, connectOneExtraEnodes)
if err != nil {
utils.Fatalf("Failed to create node configs: %v", err)
}
Expand Down Expand Up @@ -615,7 +626,7 @@ func createSentryNodeConfigs(ctx *cli.Context, baseConfig gethConfig, initDir st
if err != nil {
utils.Fatalf("Failed to parse ports: %v", err)
}
configs, enodes, _, err := createConfigs(baseConfig, initDir, "sentry", ips, ports, nil, false, true)
configs, enodes, _, err := createConfigs(baseConfig, initDir, "sentry", ips, ports, nil, false)
if err != nil {
utils.Fatalf("Failed to create config: %v", err)
}
Expand All @@ -638,7 +649,7 @@ func createAndSaveFullNodeConfigs(ctx *cli.Context, inGenesisFile *os.File, base
utils.Fatalf("Failed to parse ports: %v", err)
}

configs, enodes, _, err := createConfigs(baseConfig, initDir, "fullnode", ips, ports, extraEnodes, false, false)
configs, enodes, _, err := createConfigs(baseConfig, initDir, "fullnode", ips, ports, extraEnodes, false)
if err != nil {
utils.Fatalf("Failed to create config: %v", err)
}
Expand All @@ -653,7 +664,7 @@ func createAndSaveFullNodeConfigs(ctx *cli.Context, inGenesisFile *os.File, base
return configs, enodes, nil
}

func createConfigs(base gethConfig, initDir string, prefix string, ips []string, ports []int, extraEnodes []*enode.Node, connectOneExtraEnodes bool, staticConnect bool) ([]gethConfig, []*enode.Node, [][]common.Address, error) {
func createConfigs(base gethConfig, initDir string, prefix string, ips []string, ports []int, extraEnodes []*enode.Node, connectOneExtraEnodes bool) ([]gethConfig, []*enode.Node, [][]common.Address, error) {
if len(ips) != len(ports) {
return nil, nil, nil, errors.New("mismatch of size and length of ports")
}
Expand Down Expand Up @@ -684,7 +695,7 @@ func createConfigs(base gethConfig, initDir string, prefix string, ips []string,
allEnodes = []*enode.Node{enodes[i], extraEnodes[i]}
index = 0
}
configs[i] = createNodeConfig(base, ips[i], ports[i], allEnodes, index, staticConnect)
configs[i] = createNodeConfig(base, prefix, ips[i], ports[i], allEnodes, index)
}
return configs, enodes, accounts, nil
}
Expand Down
8 changes: 8 additions & 0 deletions cmd/geth/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,14 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
v := ctx.Uint64(utils.OverrideFermi.Name)
cfg.Eth.OverrideFermi = &v
}
if ctx.IsSet(utils.OverrideOsaka.Name) {
v := ctx.Uint64(utils.OverrideOsaka.Name)
cfg.Eth.OverrideOsaka = &v
}
if ctx.IsSet(utils.OverrideMendel.Name) {
v := ctx.Uint64(utils.OverrideMendel.Name)
cfg.Eth.OverrideMendel = &v
}
if ctx.IsSet(utils.OverrideVerkle.Name) {
v := ctx.Uint64(utils.OverrideVerkle.Name)
cfg.Eth.OverrideVerkle = &v
Expand Down
4 changes: 3 additions & 1 deletion cmd/geth/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ var (
utils.OverrideLorentz,
utils.OverrideMaxwell,
utils.OverrideFermi,
utils.OverrideOsaka,
utils.OverrideMendel,
utils.OverrideVerkle,
utils.OverrideFullImmutabilityThreshold,
utils.OverrideMinBlocksForBlobRequests,
Expand Down Expand Up @@ -128,7 +130,7 @@ var (
utils.CacheSnapshotFlag,
// utils.CacheNoPrefetchFlag,
utils.CachePreimagesFlag,
utils.MultiDataBaseFlag,
// utils.MultiDataBaseFlag,
utils.PruneAncientDataFlag, // deprecated
utils.CacheLogSizeFlag,
utils.FDLimitFlag,
Expand Down
57 changes: 50 additions & 7 deletions cmd/jsutils/getchainstatus.js
Original file line number Diff line number Diff line change
Expand Up @@ -266,9 +266,9 @@ const builderMap = new Map([

// Chapel
["0x627fE6AFA2E84e461CB7AE7C2c46e8adf9a954a2", "txboost"],
["0x5EC60f73f938e36400ec3CC3Ff4d7a7703F7c005", "nodereal ap"],
["0xa5559F1761e6dCa79Ac0c7A301CCDcC71D378fee", "nodereal ap"],
["0x6C98EB21139F6E12db5b78a4AeD4d8eBA147FB7b", "nodereal eu"],
["0x5b67a234592331e85fC57Bb148769c1d2fF62520", "nodereal us"],
["0x4E8cbf5912717B212db5b450ae7737455A5cc0aF", "nodereal us"],
["0x4827b423D03a349b7519Dda537e9A28d31ecBB48", "club48 ap"],
["0x48B2665E5E9a343409199D70F7495c8aB660BB48", "club48 eu"],
["0x48B4bBEbF0655557A461e91B8905b85864B8BB48", "club48 us"],
Expand Down Expand Up @@ -315,10 +315,53 @@ async function getBinaryVersion() {
let turnLength = program.turnLength;
for (let i = 0; i < program.num; i++) {
let blockData = await provider.getBlock(blockNum - i * turnLength);
// 1.get Geth client version
let major = ethers.toNumber(ethers.dataSlice(blockData.extraData, 2, 3));
let minor = ethers.toNumber(ethers.dataSlice(blockData.extraData, 3, 4));
let patch = ethers.toNumber(ethers.dataSlice(blockData.extraData, 4, 5));

let major = 0, minor = 0, patch = 0;
let commitID = "";

try {
major = ethers.toNumber(ethers.dataSlice(blockData.extraData, 2, 3));
minor = ethers.toNumber(ethers.dataSlice(blockData.extraData, 3, 4));
patch = ethers.toNumber(ethers.dataSlice(blockData.extraData, 4, 5));

// Check version: >= 1.6.4 uses new format with commitID
const isNewFormat = major > 1 || (major === 1 && minor > 6) || (major === 1 && minor === 6 && patch >= 4);

if (isNewFormat) {
const extraVanity = 28;
let vanityBytes = ethers.getBytes(ethers.dataSlice(blockData.extraData, 0, extraVanity));

let rlpLength = vanityBytes.length;
if (vanityBytes[0] >= 0xC0 && vanityBytes[0] <= 0xF7) {
rlpLength = (vanityBytes[0] - 0xC0) + 1;
}

const rlpData = ethers.dataSlice(blockData.extraData, 0, rlpLength);
const decoded = ethers.decodeRlp(rlpData);

if (Array.isArray(decoded) && decoded.length >= 2) {
const secondElemHex = decoded[1];
let secondElemStr = "";
try {
secondElemStr = ethers.toUtf8String(secondElemHex);
} catch (e) {
secondElemStr = secondElemHex;
}

if (secondElemStr.length > 0 && secondElemStr !== "geth") {
commitID = secondElemStr.startsWith("0x") ? secondElemStr.substring(2) : secondElemStr;
}
}
}
} catch (e) {
console.log("Parsing failed:", e.message);
}

// Format version string
let versionStr = major + "." + minor + "." + patch;
if (commitID && commitID.length > 0) {
versionStr = versionStr + "-" + commitID;
}

// 2.get minimum txGasPrice based on the last non-zero-gasprice transaction
let lastGasPrice = 0;
Expand All @@ -332,7 +375,7 @@ async function getBinaryVersion() {
break;
}
var moniker = await getValidatorMoniker(blockData.miner, blockNum);
console.log(blockNum - i * turnLength, blockData.miner, "version =", major + "." + minor + "." + patch, " MinGasPrice = " + lastGasPrice, moniker);
console.log(blockNum - i * turnLength, blockData.miner, "version =", versionStr, " MinGasPrice = " + lastGasPrice, moniker);
}
}

Expand Down
1 change: 0 additions & 1 deletion cmd/utils/diskusage.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.

//go:build !windows && !openbsd && !wasip1
// +build !windows,!openbsd,!wasip1

package utils

Expand Down
1 change: 0 additions & 1 deletion cmd/utils/diskusage_openbsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.

//go:build openbsd
// +build openbsd

package utils

Expand Down
14 changes: 12 additions & 2 deletions cmd/utils/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,6 +315,16 @@ var (
Usage: "Manually specify the Fermi fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
OverrideOsaka = &cli.Uint64Flag{
Name: "override.osaka",
Usage: "Manually specify the Osaka fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
OverrideMendel = &cli.Uint64Flag{
Name: "override.mendel",
Usage: "Manually specify the Mendel fork timestamp, overriding the bundled setting",
Category: flags.EthCategory,
}
OverrideVerkle = &cli.Uint64Flag{
Name: "override.verkle",
Usage: "Manually specify the Verkle fork timestamp, overriding the bundled setting",
Expand Down Expand Up @@ -358,7 +368,7 @@ var (
}
GCModeFlag = &cli.StringFlag{
Name: "gcmode",
Usage: `Blockchain garbage collection mode, only relevant in state.scheme=hash ("full", "archive")`,
Usage: `Blockchain garbage collection mode ("full", "archive")`,
Value: "full",
Category: flags.StateCategory,
}
Expand All @@ -381,7 +391,7 @@ var (
}
StateHistoryFlag = &cli.Uint64Flag{
Name: "history.state",
Usage: "Number of recent blocks to retain state history for, only relevant in state.scheme=path (default = 90,000 blocks, 0 = entire chain)",
Usage: "Number of recent blocks to retain state history for, only relevant in state.scheme=path (default = 600,000 blocks, 0 = entire chain)",
Value: ethconfig.Defaults.StateHistory,
Category: flags.StateCategory,
}
Expand Down
1 change: 0 additions & 1 deletion common/fdlimit/fdlimit_bsd.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

//go:build freebsd || dragonfly
// +build freebsd dragonfly

package fdlimit

Expand Down
1 change: 0 additions & 1 deletion common/fdlimit/fdlimit_unix.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.

//go:build linux || netbsd || openbsd || solaris
// +build linux netbsd openbsd solaris

package fdlimit

Expand Down
2 changes: 1 addition & 1 deletion consensus/consensus.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ type ChainHeaderReader interface {
}

type VotePool interface {
FetchVotesByBlockHash(blockHash common.Hash) []*types.VoteEnvelope
FetchVotesByBlockHash(targetBlockHash common.Hash, sourceBlockNum uint64) []*types.VoteEnvelope
}

// ChainReader defines a small collection of methods needed to access the local
Expand Down
2 changes: 1 addition & 1 deletion consensus/misc/eip4844/eip4844.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ func CalcExcessBlobGas(config *params.ChainConfig, parent *types.Header, headTim
func CalcBlobFee(config *params.ChainConfig, header *types.Header) *big.Int {
var frac uint64
switch config.LatestFork(header.Time) {
case forks.Osaka:
case forks.Mendel, forks.Osaka:
frac = config.BlobScheduleConfig.Osaka.UpdateFraction
case forks.Fermi, forks.Maxwell, forks.Lorentz, forks.Prague:
frac = config.BlobScheduleConfig.Prague.UpdateFraction
Expand Down
3 changes: 2 additions & 1 deletion consensus/parlia/parlia.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ var (
validVotesfromSelfCounter = metrics.NewRegisteredCounter("parlia/VerifyVote/self", nil)
doubleSignCounter = metrics.NewRegisteredCounter("parlia/doublesign", nil)
intentionalDelayMiningCounter = metrics.NewRegisteredCounter("parlia/intentionalDelayMining", nil)
attestationVoteCountGauge = metrics.NewRegisteredGauge("parlia/attestation/voteCount", nil)

systemContracts = map[common.Address]bool{
common.HexToAddress(systemcontracts.ValidatorContract): true,
Expand Down Expand Up @@ -1072,7 +1073,7 @@ func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, head
if err != nil {
return err
}
votes = p.VotePool.FetchVotesByBlockHash(targetHeader.Hash())
votes = p.VotePool.FetchVotesByBlockHash(targetHeader.Hash(), justifiedBlockNumber)
quorum := cmath.CeilDiv(len(snap.Validators)*2, 3)
if len(votes) >= quorum {
targetHeaderParentSnap = snap
Expand Down
5 changes: 5 additions & 0 deletions consensus/parlia/snapshot.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/internal/ethapi"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/willf/bitset"
)

// Snapshot is the state of the validatorSet at a given point.
Expand Down Expand Up @@ -219,6 +220,10 @@ func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.C
}
}

// Update vote count metric after validation passed
voteCount := bitset.From([]uint64{uint64(attestation.VoteAddressSet)}).Count()
attestationVoteCountGauge.Update(int64(voteCount))

// Update attestation
// Two scenarios for s.Attestation being nil:
// 1) The first attestation is assembled.
Expand Down
Loading