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