diff --git a/.github/workflows/pre-release.yml b/.github/workflows/pre-release.yml
index aa10ee9ec1..71d80a1830 100644
--- a/.github/workflows/pre-release.yml
+++ b/.github/workflows/pre-release.yml
@@ -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: |
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 29b5f836c6..1b20a3fb81 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -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: |
diff --git a/accounts/keystore/watch.go b/accounts/keystore/watch.go
index 1bef321cd1..b623e7d7bb 100644
--- a/accounts/keystore/watch.go
+++ b/accounts/keystore/watch.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build (darwin && !ios && cgo) || freebsd || (linux && !arm64) || netbsd || solaris
-// +build darwin,!ios,cgo freebsd linux,!arm64 netbsd solaris
package keystore
diff --git a/accounts/keystore/watch_fallback.go b/accounts/keystore/watch_fallback.go
index e3c133b3f6..17513ae3bc 100644
--- a/accounts/keystore/watch_fallback.go
+++ b/accounts/keystore/watch_fallback.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//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.
diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index 658f5c27a9..12fdfdb062 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -72,6 +72,7 @@ var (
utils.OverrideMaxwell,
utils.OverrideFermi,
utils.OverrideOsaka,
+ utils.OverrideMendel,
utils.OverrideVerkle,
// utils.MultiDataBaseFlag,
}, utils.DatabaseFlags),
@@ -349,6 +350,10 @@ func initGenesis(ctx *cli.Context) error {
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
@@ -451,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)
@@ -462,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
@@ -539,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)
}
@@ -620,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)
}
@@ -643,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)
}
@@ -658,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")
}
@@ -689,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
}
diff --git a/cmd/geth/config.go b/cmd/geth/config.go
index 16786ae249..84e107667d 100644
--- a/cmd/geth/config.go
+++ b/cmd/geth/config.go
@@ -274,6 +274,10 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) {
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
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 4e164ee78b..e4a71282d5 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -77,6 +77,7 @@ var (
utils.OverrideMaxwell,
utils.OverrideFermi,
utils.OverrideOsaka,
+ utils.OverrideMendel,
utils.OverrideVerkle,
utils.OverrideFullImmutabilityThreshold,
utils.OverrideMinBlocksForBlobRequests,
diff --git a/cmd/jsutils/getchainstatus.js b/cmd/jsutils/getchainstatus.js
index 939b09c183..ee6d050283 100644
--- a/cmd/jsutils/getchainstatus.js
+++ b/cmd/jsutils/getchainstatus.js
@@ -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;
@@ -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);
}
}
diff --git a/cmd/utils/diskusage.go b/cmd/utils/diskusage.go
index 8174236ab7..ec9b2e424a 100644
--- a/cmd/utils/diskusage.go
+++ b/cmd/utils/diskusage.go
@@ -15,7 +15,6 @@
// along with go-ethereum. If not, see .
//go:build !windows && !openbsd && !wasip1
-// +build !windows,!openbsd,!wasip1
package utils
diff --git a/cmd/utils/diskusage_openbsd.go b/cmd/utils/diskusage_openbsd.go
index 0d71d84a67..fce27070b4 100644
--- a/cmd/utils/diskusage_openbsd.go
+++ b/cmd/utils/diskusage_openbsd.go
@@ -15,7 +15,6 @@
// along with go-ethereum. If not, see .
//go:build openbsd
-// +build openbsd
package utils
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 51a17de863..f27bca90ab 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -320,6 +320,11 @@ var (
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",
diff --git a/common/fdlimit/fdlimit_bsd.go b/common/fdlimit/fdlimit_bsd.go
index a3a6902c09..ede9955168 100644
--- a/common/fdlimit/fdlimit_bsd.go
+++ b/common/fdlimit/fdlimit_bsd.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build freebsd || dragonfly
-// +build freebsd dragonfly
package fdlimit
diff --git a/common/fdlimit/fdlimit_unix.go b/common/fdlimit/fdlimit_unix.go
index a1f388ebb7..704ca27f26 100644
--- a/common/fdlimit/fdlimit_unix.go
+++ b/common/fdlimit/fdlimit_unix.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build linux || netbsd || openbsd || solaris
-// +build linux netbsd openbsd solaris
package fdlimit
diff --git a/consensus/misc/eip4844/eip4844.go b/consensus/misc/eip4844/eip4844.go
index 15e427deca..985893cf9e 100644
--- a/consensus/misc/eip4844/eip4844.go
+++ b/consensus/misc/eip4844/eip4844.go
@@ -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
diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go
index d5fe807763..2f62b9a97d 100644
--- a/consensus/parlia/parlia.go
+++ b/consensus/parlia/parlia.go
@@ -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,
@@ -1698,6 +1699,23 @@ func (p *Parlia) Delay(chain consensus.ChainReader, header *types.Header, leftOv
return &delay
}
+// AssembleSignature assemble the signature for block header
+func (p *Parlia) AssembleSignature(block *types.Block) (*types.Block, error) {
+ header := block.Header()
+ // Don't hold the val fields for the entire sealing procedure
+ p.lock.RLock()
+ val, signFn := p.val, p.signFn
+ p.lock.RUnlock()
+ sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, ParliaRLP(header, p.chainConfig.ChainID))
+ if err != nil {
+ log.Error("Sign for the block header failed when sealing", "err", err)
+ return nil, err
+ }
+ copy(header.Extra[len(header.Extra)-extraSeal:], sig)
+ block = block.WithSeal(header)
+ return block, nil
+}
+
// Seal implements consensus.Engine, attempting to create a sealed block using
// the local signing credentials.
func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error {
diff --git a/consensus/parlia/snapshot.go b/consensus/parlia/snapshot.go
index ecabc62a56..047ddf4754 100644
--- a/consensus/parlia/snapshot.go
+++ b/consensus/parlia/snapshot.go
@@ -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.
@@ -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.
diff --git a/core/blockchain.go b/core/blockchain.go
index 5bc0ab3b4e..e1d958baec 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -1997,18 +1997,18 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types.
// WriteBlockAndSetHead writes the given block and all associated state to the database,
// and applies the block as the new chain head.
-func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, sealedBlockSender *event.TypeMux) (status WriteStatus, err error) {
+func (bc *BlockChain) WriteBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, sealedBlockSender *event.TypeMux, delayBroadcast bool) (status WriteStatus, err error) {
if !bc.chainmu.TryLock() {
return NonStatTy, errChainStopped
}
defer bc.chainmu.Unlock()
- return bc.writeBlockAndSetHead(block, receipts, logs, state, sealedBlockSender)
+ return bc.writeBlockAndSetHead(block, receipts, logs, state, sealedBlockSender, delayBroadcast)
}
// writeBlockAndSetHead is the internal implementation of WriteBlockAndSetHead.
// This function expects the chain mutex to be held.
-func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, sealedBlockSender *event.TypeMux) (status WriteStatus, err error) {
+func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types.Receipt, logs []*types.Log, state *state.StateDB, sealedBlockSender *event.TypeMux, delayBroadcast bool) (status WriteStatus, err error) {
currentBlock := bc.CurrentBlock()
reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock, block.Header())
if err != nil {
@@ -2017,7 +2017,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
if reorg {
bc.highestVerifiedBlock.Store(types.CopyHeader(block.Header()))
bc.highestVerifiedBlockFeed.Send(HighestVerifiedBlockEvent{Header: block.Header()})
- if sealedBlockSender != nil {
+ if sealedBlockSender != nil && !delayBroadcast {
// If the local DB is corrupted, writeBlockWithState may fail.
// It's fine — other nodes will persist the block.
//
@@ -2628,7 +2628,7 @@ func (bc *BlockChain) processBlock(parentRoot common.Hash, block *types.Block, s
// Don't set the head, only insert the block
err = bc.writeBlockWithState(block, res.Receipts, statedb)
} else {
- status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, nil)
+ status, err = bc.writeBlockAndSetHead(block, res.Receipts, res.Logs, statedb, nil, false)
}
if err != nil {
return nil, err
diff --git a/core/genesis.go b/core/genesis.go
index 2437089b2a..883db7d751 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -272,6 +272,7 @@ type ChainOverrides struct {
OverrideMaxwell *uint64
OverrideFermi *uint64
OverrideOsaka *uint64
+ OverrideMendel *uint64
OverrideVerkle *uint64
}
@@ -304,6 +305,9 @@ func (o *ChainOverrides) apply(cfg *params.ChainConfig) error {
if o.OverrideOsaka != nil {
cfg.OsakaTime = o.OverrideOsaka
}
+ if o.OverrideMendel != nil {
+ cfg.MendelTime = o.OverrideMendel
+ }
if o.OverrideVerkle != nil {
cfg.VerkleTime = o.OverrideVerkle
}
diff --git a/core/mkalloc.go b/core/mkalloc.go
index cc4955f038..f21e349e16 100644
--- a/core/mkalloc.go
+++ b/core/mkalloc.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build none
-// +build none
/*
The mkalloc tool creates the genesis allocation constants in genesis_alloc.go
diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go
index 4f71e33cb1..68fb444188 100644
--- a/core/state_prefetcher.go
+++ b/core/state_prefetcher.go
@@ -66,7 +66,7 @@ func (p *statePrefetcher) Prefetch(transactions types.Transactions, header *type
// Iterate over and process the individual transactions
for i, tx := range transactions {
- stateCpy := statedb.CopyDoPrefetch() // closure
+ stateCpy := statedb.CopyDoPrefetch()
workers.Go(func() error {
// If block precaching was interrupted, abort
if interrupt != nil && interrupt.Load() {
diff --git a/core/state_prefetcher_test.go b/core/state_prefetcher_test.go
index c40e9c0a07..9e04ec915f 100644
--- a/core/state_prefetcher_test.go
+++ b/core/state_prefetcher_test.go
@@ -26,8 +26,7 @@ import (
)
func TestPrefetchLeaking(t *testing.T) {
- ctx, cancel := context.WithCancel(context.Background())
- defer cancel()
+ ctx := t.Context()
var (
gendb = rawdb.NewMemoryDatabase()
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
diff --git a/core/types/block.go b/core/types/block.go
index 4f4e47d9e1..e4aa171c99 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -20,6 +20,7 @@ package types
import (
"crypto/sha256"
"encoding/binary"
+ "encoding/json"
"fmt"
"io"
"math/big"
@@ -785,6 +786,14 @@ func (b *Block) WithWitness(witness *ExecutionWitness) *Block {
}
}
+func (b *Block) DeepCopySidecars(sidecars BlobSidecars) {
+ b.sidecars = make(BlobSidecars, len(sidecars))
+ if len(sidecars) != 0 {
+ buffer, _ := json.Marshal(sidecars)
+ json.Unmarshal(buffer, &b.sidecars)
+ }
+}
+
// Hash returns the keccak256 hash of b's header.
// The hash is computed on the first call and cached thereafter.
func (b *Block) Hash() common.Hash {
diff --git a/core/vote/vote_manager.go b/core/vote/vote_manager.go
index ad83b4e51f..88344afcb6 100644
--- a/core/vote/vote_manager.go
+++ b/core/vote/vote_manager.go
@@ -35,6 +35,7 @@ var notContinuousJustified = metrics.NewRegisteredCounter("votesManager/notConti
// Backend wraps all methods required for voting.
type Backend interface {
IsMining() bool
+ VoteEnabled() bool
EventMux() *event.TypeMux
}
@@ -140,6 +141,11 @@ func (voteManager *VoteManager) loop() {
log.Debug("skip voting because mining is disabled, continue")
continue
}
+ if !voteManager.eth.VoteEnabled() {
+ log.Debug("skip voting because voting is disabled, continue")
+ continue
+ }
+
blockCountSinceMining++
if blockCountSinceMining <= blocksNumberSinceMining {
log.Debug("skip voting", "blockCountSinceMining", blockCountSinceMining, "blocksNumberSinceMining", blocksNumberSinceMining)
diff --git a/core/vote/vote_pool_test.go b/core/vote/vote_pool_test.go
index c6ee87501e..63815197e1 100644
--- a/core/vote/vote_pool_test.go
+++ b/core/vote/vote_pool_test.go
@@ -76,6 +76,7 @@ func newTestBackend() *testBackend {
return &testBackend{eventMux: new(event.TypeMux)}
}
func (b *testBackend) IsMining() bool { return true }
+func (b *testBackend) VoteEnabled() bool { return true }
func (b *testBackend) EventMux() *event.TypeMux { return b.eventMux }
func (mp *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, headers []*types.Header) (uint64, common.Hash, error) {
diff --git a/crypto/blake2b/blake2bAVX2_amd64.go b/crypto/blake2b/blake2bAVX2_amd64.go
index 3a85d0e73a..bfeee2be9e 100644
--- a/crypto/blake2b/blake2bAVX2_amd64.go
+++ b/crypto/blake2b/blake2bAVX2_amd64.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build go1.7 && amd64 && !gccgo && !appengine
-// +build go1.7,amd64,!gccgo,!appengine
package blake2b
diff --git a/crypto/blake2b/blake2b_amd64.go b/crypto/blake2b/blake2b_amd64.go
index a318b2b617..7f933ecb92 100644
--- a/crypto/blake2b/blake2b_amd64.go
+++ b/crypto/blake2b/blake2b_amd64.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build !go1.7 && amd64 && !gccgo && !appengine
-// +build !go1.7,amd64,!gccgo,!appengine
package blake2b
diff --git a/crypto/blake2b/blake2b_f_fuzz_test.go b/crypto/blake2b/blake2b_f_fuzz_test.go
index 1de9a62de9..1913ede34d 100644
--- a/crypto/blake2b/blake2b_f_fuzz_test.go
+++ b/crypto/blake2b/blake2b_f_fuzz_test.go
@@ -1,6 +1,5 @@
// Only enable fuzzer on platforms with AVX enabled
//go:build go1.7 && amd64 && !gccgo && !appengine
-// +build go1.7,amd64,!gccgo,!appengine
package blake2b
diff --git a/crypto/blake2b/blake2b_ref.go b/crypto/blake2b/blake2b_ref.go
index 095c71a648..682544100f 100644
--- a/crypto/blake2b/blake2b_ref.go
+++ b/crypto/blake2b/blake2b_ref.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build !amd64 || appengine || gccgo
-// +build !amd64 appengine gccgo
package blake2b
diff --git a/crypto/blake2b/register.go b/crypto/blake2b/register.go
index 9d8633963c..d9fcac3a4d 100644
--- a/crypto/blake2b/register.go
+++ b/crypto/blake2b/register.go
@@ -3,7 +3,6 @@
// license that can be found in the LICENSE file.
//go:build go1.9
-// +build go1.9
package blake2b
diff --git a/crypto/bn256/bn256_fast.go b/crypto/bn256/bn256_fast.go
index e3c9b60518..eda11b02a0 100644
--- a/crypto/bn256/bn256_fast.go
+++ b/crypto/bn256/bn256_fast.go
@@ -3,7 +3,6 @@
// in the LICENSE file.
//go:build amd64 || arm64
-// +build amd64 arm64
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
package bn256
diff --git a/crypto/bn256/bn256_slow.go b/crypto/bn256/bn256_slow.go
index 4c0c351e2d..1b021fd4ef 100644
--- a/crypto/bn256/bn256_slow.go
+++ b/crypto/bn256/bn256_slow.go
@@ -3,7 +3,6 @@
// in the LICENSE file.
//go:build !amd64 && !arm64
-// +build !amd64,!arm64
// Package bn256 implements the Optimal Ate pairing over a 256-bit Barreto-Naehrig curve.
package bn256
diff --git a/crypto/bn256/cloudflare/gfp_decl.go b/crypto/bn256/cloudflare/gfp_decl.go
index 1954d14a4a..129babd241 100644
--- a/crypto/bn256/cloudflare/gfp_decl.go
+++ b/crypto/bn256/cloudflare/gfp_decl.go
@@ -1,5 +1,4 @@
//go:build (amd64 && !generic) || (arm64 && !generic)
-// +build amd64,!generic arm64,!generic
package bn256
diff --git a/crypto/bn256/cloudflare/gfp_generic.go b/crypto/bn256/cloudflare/gfp_generic.go
index 7742dda4c9..944208c67b 100644
--- a/crypto/bn256/cloudflare/gfp_generic.go
+++ b/crypto/bn256/cloudflare/gfp_generic.go
@@ -1,5 +1,4 @@
//go:build (!amd64 && !arm64) || generic
-// +build !amd64,!arm64 generic
package bn256
diff --git a/crypto/secp256k1/dummy.go b/crypto/secp256k1/dummy.go
index 65a75080f6..3e3b6f2623 100644
--- a/crypto/secp256k1/dummy.go
+++ b/crypto/secp256k1/dummy.go
@@ -1,5 +1,4 @@
//go:build dummy
-// +build dummy
// This file is part of a workaround for `go mod vendor` which won't vendor
// C files if there's no Go file in the same directory.
diff --git a/crypto/secp256k1/scalar_mult_nocgo.go b/crypto/secp256k1/scalar_mult_nocgo.go
index feb13a8dfd..f26aecc068 100644
--- a/crypto/secp256k1/scalar_mult_nocgo.go
+++ b/crypto/secp256k1/scalar_mult_nocgo.go
@@ -3,7 +3,6 @@
// the LICENSE file.
//go:build gofuzz || !cgo
-// +build gofuzz !cgo
package secp256k1
diff --git a/crypto/secp256k1/secp256_test.go b/crypto/secp256k1/secp256_test.go
index 4827cc5b25..109872b1e9 100644
--- a/crypto/secp256k1/secp256_test.go
+++ b/crypto/secp256k1/secp256_test.go
@@ -3,7 +3,6 @@
// the LICENSE file.
//go:build !gofuzz && cgo
-// +build !gofuzz,cgo
package secp256k1
diff --git a/crypto/signature_cgo.go b/crypto/signature_cgo.go
index 18b78f4aac..8b0625a4e3 100644
--- a/crypto/signature_cgo.go
+++ b/crypto/signature_cgo.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build !nacl && !js && !wasip1 && cgo && !gofuzz && !tinygo
-// +build !nacl,!js,!wasip1,cgo,!gofuzz,!tinygo
package crypto
diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go
index d76127c258..dd8afdaece 100644
--- a/crypto/signature_nocgo.go
+++ b/crypto/signature_nocgo.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build nacl || js || wasip1 || !cgo || gofuzz || tinygo
-// +build nacl js wasip1 !cgo gofuzz tinygo
package crypto
diff --git a/crypto/signify/signify_fuzz.go b/crypto/signify/signify_fuzz.go
index 239a2134df..7e86da54a9 100644
--- a/crypto/signify/signify_fuzz.go
+++ b/crypto/signify/signify_fuzz.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build gofuzz
-// +build gofuzz
package signify
diff --git a/eth/api_miner.go b/eth/api_miner.go
index 64b3130dae..00fceaf170 100644
--- a/eth/api_miner.go
+++ b/eth/api_miner.go
@@ -20,6 +20,7 @@ import (
"math/big"
"time"
+ "github.com/ethereum/go-ethereum/miner/minerconfig"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/common"
@@ -117,3 +118,37 @@ func (api *MinerAPI) AddBuilder(builder common.Address, url string) error {
func (api *MinerAPI) RemoveBuilder(builder common.Address) error {
return api.e.APIBackend.RemoveBuilder(builder)
}
+
+func (api *MinerAPI) MBConfig() minerconfig.MBConfig {
+ return api.e.Miner().MBConfig()
+}
+
+func (api *MinerAPI) ResetMaliciousBehavior() minerconfig.MBConfig {
+ api.e.Miner().ResetMaliciousBehavior()
+ return api.e.Miner().MBConfig()
+}
+
+func (api *MinerAPI) SetDoubleSign(on bool) minerconfig.MBConfig {
+ api.e.Miner().SetDoubleSign(on)
+ return api.e.Miner().MBConfig()
+}
+
+func (api *MinerAPI) SetVoteDisable(on bool) minerconfig.MBConfig {
+ api.e.Miner().SetVoteDisable(on)
+ return api.e.Miner().MBConfig()
+}
+
+func (api *MinerAPI) SetSkipOffsetInturn(offset uint64) minerconfig.MBConfig {
+ api.e.Miner().SetSkipOffsetInturn(offset)
+ return api.e.Miner().MBConfig()
+}
+
+func (api *MinerAPI) SetBroadcastDelayBlocks(num uint64) minerconfig.MBConfig {
+ api.e.Miner().SetBroadcastDelayBlocks(num)
+ return api.e.Miner().MBConfig()
+}
+
+func (api *MinerAPI) SetLastBlockMiningTime(time uint64) minerconfig.MBConfig {
+ api.e.Miner().SetLastBlockMiningTime(time)
+ return api.e.Miner().MBConfig()
+}
diff --git a/eth/backend.go b/eth/backend.go
index a4f6f08586..b33cec06f7 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -28,11 +28,12 @@ import (
"sync"
"time"
+ "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
- "github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/parlia"
"github.com/ethereum/go-ethereum/core"
@@ -66,7 +67,6 @@ import (
"github.com/ethereum/go-ethereum/p2p"
"github.com/ethereum/go-ethereum/p2p/dnsdisc"
"github.com/ethereum/go-ethereum/p2p/enode"
- "github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/triedb/pathdb"
@@ -256,6 +256,10 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
chainConfig.OsakaTime = config.OverrideOsaka
overrides.OverrideOsaka = config.OverrideOsaka
}
+ if config.OverrideMendel != nil {
+ chainConfig.MendelTime = config.OverrideMendel
+ overrides.OverrideMendel = config.OverrideMendel
+ }
if config.OverrideVerkle != nil {
chainConfig.VerkleTime = config.OverrideVerkle
overrides.OverrideVerkle = config.OverrideVerkle
@@ -510,12 +514,24 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
func makeExtraData(extra []byte) []byte {
if len(extra) == 0 {
- // create default extradata
+ // For version >= 1.6.4, use compact format: [version(uint32), commitID, go_version, os]
+ commitID := ""
+ git, ok := version.VCS()
+ if ok && len(git.Commit) >= 8 {
+ commitID = git.Commit[:8]
+ }
+
+ osName := runtime.GOOS
+ if len(osName) > 3 {
+ osName = osName[:3]
+ }
+
+ versionWord := uint32(gethversion.Major<<16 | gethversion.Minor<<8 | gethversion.Patch)
extra, _ = rlp.EncodeToBytes([]interface{}{
- uint(gethversion.Major<<16 | gethversion.Minor<<8 | gethversion.Patch),
- "geth",
+ versionWord,
+ commitID,
runtime.Version(),
- runtime.GOOS,
+ osName,
})
}
if uint64(len(extra)) > params.MaximumExtraDataSize-params.ForkIDSize {
@@ -790,6 +806,7 @@ func (s *Ethereum) StopMining() {
}
func (s *Ethereum) IsMining() bool { return s.miner.Mining() }
+func (s *Ethereum) VoteEnabled() bool { return s.miner.VoteEnabled() }
func (s *Ethereum) Miner() *miner.Miner { return s.miner }
func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go
index 0642d6a1ad..2c94a95f36 100644
--- a/eth/catalyst/simulated_beacon.go
+++ b/eth/catalyst/simulated_beacon.go
@@ -100,7 +100,7 @@ type SimulatedBeacon struct {
func payloadVersion(config *params.ChainConfig, time uint64) engine.PayloadVersion {
switch config.LatestFork(time) {
- case forks.Prague, forks.Cancun:
+ case forks.Mendel, forks.Osaka, forks.Fermi, forks.Maxwell, forks.Lorentz, forks.Prague, forks.Cancun:
return engine.PayloadV3
case forks.Paris, forks.Shanghai:
return engine.PayloadV2
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index 3b3faa18ea..a95f0dfd14 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -210,6 +210,9 @@ type Config struct {
// OverrideOsaka (TODO: remove after the fork)
OverrideOsaka *uint64 `toml:",omitempty"`
+ // OverrideMendel (TODO: remove after the fork)
+ OverrideMendel *uint64 `toml:",omitempty"`
+
// OverrideVerkle (TODO: remove after the fork)
OverrideVerkle *uint64 `toml:",omitempty"`
diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go
index cce5e6b576..70b5ef0bae 100644
--- a/eth/ethconfig/gen_config.go
+++ b/eth/ethconfig/gen_config.go
@@ -75,6 +75,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
OverrideMaxwell *uint64 `toml:",omitempty"`
OverrideFermi *uint64 `toml:",omitempty"`
OverrideOsaka *uint64 `toml:",omitempty"`
+ OverrideMendel *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"`
BlobExtraReserve uint64
EnableOpcodeOptimizing bool
@@ -144,6 +145,7 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.OverrideMaxwell = c.OverrideMaxwell
enc.OverrideFermi = c.OverrideFermi
enc.OverrideOsaka = c.OverrideOsaka
+ enc.OverrideMendel = c.OverrideMendel
enc.OverrideVerkle = c.OverrideVerkle
enc.BlobExtraReserve = c.BlobExtraReserve
enc.EnableOpcodeOptimizing = c.EnableOpcodeOptimizing
@@ -217,6 +219,7 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
OverrideMaxwell *uint64 `toml:",omitempty"`
OverrideFermi *uint64 `toml:",omitempty"`
OverrideOsaka *uint64 `toml:",omitempty"`
+ OverrideMendel *uint64 `toml:",omitempty"`
OverrideVerkle *uint64 `toml:",omitempty"`
BlobExtraReserve *uint64
EnableOpcodeOptimizing *bool
@@ -403,6 +406,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.OverrideOsaka != nil {
c.OverrideOsaka = dec.OverrideOsaka
}
+ if dec.OverrideMendel != nil {
+ c.OverrideMendel = dec.OverrideMendel
+ }
if dec.OverrideVerkle != nil {
c.OverrideVerkle = dec.OverrideVerkle
}
diff --git a/eth/filters/api.go b/eth/filters/api.go
index b577d58d14..499610cd45 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -452,7 +452,19 @@ func (api *FilterAPI) TransactionReceipts(ctx context.Context, filter *Transacti
gopool.Submit(func() {
defer receiptsSub.Unsubscribe()
- signer := types.LatestSigner(api.sys.backend.ChainConfig())
+ var (
+ signer = types.LatestSigner(api.sys.backend.ChainConfig())
+ pending map[common.Hash]struct{} // Track pending receipts, nil means never auto-unsubscribe
+ gracePeriod <-chan time.Time
+ )
+
+ // Initialize pending map for specific tx hashes
+ if len(txHashes) > 0 {
+ pending = make(map[common.Hash]struct{}, len(txHashes))
+ for _, hash := range txHashes {
+ pending[hash] = struct{}{}
+ }
+ }
for {
select {
@@ -473,7 +485,21 @@ func (api *FilterAPI) TransactionReceipts(ctx context.Context, filter *Transacti
// Send a batch of tx receipts in one notification
notifier.Notify(rpcSub.ID, marshaledReceipts)
+
+ // Auto-unsubscribe when all receipts received (with grace period for reorgs)
+ if pending != nil {
+ for _, receiptWithTx := range receiptsWithTxs {
+ if receiptWithTx.Transaction != nil {
+ delete(pending, receiptWithTx.Transaction.Hash())
+ }
+ }
+ if len(pending) == 0 && gracePeriod == nil {
+ gracePeriod = time.After(12 * time.Second) // Grace period for reorg handling
+ }
+ }
}
+ case <-gracePeriod:
+ return
case <-rpcSub.Err():
return
}
diff --git a/eth/handler.go b/eth/handler.go
index 6f2bb7cdde..bb63d64bfa 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -833,7 +833,8 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) {
// Step 1: Select target peers for initial broadcast.
limit := totalPeers
- if !h.directBroadcast {
+ if !h.directBroadcast &&
+ !(h.networkID == 714 /*RialtoChainConfig.ChainID*/ && block.NumberU64() == 1) { // Populate TD from every receiver on startup to establish proper sync.
limit = int(math.Sqrt(float64(totalPeers)))
}
diff --git a/eth/handler_eth.go b/eth/handler_eth.go
index 0099fb0873..d96b3b849c 100644
--- a/eth/handler_eth.go
+++ b/eth/handler_eth.go
@@ -165,6 +165,10 @@ func (h *ethHandler) handleBlockBroadcast(peer *eth.Peer, packet *eth.NewBlockPa
trueHead = block.ParentHash()
trueTD = new(big.Int).Sub(td, block.Difficulty())
)
+ if block.NumberU64() == 1 { // this enable sync with the right peer when starting up a new network
+ trueHead = block.Hash()
+ trueTD = td
+ }
// Update the peer's total difficulty if better than the previous
if _, td := peer.Head(); trueTD.Cmp(td) > 0 {
peer.SetHead(trueHead, trueTD)
diff --git a/eth/sync.go b/eth/sync.go
index 9c608f374c..cf66a324d4 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -260,7 +260,11 @@ func (h *handler) doSync(op *chainSyncOp) error {
// degenerate connectivity, but it should be healthy for the mainnet too to
// more reliably update peers or the local TD state.
if block := h.chain.GetBlock(head.Hash(), head.Number.Uint64()); block != nil {
- h.BroadcastBlock(block, false)
+ if head.Number.Uint64() == 1 { // Update TD from all receivers during network initialization.
+ h.BroadcastBlock(block, true)
+ } else {
+ h.BroadcastBlock(block, false)
+ }
}
}
return nil
diff --git a/eth/tracers/api.go b/eth/tracers/api.go
index 42fbd62770..681652518d 100644
--- a/eth/tracers/api.go
+++ b/eth/tracers/api.go
@@ -1246,18 +1246,62 @@ func overrideConfig(original *params.ChainConfig, override *params.ChainConfig)
copy.ShanghaiTime = timestamp
canon = false
}
+ if timestamp := override.KeplerTime; timestamp != nil {
+ copy.KeplerTime = timestamp
+ canon = false
+ }
+ if timestamp := override.FeynmanTime; timestamp != nil {
+ copy.FeynmanTime = timestamp
+ canon = false
+ }
+ if timestamp := override.FeynmanFixTime; timestamp != nil {
+ copy.FeynmanFixTime = timestamp
+ canon = false
+ }
if timestamp := override.CancunTime; timestamp != nil {
copy.CancunTime = timestamp
canon = false
}
+ if timestamp := override.HaberTime; timestamp != nil {
+ copy.HaberTime = timestamp
+ canon = false
+ }
+ if timestamp := override.HaberFixTime; timestamp != nil {
+ copy.HaberFixTime = timestamp
+ canon = false
+ }
+ if timestamp := override.BohrTime; timestamp != nil {
+ copy.BohrTime = timestamp
+ canon = false
+ }
+ if timestamp := override.PascalTime; timestamp != nil {
+ copy.PascalTime = timestamp
+ canon = false
+ }
if timestamp := override.PragueTime; timestamp != nil {
copy.PragueTime = timestamp
canon = false
}
+ if timestamp := override.LorentzTime; timestamp != nil {
+ copy.LorentzTime = timestamp
+ canon = false
+ }
+ if timestamp := override.MaxwellTime; timestamp != nil {
+ copy.MaxwellTime = timestamp
+ canon = false
+ }
+ if timestamp := override.FermiTime; timestamp != nil {
+ copy.FermiTime = timestamp
+ canon = false
+ }
if timestamp := override.OsakaTime; timestamp != nil {
copy.OsakaTime = timestamp
canon = false
}
+ if timestamp := override.MendelTime; timestamp != nil {
+ copy.MendelTime = timestamp
+ canon = false
+ }
if timestamp := override.VerkleTime; timestamp != nil {
copy.VerkleTime = timestamp
canon = false
diff --git a/ethdb/leveldb/leveldb.go b/ethdb/leveldb/leveldb.go
index 736a44d73d..3d7c0ece0b 100644
--- a/ethdb/leveldb/leveldb.go
+++ b/ethdb/leveldb/leveldb.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build !js && !wasip1
-// +build !js,!wasip1
// Package leveldb implements the key-value database layer based on LevelDB.
package leveldb
diff --git a/internal/cmdtest/test_cmd.go b/internal/cmdtest/test_cmd.go
index f6f0425598..cabd0fe63b 100644
--- a/internal/cmdtest/test_cmd.go
+++ b/internal/cmdtest/test_cmd.go
@@ -255,8 +255,8 @@ type testlogger struct {
}
func (tl *testlogger) Write(b []byte) (n int, err error) {
- lines := bytes.Split(b, []byte("\n"))
- for _, line := range lines {
+ lines := bytes.SplitSeq(b, []byte("\n"))
+ for line := range lines {
if len(line) > 0 {
tl.t.Logf("(stderr:%v) %s", tl.name, line)
}
diff --git a/internal/debug/api.go b/internal/debug/api.go
index 1bac36e908..21592c2b27 100644
--- a/internal/debug/api.go
+++ b/internal/debug/api.go
@@ -217,7 +217,7 @@ func (*HandlerT) Stacks(filter *string) string {
dump := buf.String()
buf.Reset()
- for _, trace := range strings.Split(dump, "\n\n") {
+ for trace := range strings.SplitSeq(dump, "\n\n") {
if ok, _ := expr.Evaluate(map[string]string{"Value": trace}); ok {
buf.WriteString(trace)
buf.WriteString("\n\n")
diff --git a/log/handler_glog.go b/log/handler_glog.go
index 739f8c5b42..021d507c05 100644
--- a/log/handler_glog.go
+++ b/log/handler_glog.go
@@ -86,7 +86,7 @@ func (h *GlogHandler) Verbosity(level slog.Level) {
// sets V to 3 in all files of any packages whose import path contains "foo"
func (h *GlogHandler) Vmodule(ruleset string) error {
var filter []pattern
- for _, rule := range strings.Split(ruleset, ",") {
+ for rule := range strings.SplitSeq(ruleset, ",") {
// Empty strings such as from a trailing comma can be ignored
if len(rule) == 0 {
continue
@@ -113,7 +113,7 @@ func (h *GlogHandler) Vmodule(ruleset string) error {
}
// Compile the rule pattern into a regular expression
matcher := ".*"
- for _, comp := range strings.Split(parts[0], "/") {
+ for comp := range strings.SplitSeq(parts[0], "/") {
if comp == "*" {
matcher += "(/.*)?"
} else if comp != "" {
diff --git a/metrics/cpu_disabled.go b/metrics/cpu_disabled.go
index 37c3e1b8f7..415240f498 100644
--- a/metrics/cpu_disabled.go
+++ b/metrics/cpu_disabled.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build ios || js || wasip1 || tinygo
-// +build ios js wasip1 tinygo
package metrics
diff --git a/metrics/cpu_enabled.go b/metrics/cpu_enabled.go
index 37c23cad1a..9cab1387a3 100644
--- a/metrics/cpu_enabled.go
+++ b/metrics/cpu_enabled.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build !ios && !js && !wasip1 && !tinygo
-// +build !ios,!js,!wasip1,!tinygo
package metrics
diff --git a/metrics/cputime_nop.go b/metrics/cputime_nop.go
index 465d88c4d2..4eb962f228 100644
--- a/metrics/cputime_nop.go
+++ b/metrics/cputime_nop.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build windows || js
-// +build windows js
package metrics
diff --git a/metrics/cputime_unix.go b/metrics/cputime_unix.go
index a44bf80876..a3485049ba 100644
--- a/metrics/cputime_unix.go
+++ b/metrics/cputime_unix.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build !windows && !js && !wasip1
-// +build !windows,!js,!wasip1
package metrics
diff --git a/metrics/disk_nop.go b/metrics/disk_nop.go
index 41bbe9adb2..79ea3b7c02 100644
--- a/metrics/disk_nop.go
+++ b/metrics/disk_nop.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build !linux
-// +build !linux
package metrics
diff --git a/metrics/syslog.go b/metrics/syslog.go
index b265328f87..6ce98bad1c 100644
--- a/metrics/syslog.go
+++ b/metrics/syslog.go
@@ -1,5 +1,4 @@
//go:build !windows
-// +build !windows
package metrics
diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go
index b81ab2614e..9bcb6a1da3 100644
--- a/miner/bid_simulator.go
+++ b/miner/bid_simulator.go
@@ -771,8 +771,7 @@ func (b *bidSimulator) simBid(interruptCh chan int32, bidRuntime *BidRuntime) {
if len(bidRuntime.bid.Txs) > prefetchTxNumber {
var interrupt atomic.Bool
defer interrupt.Store(true) // terminate the prefetch at the end
- // TODO(Nathan): use ReadersWithCacheStats to accelerate
- throwaway := bidRuntime.env.state.CopyDoPrefetch()
+ throwaway := bidRuntime.env.state.StateForPrefetch()
// Disable tracing for prefetcher executions.
vmCfg := *b.chain.GetVMConfig()
vmCfg.Tracer = nil
diff --git a/miner/miner.go b/miner/miner.go
index 3479f81dce..e216d3c143 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -170,6 +170,10 @@ func (miner *Miner) Mining() bool {
return miner.worker.isRunning()
}
+func (miner *Miner) VoteEnabled() bool {
+ return miner.worker.config.VoteEnable && !miner.worker.config.MB.VoteDisable
+}
+
func (miner *Miner) InTurn() bool {
return miner.worker.inTurn()
}
@@ -227,6 +231,34 @@ func (miner *Miner) SetGasCeil(ceil uint64) {
miner.worker.setGasCeil(ceil)
}
+func (miner *Miner) MBConfig() minerconfig.MBConfig {
+ return miner.worker.config.MB
+}
+
+func (miner *Miner) ResetMaliciousBehavior() {
+ miner.worker.config.MB = minerconfig.DefaultMBConfig
+}
+
+func (miner *Miner) SetDoubleSign(on bool) {
+ miner.worker.config.MB.DoubleSign = on
+}
+
+func (miner *Miner) SetVoteDisable(on bool) {
+ miner.worker.config.MB.VoteDisable = on
+}
+
+func (miner *Miner) SetSkipOffsetInturn(offset uint64) {
+ miner.worker.config.MB.SkipOffsetInturn = &offset
+}
+
+func (miner *Miner) SetBroadcastDelayBlocks(num uint64) {
+ miner.worker.config.MB.BroadcastDelayBlocks = num
+}
+
+func (miner *Miner) SetLastBlockMiningTime(time uint64) {
+ miner.worker.config.MB.LastBlockMiningTime = time
+}
+
// BuildPayload builds the payload according to the provided parameters.
func (miner *Miner) BuildPayload(args *BuildPayloadArgs, witness bool) (*Payload, error) {
return miner.worker.buildPayload(args, witness)
diff --git a/miner/minerconfig/config.go b/miner/minerconfig/config.go
index fc13440b30..1cf60625f0 100644
--- a/miner/minerconfig/config.go
+++ b/miner/minerconfig/config.go
@@ -63,6 +63,7 @@ type Config struct {
DisableVoteAttestation bool // Whether to skip assembling vote attestation
Mev MevConfig // Mev configuration
+ MB MBConfig // Malicious behavior configuration
}
// DefaultConfig contains default settings for miner.
@@ -82,6 +83,7 @@ var DefaultConfig = Config{
MaxWaitProposalInSecs: &defaultMaxWaitProposalInSecs,
Mev: DefaultMevConfig,
+ MB: DefaultMBConfig,
}
type BuilderConfig struct {
@@ -163,3 +165,24 @@ func ApplyDefaultMinerConfig(cfg *Config) {
log.Info("ApplyDefaultMinerConfig", "Mev.MaxBidsPerBuilder", *cfg.Mev.MaxBidsPerBuilder)
}
}
+
+//go:generate go run github.com/fjl/gencodec -type MBConfig -formats toml -out gen_mb_config.go
+type MBConfig struct {
+ // Generate two consecutive blocks for the same parent block
+ DoubleSign bool
+ // Disable voting for Fast Finality
+ VoteDisable bool
+ // Skip block production for in-turn validators at a specified offset
+ SkipOffsetInturn *uint64 `toml:",omitempty"`
+ // Delay broadcasting mined blocks by a specified number of blocks, only for in turn validators
+ BroadcastDelayBlocks uint64
+ // Mining time (milliseconds) for the last block in every turn
+ LastBlockMiningTime uint64
+}
+
+var DefaultMBConfig = MBConfig{
+ DoubleSign: false,
+ VoteDisable: false,
+ BroadcastDelayBlocks: 0,
+ LastBlockMiningTime: 0,
+}
diff --git a/miner/worker.go b/miner/worker.go
index dbabc947dd..13feb688bf 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -20,6 +20,7 @@ import (
"errors"
"fmt"
"math/big"
+ "slices"
"sync"
"sync/atomic"
"time"
@@ -46,6 +47,7 @@ import (
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/miner/minerconfig"
"github.com/ethereum/go-ethereum/params"
+ "github.com/ethereum/go-ethereum/rpc"
)
const (
@@ -221,6 +223,10 @@ type worker struct {
skipSealHook func(*task) bool // Method to decide whether skipping the sealing.
fullTaskHook func() // Method to call before pushing the full sealing task.
resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval.
+
+ // Test purpose
+ delayedBlocksForBroadcast []*types.Block
+ delayedMu sync.RWMutex
}
func newWorker(config *minerconfig.Config, engine consensus.Engine, eth Backend, mux *event.TypeMux) *worker {
@@ -262,6 +268,8 @@ func newWorker(config *minerconfig.Config, engine consensus.Engine, eth Backend,
go worker.newWorkLoop(recommit)
go worker.resultLoop()
go worker.taskLoop()
+ worker.wg.Add(1)
+ go worker.delayBlocksBroadcastLoop()
return worker
}
@@ -589,15 +597,12 @@ func (w *worker) resultLoop() {
if prev, ok := w.recentMinedBlocks.Get(block.NumberU64()); ok {
doubleSign := false
prevParents := prev
- for _, prevParent := range prevParents {
- if prevParent == block.ParentHash() {
- log.Error("Reject Double Sign!!", "block", block.NumberU64(),
- "hash", block.Hash(),
- "root", block.Root(),
- "ParentHash", block.ParentHash())
- doubleSign = true
- break
- }
+ if slices.Contains(prevParents, block.ParentHash()) {
+ log.Error("Reject Double Sign!!", "block", block.NumberU64(),
+ "hash", block.Hash(),
+ "root", block.Root(),
+ "ParentHash", block.ParentHash())
+ doubleSign = true
}
if doubleSign {
continue
@@ -617,9 +622,11 @@ func (w *worker) resultLoop() {
}
task.state.DumpAccessList(block)
+ inturn := w.inTurn()
// Commit block and state to database.
start := time.Now()
- status, err := w.chain.WriteBlockAndSetHead(block, receipts, logs, task.state, w.mux)
+ needDelay := w.needDelayBroadcast(inturn)
+ status, err := w.chain.WriteBlockAndSetHead(block, receipts, logs, task.state, w.mux, needDelay)
if status != core.CanonStatTy {
if err != nil {
log.Error("Failed writing block to chain", "err", err, "status", status)
@@ -634,10 +641,111 @@ func (w *worker) resultLoop() {
stats.StartMiningTime.Store(task.miningStartAt.UnixMilli())
log.Info("Successfully seal and write new block", "number", block.Number(), "hash", hash, "time", block.Header().MilliTimestamp(), "sealhash", sealhash,
"block size(noBal)", block.Size(), "balSize", block.BALSize(), "elapsed", common.PrettyDuration(time.Since(task.createdAt)))
- w.mux.Post(core.NewMinedBlockEvent{Block: block})
+ if needDelay {
+ w.postDelayedBlock(block)
+ } else {
+ w.mux.Post(core.NewMinedBlockEvent{Block: block})
+ }
+ if p, ok := w.engine.(*parlia.Parlia); ok {
+ if w.config.MB.DoubleSign {
+ shadowHeader := block.Header()
+ shadowHeader.Extra[0] = 'd'
+ shadowHeader.Extra[1] = 's'
+ shadowBlock := types.NewBlockWithHeader(shadowHeader).WithBody(types.Body{Transactions: block.Transactions(), Uncles: block.Uncles()}).WithWithdrawals(block.Withdrawals())
+ shadowBlock.DeepCopySidecars(block.Sidecars())
+ shadowBlock, err := p.AssembleSignature(shadowBlock)
+ if err == nil {
+ w.postBlock(shadowBlock, inturn)
+ sealhash := w.engine.SealHash(shadowBlock.Header())
+ hash := shadowBlock.Hash()
+ log.Info("Successfully sealed new block", "number", shadowBlock.Number(), "sealhash", sealhash, "hash", hash,
+ "elapsed", common.PrettyDuration(time.Since(task.createdAt)))
+ if len(block.Sidecars()) != 0 {
+ log.Debug("show sidecars", "block.Sidecars()[0].BlockHash", block.Sidecars()[0].BlockHash, "shadowBlock.Sidecars()[0].BlockHash", shadowBlock.Sidecars()[0].BlockHash)
+ }
+ } else {
+ log.Info("Failed to AssembleSignature", "err", err)
+ }
+ }
+ }
+
+ case <-w.exitCh:
+ return
+ }
+ }
+}
+
+func (w *worker) needDelayBroadcast(inTurn bool) bool {
+ return w.config.MB.BroadcastDelayBlocks > 0 && inTurn
+}
+
+func (w *worker) postDelayedBlock(block *types.Block) {
+ w.delayedMu.Lock()
+ w.delayedBlocksForBroadcast = append(w.delayedBlocksForBroadcast, block)
+ w.delayedMu.Unlock()
+}
+
+func (w *worker) postBlock(block *types.Block, inTurn bool) {
+ if w.needDelayBroadcast(inTurn) {
+ w.postDelayedBlock(block)
+ } else {
+ w.mux.Post(core.NewSealedBlockEvent{Block: block})
+ w.mux.Post(core.NewMinedBlockEvent{Block: block})
+ }
+}
+func (w *worker) delayBlocksBroadcastLoop() {
+ defer w.wg.Done()
+
+ for {
+ if len(w.delayedBlocksForBroadcast) > 0 && w.config.MB.BroadcastDelayBlocks > 0 {
+ w.delayedMu.Lock()
+
+ currentBlock := w.chain.CurrentBlock()
+ currentBlockNum := currentBlock.Number.Uint64()
+
+ if p, ok := w.engine.(*parlia.Parlia); ok {
+ blockInterval, err := p.BlockInterval(w.chain, currentBlock)
+ if err != nil {
+ log.Debug("failed to get BlockInterval when delayBlocksBroadcastLoop")
+ }
+ delayTime := (w.config.MB.BroadcastDelayBlocks - 1) * blockInterval
+ service := p.APIs(w.chain)[0].Service
+ latestBlockNumber := rpc.LatestBlockNumber
+ currentTurnLength, err := service.(*parlia.API).GetTurnLength(&latestBlockNumber)
+ nonInTurnBackoff := w.config.MB.BroadcastDelayBlocks
+ if err == nil {
+ if w.config.MB.BroadcastDelayBlocks > uint64(currentTurnLength) {
+ // suppose extra blocks are generated by in turn validators
+ nonInTurnBackoff = uint64(currentTurnLength)
+ }
+ }
+ if w.chainConfig.IsLorentz(currentBlock.Number, currentBlock.Time) { // not exactly right, but no matters
+ nonInTurnBackoff *= 2
+ }
+ delayTime += nonInTurnBackoff * 1000
+
+ firstBlock := w.delayedBlocksForBroadcast[0]
+ if uint64(time.Now().UnixMilli()) >= (firstBlock.Header().MilliTimestamp() + delayTime) {
+ time.Sleep(500 * time.Microsecond)
+ for _, block := range w.delayedBlocksForBroadcast {
+ w.mux.Post(core.NewSealedBlockEvent{Block: block})
+ w.mux.Post(core.NewMinedBlockEvent{Block: block})
+ log.Info("delayBlocksBroadcastLoop", "number", block.Number(), "hash", block.Hash(),
+ "milliTimestamp", block.Header().MilliTimestamp(), "now", uint64(time.Now().UnixMilli()), "currentBlockNum", currentBlockNum)
+ }
+ w.delayedBlocksForBroadcast = make([]*types.Block, 0)
+ }
+ }
+
+ w.delayedMu.Unlock()
+ }
+
+ select {
case <-w.exitCh:
return
+ default:
+ time.Sleep(100 * time.Millisecond)
}
}
}
@@ -1192,6 +1300,25 @@ func (w *worker) commitWork(interruptCh chan int32, timestamp int64) {
return
}
}
+ if w.config.MB.SkipOffsetInturn != nil {
+ if w.inTurn() {
+ if p, ok := w.engine.(*parlia.Parlia); ok {
+ service := p.APIs(w.chain)[0].Service
+ latestBlockNumber := rpc.LatestBlockNumber
+ currentTurnLength, err := service.(*parlia.API).GetTurnLength(&latestBlockNumber)
+ if err == nil {
+ currentHeader := w.chain.CurrentBlock()
+ blockToMine := currentHeader.Number.Uint64() + 1
+ if *w.config.MB.SkipOffsetInturn == blockToMine%uint64(currentTurnLength) {
+ log.Info("skip commitWork", "blockNumber", blockToMine)
+ return
+ }
+ } else {
+ log.Error("commitWork|GetTurnLength", "err", err)
+ }
+ }
+ }
+ }
stopTimer := time.NewTimer(0)
defer stopTimer.Stop()
@@ -1232,6 +1359,24 @@ LOOP:
workList = append(workList, work)
delay := w.engine.Delay(w.chain, work.header, w.config.DelayLeftOver)
+ if p, ok := w.engine.(*parlia.Parlia); ok {
+ blockInterval, err := p.BlockInterval(w.chain, work.header)
+ if err != nil {
+ log.Debug("failed to get BlockInterval when tryWaitProposalDoneWhenStopping")
+ }
+ if w.config.MB.LastBlockMiningTime > blockInterval/2 {
+ service := p.APIs(w.chain)[0].Service
+ latestBlockNumber := rpc.LatestBlockNumber
+ currentTurnLength, err := service.(*parlia.API).GetTurnLength(&latestBlockNumber)
+ if err == nil && (work.header.Number.Uint64()+1)%uint64(currentTurnLength) == 0 {
+ *delay += time.Duration((w.config.MB.LastBlockMiningTime - blockInterval/2) * uint64(time.Millisecond))
+ timeLeft := time.Until(time.UnixMilli(int64(work.header.MilliTimestamp())))
+ if *delay > timeLeft {
+ *delay = timeLeft
+ }
+ }
+ }
+ }
if delay == nil {
log.Warn("commitWork delay is nil, something is wrong")
stopTimer = nil
diff --git a/node/api.go b/node/api.go
index 27b91d4aee..43367b1dab 100644
--- a/node/api.go
+++ b/node/api.go
@@ -186,19 +186,19 @@ func (api *adminAPI) StartHTTP(host *string, port *int, cors *string, apis *stri
}
if cors != nil {
config.CorsAllowedOrigins = nil
- for _, origin := range strings.Split(*cors, ",") {
+ for origin := range strings.SplitSeq(*cors, ",") {
config.CorsAllowedOrigins = append(config.CorsAllowedOrigins, strings.TrimSpace(origin))
}
}
if vhosts != nil {
config.Vhosts = nil
- for _, vhost := range strings.Split(*host, ",") {
+ for vhost := range strings.SplitSeq(*vhosts, ",") {
config.Vhosts = append(config.Vhosts, strings.TrimSpace(vhost))
}
}
if apis != nil {
config.Modules = nil
- for _, m := range strings.Split(*apis, ",") {
+ for m := range strings.SplitSeq(*apis, ",") {
config.Modules = append(config.Modules, strings.TrimSpace(m))
}
}
@@ -265,13 +265,13 @@ func (api *adminAPI) StartWS(host *string, port *int, allowedOrigins *string, ap
}
if apis != nil {
config.Modules = nil
- for _, m := range strings.Split(*apis, ",") {
+ for m := range strings.SplitSeq(*apis, ",") {
config.Modules = append(config.Modules, strings.TrimSpace(m))
}
}
if allowedOrigins != nil {
config.Origins = nil
- for _, origin := range strings.Split(*allowedOrigins, ",") {
+ for origin := range strings.SplitSeq(*allowedOrigins, ",") {
config.Origins = append(config.Origins, strings.TrimSpace(origin))
}
}
diff --git a/node/rpcstack_test.go b/node/rpcstack_test.go
index 54e58cccb2..5bf05aebb0 100644
--- a/node/rpcstack_test.go
+++ b/node/rpcstack_test.go
@@ -74,8 +74,8 @@ type originTest struct {
// and trims excessive white space from the substrings.
// Copied over from flags.go
func splitAndTrim(input string) (ret []string) {
- l := strings.Split(input, ",")
- for _, r := range l {
+ l := strings.SplitSeq(input, ",")
+ for r := range l {
r = strings.TrimSpace(r)
if len(r) > 0 {
ret = append(ret, r)
diff --git a/p2p/netutil/toobig_notwindows.go b/p2p/netutil/toobig_notwindows.go
index f9f936ae56..a9c5601c7c 100644
--- a/p2p/netutil/toobig_notwindows.go
+++ b/p2p/netutil/toobig_notwindows.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build !windows
-// +build !windows
package netutil
diff --git a/p2p/netutil/toobig_windows.go b/p2p/netutil/toobig_windows.go
index 652903e83c..13a1ace051 100644
--- a/p2p/netutil/toobig_windows.go
+++ b/p2p/netutil/toobig_windows.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build windows
-// +build windows
package netutil
diff --git a/p2p/peer.go b/p2p/peer.go
index f9e9d424da..1f781fe0c3 100644
--- a/p2p/peer.go
+++ b/p2p/peer.go
@@ -209,10 +209,8 @@ func (p *Peer) Caps() []Cap {
// versions is supported by both this node and the peer p.
func (p *Peer) RunningCap(protocol string, versions []uint) bool {
if proto, ok := p.running[protocol]; ok {
- for _, ver := range versions {
- if proto.Version == ver {
- return true
- }
+ if slices.Contains(versions, proto.Version) {
+ return true
}
}
return false
diff --git a/params/config.go b/params/config.go
index 7c96e8a68e..ed6512ece5 100644
--- a/params/config.go
+++ b/params/config.go
@@ -225,8 +225,9 @@ var (
PragueTime: newUint64(1742436600), // 2025-03-20 02:10:00 AM UTC
LorentzTime: newUint64(1745903100), // 2025-04-29 05:05:00 AM UTC
MaxwellTime: newUint64(1751250600), // 2025-06-30 02:30:00 AM UTC
- FermiTime: nil,
+ FermiTime: newUint64(1768357800), // 2026-01-14 02:30:00 AM UTC
OsakaTime: nil,
+ MendelTime: nil,
Parlia: &ParliaConfig{},
BlobScheduleConfig: &BlobScheduleConfig{
@@ -276,6 +277,7 @@ var (
MaxwellTime: newUint64(1748243100), // 2025-05-26 07:05:00 AM UTC
FermiTime: newUint64(1762741500), // 2025-11-10 02:25:00 AM UTC
OsakaTime: nil,
+ MendelTime: nil,
Parlia: &ParliaConfig{},
BlobScheduleConfig: &BlobScheduleConfig{
@@ -325,8 +327,9 @@ var (
LorentzTime: newUint64(0),
MaxwellTime: newUint64(0),
// TODO: set them to `0` when passed on the mainnet
- FermiTime: nil,
- OsakaTime: nil,
+ FermiTime: nil,
+ OsakaTime: nil,
+ MendelTime: nil,
Parlia: &ParliaConfig{},
BlobScheduleConfig: &BlobScheduleConfig{
@@ -656,6 +659,7 @@ type ChainConfig struct {
MaxwellTime *uint64 `json:"maxwellTime,omitempty"` // Maxwell switch time (nil = no fork, 0 = already on maxwell)
FermiTime *uint64 `json:"fermiTime,omitempty"` // Fermi switch time (nil = no fork, 0 = already on fermi)
OsakaTime *uint64 `json:"osakaTime,omitempty"` // Osaka switch time (nil = no fork, 0 = already on osaka)
+ MendelTime *uint64 `json:"mendelTime,omitempty"` // Mendel switch time (nil = no fork, 0 = already on mendel)
VerkleTime *uint64 `json:"verkleTime,omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle)
// TerminalTotalDifficulty is the amount of total difficulty reached by
@@ -837,9 +841,15 @@ func (c *ChainConfig) String() string {
OsakaTime = big.NewInt(0).SetUint64(*c.OsakaTime)
}
+ var MendelTime *big.Int
+ if c.MendelTime != nil {
+ MendelTime = big.NewInt(0).SetUint64(*c.MendelTime)
+ }
+
return fmt.Sprintf("{ChainID: %v, Engine: %v, Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, "+
"MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Luban: %v, Plato: %v, Hertz: %v, Hertzfix: %v, "+
- "ShanghaiTime: %v, KeplerTime: %v, FeynmanTime: %v, FeynmanFixTime: %v, CancunTime: %v, HaberTime: %v, HaberFixTime: %v, BohrTime: %v, PascalTime: %v, PragueTime: %v, LorentzTime: %v, MaxwellTime: %v, FermiTime: %v, OsakaTime: %v}",
+ "ShanghaiTime: %v, KeplerTime: %v, FeynmanTime: %v, FeynmanFixTime: %v, CancunTime: %v, HaberTime: %v, HaberFixTime: %v, BohrTime: %v, PascalTime: %v, PragueTime: %v, LorentzTime: %v, MaxwellTime: %v, FermiTime: %v, "+
+ "OsakaTime: %v, MendelTime: %v}",
c.ChainID,
engine,
c.HomesteadBlock,
@@ -886,6 +896,7 @@ func (c *ChainConfig) String() string {
MaxwellTime,
FermiTime,
OsakaTime,
+ MendelTime,
)
}
@@ -1300,6 +1311,20 @@ func (c *ChainConfig) IsOnOsaka(currentBlockNumber *big.Int, lastBlockTime uint6
return !c.IsOsaka(lastBlockNumber, lastBlockTime) && c.IsOsaka(currentBlockNumber, currentBlockTime)
}
+// IsMendel returns whether time is either equal to the Mendel fork time or greater.
+func (c *ChainConfig) IsMendel(num *big.Int, time uint64) bool {
+ return c.IsLondon(num) && isTimestampForked(c.MendelTime, time)
+}
+
+// IsOnMendel eturns whether currentBlockTime is either equal to the Mendel fork time or greater firstly.
+func (c *ChainConfig) IsOnMendel(currentBlockNumber *big.Int, lastBlockTime uint64, currentBlockTime uint64) bool {
+ lastBlockNumber := new(big.Int)
+ if currentBlockNumber.Cmp(big.NewInt(1)) >= 0 {
+ lastBlockNumber.Sub(currentBlockNumber, big.NewInt(1))
+ }
+ return !c.IsMendel(lastBlockNumber, lastBlockTime) && c.IsMendel(currentBlockNumber, currentBlockTime)
+}
+
// IsVerkle returns whether time is either equal to the Verkle fork time or greater.
func (c *ChainConfig) IsVerkle(num *big.Int, time uint64) bool {
return c.IsLondon(num) && isTimestampForked(c.VerkleTime, time)
@@ -1386,6 +1411,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
{name: "maxwellTime", timestamp: c.MaxwellTime},
{name: "fermiTime", timestamp: c.FermiTime},
{name: "osakaTime", timestamp: c.OsakaTime},
+ {name: "mendelTime", timestamp: c.MendelTime},
{name: "verkleTime", timestamp: c.VerkleTime, optional: true},
} {
if lastFork.name != "" {
@@ -1599,6 +1625,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int,
if isForkTimestampIncompatible(c.OsakaTime, newcfg.OsakaTime, headTimestamp) {
return newTimestampCompatError("Osaka fork timestamp", c.OsakaTime, newcfg.OsakaTime)
}
+ if isForkTimestampIncompatible(c.MendelTime, newcfg.MendelTime, headTimestamp) {
+ return newTimestampCompatError("Mendel fork timestamp", c.MendelTime, newcfg.MendelTime)
+ }
if isForkTimestampIncompatible(c.VerkleTime, newcfg.VerkleTime, headTimestamp) {
return newTimestampCompatError("Verkle fork timestamp", c.VerkleTime, newcfg.VerkleTime)
}
@@ -1622,6 +1651,8 @@ func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
london := c.LondonBlock
switch {
+ case c.IsMendel(london, time):
+ return forks.Mendel
case c.IsOsaka(london, time):
return forks.Osaka
case c.IsFermi(london, time):
@@ -1645,6 +1676,8 @@ func (c *ChainConfig) LatestFork(time uint64) forks.Fork {
// the fork isn't defined or isn't a time-based fork.
func (c *ChainConfig) Timestamp(fork forks.Fork) *uint64 {
switch {
+ case fork == forks.Mendel:
+ return c.MendelTime
case fork == forks.Osaka:
return c.OsakaTime
case fork == forks.Fermi:
@@ -1814,7 +1847,7 @@ type Rules struct {
IsHertzfix bool
IsShanghai, IsKepler, IsFeynman, IsCancun, IsHaber bool
IsBohr, IsPascal, IsPrague, IsLorentz, IsMaxwell bool
- IsFermi, IsOsaka, IsVerkle bool
+ IsFermi, IsOsaka, IsMendel, IsVerkle bool
}
// Rules ensures c's ChainID is not nil.
@@ -1859,6 +1892,7 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules
IsMaxwell: c.IsMaxwell(num, timestamp),
IsFermi: c.IsFermi(num, timestamp),
IsOsaka: c.IsOsaka(num, timestamp),
+ IsMendel: c.IsMendel(num, timestamp),
IsVerkle: c.IsVerkle(num, timestamp),
IsEIP4762: isVerkle,
}
diff --git a/params/forks/forks.go b/params/forks/forks.go
index 27ac421c0c..ff12e1f464 100644
--- a/params/forks/forks.go
+++ b/params/forks/forks.go
@@ -44,6 +44,7 @@ const (
Maxwell
Fermi
Osaka
+ Mendel
)
// String implements fmt.Stringer.
@@ -79,4 +80,5 @@ var forkToString = map[Fork]string{
Maxwell: "Maxwell",
Fermi: "Fermi",
Osaka: "Osaka",
+ Mendel: "Mendel",
}
diff --git a/rlp/safe.go b/rlp/safe.go
index 3c910337b6..72807abe74 100644
--- a/rlp/safe.go
+++ b/rlp/safe.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build nacl || js || !cgo
-// +build nacl js !cgo
package rlp
diff --git a/rlp/unsafe.go b/rlp/unsafe.go
index 10868caaf2..b8f334ac1b 100644
--- a/rlp/unsafe.go
+++ b/rlp/unsafe.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build !nacl && !js && cgo
-// +build !nacl,!js,cgo
package rlp
diff --git a/rpc/ipc_js.go b/rpc/ipc_js.go
index 453a20bc1a..ce0779b656 100644
--- a/rpc/ipc_js.go
+++ b/rpc/ipc_js.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build js
-// +build js
package rpc
diff --git a/rpc/ipc_unix.go b/rpc/ipc_unix.go
index 588bf62605..bd5639c119 100644
--- a/rpc/ipc_unix.go
+++ b/rpc/ipc_unix.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build darwin || dragonfly || freebsd || linux || nacl || netbsd || openbsd || solaris
-// +build darwin dragonfly freebsd linux nacl netbsd openbsd solaris
package rpc
diff --git a/rpc/ipc_wasip1.go b/rpc/ipc_wasip1.go
index 2608e29222..ceced01d12 100644
--- a/rpc/ipc_wasip1.go
+++ b/rpc/ipc_wasip1.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build wasip1
-// +build wasip1
package rpc
diff --git a/rpc/ipc_windows.go b/rpc/ipc_windows.go
index efec38cf37..62a6d4b84e 100644
--- a/rpc/ipc_windows.go
+++ b/rpc/ipc_windows.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build windows
-// +build windows
package rpc
diff --git a/tests/fuzzers/bls12381/bls12381_fuzz.go b/tests/fuzzers/bls12381/bls12381_fuzz.go
index a17c128b7f..6b4db1278a 100644
--- a/tests/fuzzers/bls12381/bls12381_fuzz.go
+++ b/tests/fuzzers/bls12381/bls12381_fuzz.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build cgo
-// +build cgo
package bls
diff --git a/tests/fuzzers/bls12381/bls12381_test.go b/tests/fuzzers/bls12381/bls12381_test.go
index cb89d8a7a7..b33eb7716f 100644
--- a/tests/fuzzers/bls12381/bls12381_test.go
+++ b/tests/fuzzers/bls12381/bls12381_test.go
@@ -15,7 +15,6 @@
// along with the go-ethereum library. If not, see .
//go:build cgo
-// +build cgo
package bls