From b237a2c398cb3b5c460e2200ffb99308a779b625 Mon Sep 17 00:00:00 2001 From: qybdyx Date: Wed, 6 May 2026 17:09:23 +0800 Subject: [PATCH 01/48] eth/handler.go: add verify bal --- eth/handler.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/eth/handler.go b/eth/handler.go index 83c628b23c..c1cee8f648 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -358,7 +358,9 @@ func newHandler(config *handlerConfig) (*handler, error) { for i, item := range res { block := types.NewBlockWithHeader(item.Header).WithBody(types.Body{Transactions: item.Txs, Uncles: item.Uncles}) block = block.WithSidecars(item.Sidecars) - block = block.WithBAL(item.BAL) + if item.BAL != nil && h.chain.Engine().VerifyBAL(block, item.BAL) == nil { + block = block.WithBAL(item.BAL) + } block.ReceivedAt = time.Now() block.ReceivedFrom = p.ID() if err := block.SanityCheck(); err != nil { From a9e67f2d29743fd73a4ebb1b53b1305034b011af Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Mon, 11 May 2026 14:15:11 +0800 Subject: [PATCH 02/48] triedb/pathdb: remove legacy field JournalFilePath (#3670) * Revert "pathdb: add backward compatibility for legacy journal file format" This reverts commit f4d66f2d7b37942e99b46ce1487c5cd008999bc8. * triedb/pathdb: remove legacy field JournalFilePath --- cmd/geth/chaincmd.go | 4 +-- cmd/geth/dbcmd.go | 2 +- cmd/geth/main.go | 2 +- cmd/utils/flags.go | 10 ++---- core/blockchain.go | 2 -- eth/backend.go | 7 ---- triedb/pathdb/config.go | 2 -- triedb/pathdb/journal.go | 71 ++++++---------------------------------- 8 files changed, 17 insertions(+), 83 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 5da9d17ade..7a5a3452ac 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -1063,7 +1063,7 @@ func parseDumpConfig(ctx *cli.Context, stack *node.Node, db ethdb.Database) (*st } else { // Use latest if scheme == rawdb.PathScheme { - triedb := triedb.NewDatabase(db, &triedb.Config{PathDB: utils.PathDBConfigAddJournalFilePath(stack, pathdb.ReadOnly)}) + triedb := triedb.NewDatabase(db, &triedb.Config{PathDB: pathdb.ReadOnly}) defer triedb.Close() if stateRoot := triedb.Head(); stateRoot != (common.Hash{}) { header.Root = stateRoot @@ -1136,7 +1136,7 @@ func dumpAllRootHashInPath(ctx *cli.Context) error { defer stack.Close() db := utils.MakeChainDatabase(ctx, stack, true) defer db.Close() - triedb := triedb.NewDatabase(db, &triedb.Config{PathDB: utils.PathDBConfigAddJournalFilePath(stack, pathdb.ReadOnly)}) + triedb := triedb.NewDatabase(db, &triedb.Config{PathDB: pathdb.ReadOnly}) defer triedb.Close() scheme, err := rawdb.ParseStateScheme(ctx.String(utils.StateSchemeFlag.Name), db) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 1bedff0079..75971473fb 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -458,7 +458,7 @@ func inspectTrie(ctx *cli.Context) error { var config *triedb.Config if dbScheme == rawdb.PathScheme { config = &triedb.Config{ - PathDB: utils.PathDBConfigAddJournalFilePath(stack, pathdb.ReadOnly), + PathDB: pathdb.ReadOnly, } } else if dbScheme == rawdb.HashScheme { config = triedb.HashDefaults diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 1e13ea9f9b..69bd7aa0ee 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -121,7 +121,7 @@ var ( utils.LogExportCheckpointsFlag, utils.StateHistoryFlag, utils.PathDBSyncFlag, - utils.JournalFileFlag, + utils.JournalFileFlag, // deprecated utils.LightKDFFlag, utils.EthRequiredBlocksFlag, utils.LegacyWhitelistFlag, // deprecated diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index b75d6a813f..eb2858de76 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2807,12 +2807,6 @@ func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb. return statediskdb } -func PathDBConfigAddJournalFilePath(stack *node.Node, config *pathdb.Config) *pathdb.Config { - path := fmt.Sprintf("%s/%s", stack.ResolvePath("chaindata"), eth.JournalFileName) - config.JournalFilePath = path - return config -} - // tryMakeReadOnlyDatabase try to open the chain database in read-only mode, // or fallback to write mode if the database is not initialized. // @@ -2990,6 +2984,9 @@ func MakeConsolePreloads(ctx *cli.Context) []string { // MakeTrieDatabase constructs a trie database based on the configured scheme. func MakeTrieDatabase(ctx *cli.Context, stack *node.Node, disk ethdb.Database, preimage bool, readOnly bool, isVerkle bool, mergeIncr bool) *triedb.Database { + if ctx.IsSet(JournalFileFlag.Name) { + log.Warn("--journalfile is deprecated and has no effect, please remove it") + } config := &triedb.Config{ Preimages: preimage, IsVerkle: isVerkle, @@ -3016,7 +3013,6 @@ func MakeTrieDatabase(ctx *cli.Context, stack *node.Node, disk ethdb.Database, p } pathConfig.JournalDirectory = stack.ResolvePath("triedb") config.PathDB = &pathConfig - config.PathDB.JournalFilePath = fmt.Sprintf("%s/%s", stack.ResolvePath("chaindata"), eth.JournalFileName) return triedb.NewDatabase(disk, config) } diff --git a/core/blockchain.go b/core/blockchain.go index a2f519d0d0..6150fa2fc8 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -184,7 +184,6 @@ type BlockChainConfig struct { TriesInMemory uint64 // How many tries keeps in memory NoTries bool // Insecure settings. Do not have any tries in databases if enabled. PathSyncFlush bool // Whether sync flush the trienodebuffer of pathdb to disk. - JournalFilePath string // The path to store journal file which is used in pathdb EnableIncr bool // Flag whether the freezer db stores incremental block and state history IncrHistoryPath string // The path to store incremental block and chain files IncrHistory uint64 // Amount of block and state history stored in incremental freezer db @@ -286,7 +285,6 @@ func (cfg *BlockChainConfig) triedbConfig(isVerkle bool) *triedb.Config { } if cfg.StateScheme == rawdb.PathScheme { config.PathDB = &pathdb.Config{ - JournalFilePath: cfg.JournalFilePath, EnableIncr: cfg.EnableIncr, IncrHistoryPath: cfg.IncrHistoryPath, IncrHistory: cfg.IncrHistory, diff --git a/eth/backend.go b/eth/backend.go index b50d3f61fd..d5ac85ddaa 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -76,7 +76,6 @@ import ( const ( ChainDBNamespace = "eth/db/chaindata/" - JournalFileName = "trie.journal" ChainData = "chaindata" ) @@ -336,11 +335,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { } } - path := ChainData - if stack.CheckIfMultiDataBase() { - path = ChainData + "/state" - } - journalFilePath := stack.ResolvePath(path) + "/" + JournalFileName var ( options = &core.BlockChainConfig{ TrieCleanLimit: config.TrieCleanCache, @@ -356,7 +350,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { StateHistory: config.StateHistory, StateScheme: config.StateScheme, PathSyncFlush: config.PathSyncFlush, - JournalFilePath: journalFilePath, EnableIncr: config.EnableIncrSnapshots, IncrHistoryPath: config.IncrSnapshotPath, IncrHistory: config.IncrSnapshotBlockInterval, diff --git a/triedb/pathdb/config.go b/triedb/pathdb/config.go index d7cf7a5422..afc19081ff 100644 --- a/triedb/pathdb/config.go +++ b/triedb/pathdb/config.go @@ -81,8 +81,6 @@ type Config struct { NoAsyncFlush bool // Flag whether the background buffer flushing is disabled NoAsyncGeneration bool // Flag whether the background generation is disabled - JournalFilePath string // The path of journal file - EnableIncr bool // Flag whether the freezer db stores incr block and state history MergeIncr bool // Flag to merge incr snapshots IncrHistory uint64 // Amount of block and state history stored in incr freezer db diff --git a/triedb/pathdb/journal.go b/triedb/pathdb/journal.go index 7132c3f920..a2e472bcd7 100644 --- a/triedb/pathdb/journal.go +++ b/triedb/pathdb/journal.go @@ -64,15 +64,6 @@ func (db *Database) loadJournal(diskRoot common.Hash) (layer, error) { } defer f.Close() reader = f - } else if path := db.config.JournalFilePath; path != "" && common.FileExist(path) { // TODO(Nathan): delete this branch in v1.8.x - // If a journal file is specified, read it from there - log.Info("Load database journal from file", "path", path) - f, err := os.OpenFile(path, os.O_RDONLY, 0644) - if err != nil { - return nil, fmt.Errorf("failed to read journal file %s: %w", path, err) - } - defer f.Close() - reader = f } else { log.Info("Load database journal from disk") journal := rawdb.ReadTrieJournal(db.diskdb) @@ -189,40 +180,19 @@ func (db *Database) loadLayers() layer { return newDiskLayer(root, rawdb.ReadPersistentStateID(db.diskdb), db, nil, nil, newBuffer(db.config.WriteBufferSize, nil, nil, 0), nil) } -// tryUnwrapJournal detects legacy format and unwraps if needed. -// Legacy format: wraps layer data in []byte with shasum. -func tryUnwrapJournal(r *rlp.Stream) (jr *rlp.Stream, isLegacy bool, err error) { - kind, size, err := r.Kind() - if err != nil { - return nil, false, err - } - if kind == rlp.String && size > common.HashLength { - var buf []byte - if err := r.Decode(&buf); err != nil { - return nil, false, err - } - return rlp.NewStream(bytes.NewReader(buf), 0), true, nil - } - return r, false, nil -} - // loadDiskLayer reads the binary blob from the layer journal, reconstructing // a new disk layer on it. func (db *Database) loadDiskLayer(r *rlp.Stream) (layer, error) { - jr, isLegacy, err := tryUnwrapJournal(r) - if err != nil { - return nil, fmt.Errorf("load disk layer: %v", err) - } - + // Resolve disk layer root var root common.Hash - if err := jr.Decode(&root); err != nil { + if err := r.Decode(&root); err != nil { return nil, fmt.Errorf("load disk root: %v", err) } // Resolve the state id of disk layer, it can be different // with the persistent id tracked in disk, the id distance // is the number of transitions aggregated in disk layer. var id uint64 - if err := jr.Decode(&id); err != nil { + if err := r.Decode(&id); err != nil { return nil, fmt.Errorf("load state id: %v", err) } stored := rawdb.ReadPersistentStateID(db.diskdb) @@ -231,37 +201,23 @@ func (db *Database) loadDiskLayer(r *rlp.Stream) (layer, error) { } // Resolve nodes cached in aggregated buffer var nodes nodeSet - if err := nodes.decode(jr); err != nil { + if err := nodes.decode(r); err != nil { return nil, err } // Resolve flat state sets in aggregated buffer var states stateSet - if err := states.decode(jr); err != nil { + if err := states.decode(r); err != nil { return nil, err } - // Skip shasum if legacy format - if isLegacy { - var shaSum [32]byte - if err := r.Decode(&shaSum); err != nil { - return nil, fmt.Errorf("load disk shasum: %v", err) - } - } return newDiskLayer(root, id, db, nil, nil, newBuffer(db.config.WriteBufferSize, &nodes, &states, id-stored), nil), nil } // loadDiffLayer reads the next sections of a layer journal, reconstructing a new // diff and verifying that it can be linked to the requested parent. func (db *Database) loadDiffLayer(parent layer, r *rlp.Stream) (layer, error) { - jr, isLegacy, err := tryUnwrapJournal(r) - if err != nil { - if err == io.EOF { - return parent, nil - } - return nil, fmt.Errorf("load diff layer: %v", err) - } - + // Read the next diff journal entry var root common.Hash - if err := jr.Decode(&root); err != nil { + if err := r.Decode(&root); err != nil { // The first read may fail with EOF, marking the end of the journal if err == io.EOF { return parent, nil @@ -269,26 +225,19 @@ func (db *Database) loadDiffLayer(parent layer, r *rlp.Stream) (layer, error) { return nil, fmt.Errorf("load diff root: %v", err) } var block uint64 - if err := jr.Decode(&block); err != nil { + if err := r.Decode(&block); err != nil { return nil, fmt.Errorf("load block number: %v", err) } // Read in-memory trie nodes from journal var nodes nodeSetWithOrigin - if err := nodes.decode(jr); err != nil { + if err := nodes.decode(r); err != nil { return nil, err } // Read flat states set (with original value attached) from journal var stateSet StateSetWithOrigin - if err := stateSet.decode(jr); err != nil { + if err := stateSet.decode(r); err != nil { return nil, err } - // Skip shasum if legacy format - if isLegacy { - var shaSum [32]byte - if err := r.Decode(&shaSum); err != nil { - return nil, fmt.Errorf("load diff shasum: %v", err) - } - } return db.loadDiffLayer(newDiffLayer(parent, root, parent.stateID()+1, block, &nodes, &stateSet), r) } From 9d07c7be374bc8f5ab26679547ecf790dc82c2e0 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Mon, 11 May 2026 17:26:18 +0800 Subject: [PATCH 03/48] miner: remove optional transaction gas limit cap (#3678) --- cmd/geth/main.go | 16 ---------------- cmd/utils/flags.go | 11 +---------- cmd/utils/flags_legacy.go | 7 +++++++ core/txpool/blobpool/blobpool.go | 10 ---------- core/txpool/legacypool/legacypool.go | 10 ---------- core/txpool/subpool.go | 3 --- core/txpool/txpool.go | 6 ------ core/txpool/validation.go | 6 ------ eth/api_miner.go | 11 ----------- internal/web3ext/web3ext.go | 6 ------ miner/bid_simulator.go | 24 +++++++----------------- miner/miner.go | 6 +----- miner/minerconfig/config.go | 1 - miner/worker.go | 10 ---------- 14 files changed, 16 insertions(+), 111 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 69bd7aa0ee..ca111ca77b 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -26,8 +26,6 @@ import ( "strings" "time" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/cmd/utils" @@ -465,20 +463,6 @@ func startNode(ctx *cli.Context, stack *node.Node, backend ethapi.Backend, isCon // Start auxiliary services if enabled ethBackend, ok := backend.(*eth.EthAPIBackend) - gasCeil := ethBackend.Miner().GasCeil() - maxTxGas := uint64(0) - if gasCeil > params.SystemTxsGasSoftLimit { - maxTxGas = gasCeil - params.SystemTxsGasSoftLimit - } - if txGasLimit := ethBackend.Miner().TxGasLimit(); txGasLimit > 0 { - if maxTxGas == 0 || txGasLimit < maxTxGas { - maxTxGas = txGasLimit - } - } - if maxTxGas > 0 { - ethBackend.TxPool().SetMaxGas(maxTxGas) - } - if ctx.Bool(utils.MiningEnabledFlag.Name) { // Mining only makes sense if a full Ethereum node is running if ctx.String(utils.SyncModeFlag.Name) == "light" { diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index eb2858de76..6b73c7111f 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -584,11 +584,6 @@ var ( Value: ethconfig.Defaults.TxPool.ReannounceTime, Category: flags.TxPoolCategory, } - MinerTxGasLimitFlag = &cli.Uint64Flag{ - Name: "miner.txgaslimit", - Usage: fmt.Sprintf("Maximum gas allowed per transaction (default = 0, disabled; min = %d)", params.MaxTxGas), - Category: flags.MinerCategory, - } // Blob transaction pool settings BlobPoolDataDirFlag = &cli.StringFlag{ Name: "blobpool.datadir", @@ -2044,11 +2039,7 @@ func setMiner(ctx *cli.Context, cfg *minerconfig.Config) { cfg.DisableVoteAttestation = true } if ctx.IsSet(MinerTxGasLimitFlag.Name) { - limit := ctx.Uint64(MinerTxGasLimitFlag.Name) - if limit != 0 && limit < params.MaxTxGas { - Fatalf("Invalid --miner.txgaslimit: %d (must be >= %d or 0)", limit, params.MaxTxGas) - } - cfg.TxGasLimit = limit + log.Warn("The flag --miner.txgaslimit is deprecated and has no effect; per-transaction gas limit is now enforced by EIP-7825") } } diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go index 1ac54c5742..004b5e792b 100644 --- a/cmd/utils/flags_legacy.go +++ b/cmd/utils/flags_legacy.go @@ -140,6 +140,13 @@ var ( Value: true, Category: flags.DeprecatedCategory, } + // Deprecated: tx gas limit is now enforced at protocol level by EIP-7825. + MinerTxGasLimitFlag = &cli.Uint64Flag{ + Name: "miner.txgaslimit", + Hidden: true, + Usage: "Deprecated: per-transaction gas limit is now enforced by EIP-7825; this flag has no effect", + Category: flags.DeprecatedCategory, + } ) // showDeprecated displays deprecated flags that will be soon removed from the codebase. diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 06f94354d9..521a2697ec 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -344,7 +344,6 @@ type BlobPool struct { head atomic.Pointer[types.Header] // Current head of the chain state *state.StateDB // Current state at the head of the chain gasTip atomic.Pointer[uint256.Int] // Currently accepted minimum gas tip - maxGas atomic.Uint64 // Currently accepted max gas, it will be modified by MinerAPI lookup *lookup // Lookup table mapping blobs to txs and txs to billy entries index map[common.Address][]*blobTxMeta // Blob transactions grouped by accounts, sorted by nonce @@ -1335,7 +1334,6 @@ func (p *BlobPool) ValidateTxBasics(tx *types.Transaction) error { MaxSize: txMaxSize, MinTip: p.gasTip.Load().ToBig(), MaxBlobCount: maxBlobsPerTx, - MaxGas: p.GetMaxGas(), } return txpool.ValidateTransaction(tx, p.head.Load(), p.signer, opts) } @@ -2159,14 +2157,6 @@ func (p *BlobPool) Status(hash common.Hash) txpool.TxStatus { return txpool.TxStatusUnknown } -func (p *BlobPool) SetMaxGas(maxGas uint64) { - p.maxGas.Store(maxGas) -} - -func (p *BlobPool) GetMaxGas() uint64 { - return p.maxGas.Load() -} - // Clear implements txpool.SubPool, removing all tracked transactions // from the blob pool and persistent store. // diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index 50f9cf4eb4..e064fc9c12 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -247,7 +247,6 @@ type LegacyPool struct { scope event.SubscriptionScope signer types.Signer mu sync.RWMutex - maxGas atomic.Uint64 // Currently accepted max gas, it will be modified by MinerAPI currentHead atomic.Pointer[types.Header] // Current head of the blockchain currentState *state.StateDB // Current state in the blockchain head @@ -623,7 +622,6 @@ func (pool *LegacyPool) ValidateTxBasics(tx *types.Transaction) error { 1< 0 && tx.Gas() > opts.MaxGas { - return fmt.Errorf("%w (cap: %d, tx: %d)", core.ErrGasLimitTooHigh, opts.MaxGas, tx.Gas()) - } - // Sanity check for extremely large numbers (supported by RLP or RPC) if tx.GasFeeCap().BitLen() > 256 { return core.ErrFeeCapVeryHigh diff --git a/eth/api_miner.go b/eth/api_miner.go index 64b3130dae..524056b289 100644 --- a/eth/api_miner.go +++ b/eth/api_miner.go @@ -20,8 +20,6 @@ import ( "math/big" "time" - "github.com/ethereum/go-ethereum/params" - "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" ) @@ -70,15 +68,6 @@ func (api *MinerAPI) SetGasPrice(gasPrice hexutil.Big) bool { return true } -// SetGasLimit sets the gaslimit to target towards during mining. -func (api *MinerAPI) SetGasLimit(gasLimit hexutil.Uint64) bool { - api.e.Miner().SetGasCeil(uint64(gasLimit)) - if uint64(gasLimit) > params.SystemTxsGasSoftLimit { - api.e.TxPool().SetMaxGas(uint64(gasLimit) - params.SystemTxsGasSoftLimit) - } - return true -} - // SetEtherbase sets the etherbase of the miner. func (api *MinerAPI) SetEtherbase(etherbase common.Address) bool { api.e.SetEtherbase(etherbase) diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 8a889b5ffb..99b9214684 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -672,12 +672,6 @@ web3._extend({ params: 1, inputFormatter: [web3._extend.utils.fromDecimal] }), - new web3._extend.Method({ - name: 'setGasLimit', - call: 'miner_setGasLimit', - params: 1, - inputFormatter: [web3._extend.utils.fromDecimal] - }), new web3._extend.Method({ name: 'setRecommitInterval', call: 'miner_setRecommitInterval', diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index e8d34c20b7..88676655a0 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -96,7 +96,6 @@ type bidSimulator struct { config *minerconfig.MevConfig delayLeftOver time.Duration minGasPrice *big.Int - txMaxGas uint64 // Maximum gas for per transaction(will be removed after Mendel hardfork) chain *core.BlockChain txpool *txpool.TxPool chainConfig *params.ChainConfig @@ -139,7 +138,6 @@ func newBidSimulator( config *minerconfig.MevConfig, delayLeftOver *time.Duration, minGasPrice *big.Int, - txMaxGas uint64, eth Backend, chainConfig *params.ChainConfig, engine consensus.Engine, @@ -148,7 +146,6 @@ func newBidSimulator( b := &bidSimulator{ config: config, minGasPrice: minGasPrice, - txMaxGas: txMaxGas, chain: eth.BlockChain(), txpool: eth.TxPool(), chainConfig: chainConfig, @@ -436,6 +433,8 @@ func (b *bidSimulator) newBidLoop() { continue } + // Pre-check before simulation for fast feedback to the builder; + // simulation would reject these txs anyway via state_transition preCheck. if errCap := b.checkIfBidExceedsTxGasLimit(newBid.bid); errCap != nil { if newBid.feedback != nil { newBid.feedback <- errCap @@ -535,29 +534,20 @@ func (b *bidSimulator) getBlockInterval(parentHeader *types.Header) uint64 { // checkIfBidExceedsTxGasLimit checks whether any transaction in the bid exceeds the max txn gas. func (b *bidSimulator) checkIfBidExceedsTxGasLimit(bid *types.Bid) error { - var gasLimitCap uint64 currentHeader := b.chain.CurrentBlock() - if b.chainConfig.IsOsaka(currentHeader.Number, currentHeader.Time) { - gasLimitCap = params.MaxTxGas - } else { - if b.txMaxGas == 0 { - return nil - } - gasLimitCap = b.txMaxGas + if !b.chainConfig.IsOsaka(currentHeader.Number, currentHeader.Time) { + return nil } - - // Scan all txs in the bid to check if any transaction exceeds the gas limit cap for _, tx := range bid.Txs { - if tx.Gas() > gasLimitCap { + if tx.Gas() > params.MaxTxGas { log.Debug("discard bid due to per-tx gas limit", "block", bid.BlockNumber, "bidHash", bid.Hash().TerminalString(), "txHash", tx.Hash().TerminalString(), "txGas", tx.Gas(), - "txGasLimit", gasLimitCap, + "txGasLimit", params.MaxTxGas, ) - - return fmt.Errorf("bid rejected: %w (cap: %d, tx: %d)", core.ErrGasLimitTooHigh, gasLimitCap, tx.Gas()) + return fmt.Errorf("bid rejected: %w (cap: %d, tx: %d)", core.ErrGasLimitTooHigh, params.MaxTxGas, tx.Gas()) } } return nil diff --git a/miner/miner.go b/miner/miner.go index 99de403eb4..3479f81dce 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -70,7 +70,7 @@ func New(eth Backend, config *minerconfig.Config, mux *event.TypeMux, engine con worker: newWorker(config, engine, eth, mux), } - miner.bidSimulator = newBidSimulator(&config.Mev, config.DelayLeftOver, config.GasPrice, config.TxGasLimit, eth, eth.BlockChain().Config(), engine, miner.worker) + miner.bidSimulator = newBidSimulator(&config.Mev, config.DelayLeftOver, config.GasPrice, eth, eth.BlockChain().Config(), engine, miner.worker) miner.worker.setBestBidFetcher(miner.bidSimulator) miner.wg.Add(1) @@ -235,7 +235,3 @@ func (miner *Miner) BuildPayload(args *BuildPayloadArgs, witness bool) (*Payload func (miner *Miner) GasCeil() uint64 { return miner.worker.getGasCeil() } - -func (miner *Miner) TxGasLimit() uint64 { - return miner.worker.getTxGasLimit() -} diff --git a/miner/minerconfig/config.go b/miner/minerconfig/config.go index 5b2df67696..2b530dad3e 100644 --- a/miner/minerconfig/config.go +++ b/miner/minerconfig/config.go @@ -68,7 +68,6 @@ type Config struct { VoteEnable bool // Whether to vote when mining MaxWaitProposalInSecs *uint64 `toml:",omitempty"` // The maximum time to wait for the proposal to be done, it's aimed to prevent validator being slashed when restarting DisableVoteAttestation bool // Whether to skip assembling vote attestation - TxGasLimit uint64 // Maximum gas for per transaction(will be removed after Mendel hardfork) Mev MevConfig // Mev configuration } diff --git a/miner/worker.go b/miner/worker.go index c275ea8f11..4b5c408ab3 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -315,12 +315,6 @@ func (w *worker) getGasCeil() uint64 { return w.config.GasCeil } -func (w *worker) getTxGasLimit() uint64 { - w.confMu.RLock() - defer w.confMu.RUnlock() - return w.config.TxGasLimit -} - // setExtra sets the content used to initialize the block extra field. func (w *worker) setExtra(extra []byte) { w.confMu.Lock() @@ -1054,10 +1048,6 @@ func (w *worker) fillTransactions(interruptCh chan int32, env *environment, stop filter.BlobFee = uint256.MustFromBig(eip4844.CalcBlobFee(w.chainConfig, env.header)) } - if cap := w.getTxGasLimit(); cap > 0 { - filter.GasLimitCap = cap - } - if w.chainConfig.IsOsaka(env.header.Number, env.header.Time) { filter.GasLimitCap = params.MaxTxGas } From 4d6b4ecd146af42dc961c82695d8cdfed80a8650 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Tue, 12 May 2026 12:00:17 +0800 Subject: [PATCH 04/48] bsc: rate-limit incoming votes by vote (#3672) count, not packet count --- eth/handler_bsc.go | 6 ++---- eth/protocols/bsc/handler.go | 5 +++++ eth/protocols/bsc/peer.go | 9 +++++---- 3 files changed, 12 insertions(+), 8 deletions(-) diff --git a/eth/handler_bsc.go b/eth/handler_bsc.go index 791c60db1e..a5cc01a0f6 100644 --- a/eth/handler_bsc.go +++ b/eth/handler_bsc.go @@ -48,11 +48,9 @@ func (h *bscHandler) Handle(peer *bsc.Peer, packet bsc.Packet) error { } // handleVotesBroadcast is invoked from a peer's message handler when it transmits a -// votes broadcast for the local node to process. +// votes broadcast for the local node to process. Per-peer rate limiting happens +// upstream in bsc.handleVotes via IsOverLimitAfterReceivingVotes. func (h *bscHandler) handleVotesBroadcast(peer *bsc.Peer, votes []*types.VoteEnvelope) error { - if peer.IsOverLimitAfterReceiving() { - return nil - } // Here we only put the first vote, to avoid ddos attack by sending a large batch of votes. // This won't abandon any valid vote, because one vote is sent every time referring to func voteBroadcastLoop if len(votes) > 0 { diff --git a/eth/protocols/bsc/handler.go b/eth/protocols/bsc/handler.go index df15894a14..ab2866719d 100644 --- a/eth/protocols/bsc/handler.go +++ b/eth/protocols/bsc/handler.go @@ -150,6 +150,11 @@ func handleVotes(backend Backend, msg Decoder, peer *Peer) error { if err := msg.Decode(ann); err != nil { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } + // Charge limiter by vote count, not packet count, to match the documented + // intent of receiveRateLimitPerSecond (see peer.go:23-27). + if peer.IsOverLimitAfterReceivingVotes(uint(len(ann.Votes))) { + return nil + } // Schedule all the unknown hashes for retrieval peer.markVotes(ann.Votes) return backend.Handle(peer, ann) diff --git a/eth/protocols/bsc/peer.go b/eth/protocols/bsc/peer.go index c74a956e86..733f5c1e90 100644 --- a/eth/protocols/bsc/peer.go +++ b/eth/protocols/bsc/peer.go @@ -124,9 +124,10 @@ func (p *Peer) AsyncSendVotes(votes []*types.VoteEnvelope) { } } -// Step into the next period when secondsPerPeriod seconds passed, -// Otherwise, check whether the number of received votes extra (secondsPerPeriod * receiveRateLimitPerSecond) -func (p *Peer) IsOverLimitAfterReceiving() bool { +// IsOverLimitAfterReceivingVotes increments the per-period vote counter by n +// and reports whether the rolling 30s budget has been exceeded. +// The budget is `secondsPerPeriod * receiveRateLimitPerSecond` votes per peer. +func (p *Peer) IsOverLimitAfterReceivingVotes(n uint) bool { if timeInterval := time.Since(p.periodBegin).Seconds(); timeInterval >= secondsPerPeriod { if p.periodCounter > uint(secondsPerPeriod*receiveRateLimitPerSecond) { p.Log().Debug("sending votes too much", "secondsPerPeriod", secondsPerPeriod, "count ", p.periodCounter) @@ -135,7 +136,7 @@ func (p *Peer) IsOverLimitAfterReceiving() bool { p.periodCounter = 0 return false } - p.periodCounter += 1 + p.periodCounter += n return p.periodCounter > uint(secondsPerPeriod*receiveRateLimitPerSecond) } From e38c766b0b0b90d419a860c6f011cc1af5e28bc2 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Tue, 12 May 2026 14:31:04 +0800 Subject: [PATCH 05/48] eth/protocols/bsc: cap GetBlocksByRange response size (#3671) --- eth/protocols/bsc/handler.go | 42 ++++++++++++++++++++++++++--------- eth/protocols/bsc/protocol.go | 8 +++++++ 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/eth/protocols/bsc/handler.go b/eth/protocols/bsc/handler.go index ab2866719d..e83ca2dd19 100644 --- a/eth/protocols/bsc/handler.go +++ b/eth/protocols/bsc/handler.go @@ -13,9 +13,20 @@ import ( "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/enr" + "github.com/ethereum/go-ethereum/rlp" ) -const MaxRequestRangeBlocksCount = 64 +const ( + // MaxRequestRangeBlocksCount is the maximum number of blocks to serve per + // GetBlocksByRange request. Mostly there to bound disk lookups; with BSC's + // typical block size, the practical limit will always be softResponseLimit. + MaxRequestRangeBlocksCount = 64 + + // softResponseLimit is the target maximum size of replies. The hard cap on + // the wire is maxMessageSize (10MB); 8MB leaves headroom for outer RLP/p2p + // framing. Each entry's measured size includes sidecars and BAL. + softResponseLimit = 8 * 1024 * 1024 +) // Handler is a callback to invoke from an outside runner after the boilerplate // exchanges have passed. @@ -173,7 +184,7 @@ func handleGetBlocksByRange(backend Backend, msg Decoder, peer *Peer) error { } // Get requested blocks - blocks := make([]*BlockData, 0, req.Count) + blocks := make([]rlp.RawValue, 0, req.Count) var block *types.Block // Prioritize blockHash query, get block & sidecars from db if req.StartBlockHash != (common.Hash{}) { @@ -184,19 +195,28 @@ func handleGetBlocksByRange(backend Backend, msg Decoder, peer *Peer) error { if block == nil { return fmt.Errorf("msg %v, cannot get start block: %v, %v", GetBlocksByRangeMsg, req.StartBlockHeight, req.StartBlockHash) } - blocks = append(blocks, NewBlockData(block)) - balSize := block.BALSize() - for i := uint64(1); i < req.Count; i++ { - block = backend.Chain().GetBlockByHash(block.ParentHash()) - if block == nil { + responseSize := 0 + for i := uint64(0); i < req.Count; i++ { + if i > 0 { + block = backend.Chain().GetBlockByHash(block.ParentHash()) + if block == nil { + break + } + } + enc, err := rlp.EncodeToBytes(NewBlockData(block)) + if err != nil { + log.Error("failed to encode BlockData", "hash", block.Hash(), "err", err) break } - balSize += block.BALSize() - blocks = append(blocks, NewBlockData(block)) + if len(blocks) > 0 && responseSize+len(enc) > softResponseLimit { + break // already have at least one block; next entry would overflow + } + blocks = append(blocks, enc) + responseSize += len(enc) } - log.Debug("reply GetBlocksByRange msg", "from", peer.id, "req", req.Count, "blocks", len(blocks), "balSize", balSize) - return p2p.Send(peer.rw, BlocksByRangeMsg, &BlocksByRangePacket{ + log.Debug("reply GetBlocksByRange msg", "from", peer.id, "req", req.Count, "blocks", len(blocks), "responseSize", responseSize) + return p2p.Send(peer.rw, BlocksByRangeMsg, &BlocksByRangeRLPPacket{ RequestId: req.RequestId, Blocks: blocks, }) diff --git a/eth/protocols/bsc/protocol.go b/eth/protocols/bsc/protocol.go index fc3eb5b709..7c86269c2e 100644 --- a/eth/protocols/bsc/protocol.go +++ b/eth/protocols/bsc/protocol.go @@ -107,3 +107,11 @@ type BlocksByRangePacket struct { func (*BlocksByRangePacket) Name() string { return "BlocksByRange" } func (*BlocksByRangePacket) Kind() byte { return BlocksByRangeMsg } + +// BlocksByRangeRLPPacket mirrors BlocksByRangePacket on the wire but carries +// pre-encoded entries, letting the server reuse RLP bytes already produced for +// size accounting and avoid a redundant encode pass in p2p.Send. +type BlocksByRangeRLPPacket struct { + RequestId uint64 + Blocks []rlp.RawValue +} From 65eb48087c7f61234a12f6c99f9458ba617462c8 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 13 May 2026 15:17:11 +0800 Subject: [PATCH 06/48] eth/filters: fix race in NewVotes and NewFinalizedHeaders (#3689) --- eth/filters/api.go | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/eth/filters/api.go b/eth/filters/api.go index 692a018413..e21c82e6f2 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -246,18 +246,20 @@ func (api *FilterAPI) NewVotes(ctx context.Context) (*rpc.Subscription, error) { return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported } - rpcSub := notifier.CreateSubscription() + var ( + rpcSub = notifier.CreateSubscription() + votes = make(chan *types.VoteEnvelope, 128) + voteSub = api.events.SubscribeNewVotes(votes) + ) gopool.Submit(func() { - votes := make(chan *types.VoteEnvelope, 128) - voteSub := api.events.SubscribeNewVotes(votes) + defer voteSub.Unsubscribe() for { select { case vote := <-votes: notifier.Notify(rpcSub.ID, vote) case <-rpcSub.Err(): - voteSub.Unsubscribe() return } } @@ -366,18 +368,20 @@ func (api *FilterAPI) NewFinalizedHeaders(ctx context.Context) (*rpc.Subscriptio return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported } - rpcSub := notifier.CreateSubscription() + var ( + rpcSub = notifier.CreateSubscription() + headers = make(chan *types.Header) + headersSub = api.events.SubscribeNewFinalizedHeaders(headers) + ) gopool.Submit(func() { - headers := make(chan *types.Header) - headersSub := api.events.SubscribeNewFinalizedHeaders(headers) + defer headersSub.Unsubscribe() for { select { case h := <-headers: notifier.Notify(rpcSub.ID, h) case <-rpcSub.Err(): - headersSub.Unsubscribe() return } } From 764f8d0e0541a553a780e6727b67e24a47278421 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Wed, 13 May 2026 15:22:54 +0800 Subject: [PATCH 07/48] miner: reduce local mining time for last block in one turn (#3669) --- consensus/parlia/parlia.go | 15 ++++++++++----- miner/worker.go | 24 ++++++++++++++++++++++-- 2 files changed, 32 insertions(+), 7 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 94eee2ca7c..c85d04355e 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1667,6 +1667,15 @@ func (p *Parlia) Authorize(val common.Address, signFn SignerFn, signTxFn SignerT p.signTxFn = signTxFn } +// IsLastBlockInTurn reports whether header is the last block in the current validator's turn. +func (p *Parlia) IsLastBlockInTurn(chain consensus.ChainReader, header *types.Header) bool { + snap, err := p.snapshot(chain, header.Number.Uint64()-1, header.ParentHash, nil) + if err != nil { + return false + } + return snap.lastBlockInOneTurn(header.Number.Uint64()) +} + // Argument leftOver is the time reserved for block finalize(calculate root, distribute income...) func (p *Parlia) Delay(chain consensus.ChainReader, header *types.Header, leftOver *time.Duration) *time.Duration { snap, err := p.snapshot(chain, header.Number.Uint64()-1, header.ParentHash, nil) @@ -1675,11 +1684,7 @@ func (p *Parlia) Delay(chain consensus.ChainReader, header *types.Header, leftOv } delay := p.delayForRamanujanFork(snap, header) - // The blocking time should be no more than half of period when snap.TurnLength == 1 - timeForMining := time.Duration(snap.BlockInterval) * time.Millisecond / 2 - if !snap.lastBlockInOneTurn(header.Number.Uint64()) { - timeForMining = time.Duration(snap.BlockInterval) * time.Millisecond - } + timeForMining := time.Duration(snap.BlockInterval) * time.Millisecond if delay > timeForMining { delay = timeForMining } diff --git a/miner/worker.go b/miner/worker.go index 4b5c408ab3..25eb7eb424 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -1198,6 +1198,26 @@ func (w *worker) generateWork(genParam *generateParams, witness bool) *newPayloa } } +// delay returns the time budget for local block building. +// For the last block in a validator's turn it caps the budget to BlockInterval/4, +// giving the next validator enough lead time to avoid producing an empty block. +// (post-Fermi: 450ms interval, ~120ms one-way p2p delay) +func (w *worker) delay(header *types.Header, leftOver *time.Duration) *time.Duration { + d := w.engine.Delay(w.chain, header, leftOver) + if d == nil { + return nil + } + if p, ok := w.engine.(*parlia.Parlia); ok && p.IsLastBlockInTurn(w.chain, header) { + blockInterval, err := p.BlockInterval(w.chain, header) + if err == nil { + if cap := time.Duration(blockInterval) * time.Millisecond / 4; *d > cap { + return &cap + } + } + } + return d +} + // commitWork generates several new sealing tasks based on the parent block // and submit them to the sealer. func (w *worker) commitWork(interruptCh chan int32, timestamp int64) { @@ -1255,7 +1275,7 @@ LOOP: prevWork = work workList = append(workList, work) - delay := w.engine.Delay(w.chain, work.header, w.config.DelayLeftOver) + delay := w.delay(work.header, w.config.DelayLeftOver) if delay == nil { log.Warn("commitWork delay is nil, something is wrong") stopTimer = nil @@ -1338,7 +1358,7 @@ LOOP: log.Debug("commitWork interruptCh closed, new block imported or resubmit triggered") return case ev := <-txsCh: - delay := w.engine.Delay(w.chain, work.header, w.config.DelayLeftOver) + delay := w.delay(work.header, w.config.DelayLeftOver) log.Debug("commitWork txsCh arrived", "fillDuration", fillDuration.String(), "delay", delay.String(), "work.tcount", work.tcount, "newTxsNum", newTxsNum, "len(ev.Txs)", len(ev.Txs)) From 5b3e195dc352292e3618a144631d20d4c3c4fbe1 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Tue, 19 May 2026 11:20:27 +0800 Subject: [PATCH 08/48] all: remove BEP-592 non-consensus block access list (#3690) --- cmd/geth/main.go | 2 +- cmd/utils/flags.go | 15 +- cmd/utils/flags_legacy.go | 8 + consensus/beacon/consensus.go | 9 - consensus/clique/clique.go | 8 - consensus/consensus.go | 6 - consensus/ethash/ethash.go | 8 - consensus/parlia/parlia.go | 65 ---- consensus/parlia/parlia_test.go | 507 +---------------------------- core/blockchain.go | 17 +- core/blockchain_insert.go | 2 +- core/blockchain_reader.go | 10 - core/rawdb/accessors_chain.go | 43 --- core/rawdb/accessors_chain_test.go | 373 --------------------- core/rawdb/schema.go | 2 + core/state/statedb.go | 110 ------- core/state_prefetcher.go | 144 -------- core/state_processor.go | 2 +- core/types.go | 2 - core/types/block.go | 159 --------- eth/backend.go | 2 - eth/ethconfig/config.go | 1 - eth/ethconfig/gen_config.go | 6 - eth/fetcher/block_fetcher.go | 2 +- eth/handler.go | 15 +- eth/handler_eth.go | 4 - eth/protocols/bsc/handler.go | 2 +- eth/protocols/bsc/protocol.go | 11 +- eth/protocols/eth/handlers.go | 7 - eth/protocols/eth/peer.go | 13 - eth/protocols/eth/protocol.go | 3 +- miner/worker.go | 9 +- node/config.go | 3 - p2p/peer.go | 3 - params/network_params.go | 3 - 35 files changed, 36 insertions(+), 1540 deletions(-) diff --git a/cmd/geth/main.go b/cmd/geth/main.go index ca111ca77b..b4d00d40c5 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -101,6 +101,7 @@ var ( utils.TxPoolLifetimeFlag, utils.TxPoolReannounceTimeFlag, utils.MinerTxGasLimitFlag, + utils.EnableBALFlag, utils.BlobPoolDataDirFlag, utils.BlobPoolDataCapFlag, utils.BlobPoolPriceBumpFlag, @@ -151,7 +152,6 @@ var ( utils.MinerRecommitIntervalFlag, utils.MinerNewPayloadTimeoutFlag, // deprecated utils.MinerDelayLeftoverFlag, - utils.EnableBALFlag, // utils.MinerNewPayloadTimeout, utils.NATFlag, utils.NoDiscoverFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 6b73c7111f..c0749f5a23 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -182,11 +182,6 @@ var ( Usage: "Chapel network: pre-configured Proof-of-Stake-Authority BSC test network", Category: flags.EthCategory, } - EnableBALFlag = &cli.BoolFlag{ - Name: "enablebal", - Usage: "Enable block access list feature, validator will generate BAL for each block", - Category: flags.EthCategory, - } // Dev mode DeveloperFlag = &cli.BoolFlag{ Name: "dev", @@ -1857,9 +1852,6 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) { if ctx.IsSet(DisableSnapProtocolFlag.Name) { cfg.DisableSnapProtocol = ctx.Bool(DisableSnapProtocolFlag.Name) } - if ctx.IsSet(EnableBALFlag.Name) { - cfg.EnableBAL = ctx.Bool(EnableBALFlag.Name) - } if ctx.IsSet(RangeLimitFlag.Name) { cfg.RangeLimit = ctx.Bool(RangeLimitFlag.Name) } @@ -2077,6 +2069,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { flags.CheckExclusive(ctx, BSCMainnetFlag, DeveloperFlag, NetworkIdFlag, OverrideGenesisFlag) flags.CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer + if ctx.IsSet(EnableBALFlag.Name) { + log.Warn("The flag --enable-bal is deprecated and has no effect; BEP-592 block access list has been removed") + } // Set configurations from CLI flags setEtherbase(ctx, cfg) setGPO(ctx, &cfg.GPO) @@ -2162,9 +2157,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) { if ctx.IsSet(CacheNoPrefetchFlag.Name) { cfg.NoPrefetch = ctx.Bool(CacheNoPrefetchFlag.Name) } - if ctx.IsSet(EnableBALFlag.Name) { - cfg.EnableBAL = ctx.Bool(EnableBALFlag.Name) - } // Read the value from the flag no matter if it's set or not. cfg.Preimages = ctx.Bool(CachePreimagesFlag.Name) if cfg.NoPruning && !cfg.Preimages { @@ -2883,7 +2875,6 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh options := &core.BlockChainConfig{ TrieCleanLimit: ethconfig.Defaults.TrieCleanCache, NoPrefetch: ctx.Bool(CacheNoPrefetchFlag.Name), - EnableBAL: ctx.Bool(EnableBALFlag.Name), TrieDirtyLimit: ethconfig.Defaults.TrieDirtyCache, ArchiveMode: ctx.String(GCModeFlag.Name) == "archive", TrieTimeLimit: ethconfig.Defaults.TrieTimeout, diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go index 004b5e792b..45ab6a31b8 100644 --- a/cmd/utils/flags_legacy.go +++ b/cmd/utils/flags_legacy.go @@ -47,6 +47,7 @@ var DeprecatedFlags = []cli.Flag{ PruneAncientDataFlag, JournalFileFlag, LogExportCheckpointsFlag, + EnableBALFlag, } var ( @@ -147,6 +148,13 @@ var ( Usage: "Deprecated: per-transaction gas limit is now enforced by EIP-7825; this flag has no effect", Category: flags.DeprecatedCategory, } + // Deprecated: BEP-592 non-consensus BAL is superseded by EIP-7928 in upstream go-ethereum. + EnableBALFlag = &cli.BoolFlag{ + Name: "enable-bal", + Hidden: true, + Usage: "Deprecated: BEP-592 block access list has been removed; this flag has no effect", + Category: flags.DeprecatedCategory, + } ) // showDeprecated displays deprecated flags that will be soon removed from the codebase. diff --git a/consensus/beacon/consensus.go b/consensus/beacon/consensus.go index 9d631beb70..200459b301 100644 --- a/consensus/beacon/consensus.go +++ b/consensus/beacon/consensus.go @@ -468,15 +468,6 @@ func (beacon *Beacon) SealHash(header *types.Header) common.Hash { return beacon.ethone.SealHash(header) } -func (beacon *Beacon) SignBAL(blockAccessList *types.BlockAccessListEncode) error { - return nil -} - -// VerifyBAL verifies the BAL of the block -func (beacon *Beacon) VerifyBAL(block *types.Block, bal *types.BlockAccessListEncode) error { - return nil -} - // CalcDifficulty is the difficulty adjustment algorithm. It returns // the difficulty that a new block should have when created at time // given the parent block's time and difficulty. diff --git a/consensus/clique/clique.go b/consensus/clique/clique.go index 411ddc5fd4..7e5e85c578 100644 --- a/consensus/clique/clique.go +++ b/consensus/clique/clique.go @@ -787,11 +787,3 @@ func encodeSigHeader(w io.Writer, header *types.Header) { panic("can't encode: " + err.Error()) } } - -func (c *Clique) SignBAL(bal *types.BlockAccessListEncode) error { - return nil -} - -func (c *Clique) VerifyBAL(block *types.Block, bal *types.BlockAccessListEncode) error { - return nil -} diff --git a/consensus/consensus.go b/consensus/consensus.go index f90f708a55..63a5719f5d 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -133,12 +133,6 @@ type Engine interface { // SealHash returns the hash of a block prior to it being sealed. SealHash(header *types.Header) common.Hash - // SignBAL signs the BAL of the block - SignBAL(blockAccessList *types.BlockAccessListEncode) error - - // VerifyBAL verifies the BAL of the block - VerifyBAL(block *types.Block, bal *types.BlockAccessListEncode) error - // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty // that a new block should have. CalcDifficulty(chain ChainHeaderReader, time uint64, parent *types.Header) *big.Int diff --git a/consensus/ethash/ethash.go b/consensus/ethash/ethash.go index 3027898981..f624f73875 100644 --- a/consensus/ethash/ethash.go +++ b/consensus/ethash/ethash.go @@ -76,11 +76,3 @@ func (ethash *Ethash) Close() error { func (ethash *Ethash) Seal(chain consensus.ChainHeaderReader, block *types.Block, results chan<- *types.Block, stop <-chan struct{}) error { panic("ethash (pow) sealing not supported any more") } - -func (ethash *Ethash) SignBAL(bal *types.BlockAccessListEncode) error { - return nil -} - -func (ethash *Ethash) VerifyBAL(block *types.Block, bal *types.BlockAccessListEncode) error { - return nil -} diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index c85d04355e..4e79dfe413 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -1790,71 +1790,6 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res return nil } -func (p *Parlia) SignBAL(blockAccessList *types.BlockAccessListEncode) error { - p.lock.RLock() - val, signFn := p.val, p.signFn - p.lock.RUnlock() - - data, err := rlp.EncodeToBytes([]interface{}{blockAccessList.Version, blockAccessList.Number, blockAccessList.Hash, blockAccessList.Accounts}) - if err != nil { - log.Error("Encode to bytes failed when sealing", "err", err) - return errors.New("encode to bytes failed") - } - - if len(data) > int(params.MaxBALSize) { - log.Error("data is too large", "dataSize", len(data), "maxSize", params.MaxBALSize) - return errors.New("data is too large") - } - - sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, data) - if err != nil { - log.Error("Sign for the block header failed when sealing", "err", err) - return errors.New("sign for the block header failed") - } - - copy(blockAccessList.SignData, sig) - return nil -} - -func (p *Parlia) VerifyBAL(block *types.Block, bal *types.BlockAccessListEncode) error { - if bal.Version != 0 { - log.Error("invalid BAL version", "version", bal.Version) - return errors.New("invalid BAL version") - } - - if len(bal.SignData) != 65 { - log.Error("invalid BAL signature", "signatureSize", len(bal.SignData)) - return errors.New("invalid BAL signature") - } - - // Recover the public key and the Ethereum address - data, err := rlp.EncodeToBytes([]interface{}{bal.Version, block.Number(), block.Hash(), bal.Accounts}) - if err != nil { - log.Error("encode to bytes failed", "err", err) - return errors.New("encode to bytes failed") - } - - if len(data) > int(params.MaxBALSize) { - log.Error("data is too large", "dataSize", len(data), "maxSize", params.MaxBALSize) - return errors.New("data is too large") - } - - pubkey, err := crypto.Ecrecover(crypto.Keccak256(data), bal.SignData) - if err != nil { - return err - } - var pubkeyAddr common.Address - copy(pubkeyAddr[:], crypto.Keccak256(pubkey[1:])[12:]) - - signer := block.Header().Coinbase - if signer != pubkeyAddr { - log.Error("BAL signer mismatch", "signer", signer, "pubkeyAddr", pubkeyAddr, "bal.Number", bal.Number, "bal.Hash", bal.Hash) - return errors.New("signer mismatch") - } - - return nil -} - func (p *Parlia) shouldWaitForCurrentBlockProcess(chain consensus.ChainHeaderReader, header *types.Header, snap *Snapshot) bool { if header.Difficulty.Cmp(diffInTurn) == 0 { return false diff --git a/consensus/parlia/parlia_test.go b/consensus/parlia/parlia_test.go index 92b3691613..7b7b50a6ea 100644 --- a/consensus/parlia/parlia_test.go +++ b/consensus/parlia/parlia_test.go @@ -10,7 +10,6 @@ import ( "strings" "testing" - "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" cmath "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" @@ -619,16 +618,15 @@ func TestSimulateP2P(t *testing.T) { if err != nil { t.Fatalf("[Testcase %d] simulate P2P error: %v", index, err) } - /* - for _, val := range c.validators { - t.Logf("[Testcase %d] validator(%d) head block: %d", - index, val.index, val.head.blockNumber) - t.Logf("[Testcase %d] validator(%d) highest justified block: %d", - index, val.index, val.head.GetJustifiedNumber()) - t.Logf("[Testcase %d] validator(%d) highest finalized block: %d", - index, val.index, val.head.GetFinalizedBlock().blockNumber) - } - */ + for _, val := range c.validators { + t.Logf("[Testcase %d] validator(%d) head block: %d", + index, val.index, val.head.blockNumber) + t.Logf("[Testcase %d] validator(%d) highest justified block: %d", + index, val.index, val.head.GetJustifiedNumber()) + t.Logf("[Testcase %d] validator(%d) highest finalized block: %d", + index, val.index, val.head.GetFinalizedBlock().blockNumber) + } + if c.CheckChain() == false { t.Fatalf("[Testcase %d] chain not works as expected", index) } @@ -860,490 +858,3 @@ func (c *mockParlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, head func (c *mockParlia) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, parent *types.Header) *big.Int { return big.NewInt(1) } - -func TestSignBAL(t *testing.T) { - // Setup test environment - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - - // Create mock signing function that succeeds - mockSignFn := func(account accounts.Account, mimeType string, data []byte) ([]byte, error) { - if account.Address != addr { - return nil, fmt.Errorf("wrong address") - } - if mimeType != accounts.MimetypeParlia { - return nil, fmt.Errorf("wrong mime type") - } - // Return a dummy 65-byte signature - sig := make([]byte, 65) - copy(sig, []byte("test_signature_data_for_testing_purposes_123456789012345678901234")) - return sig, nil - } - - // Create Parlia instance - parlia := &Parlia{ - val: addr, - signFn: mockSignFn, - } - - tests := []struct { - name string - bal *types.BlockAccessListEncode - expectedError bool - signFn SignerFn - description string - }{ - { - name: "successful signing", - bal: &types.BlockAccessListEncode{ - Version: 0, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1234567890123456789012345678901234567890"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - }, - }, - }, - }, - expectedError: false, - signFn: mockSignFn, - description: "Should successfully sign a valid BlockAccessListEncode", - }, - { - name: "signing function error", - bal: &types.BlockAccessListEncode{ - Version: 0, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{}, - }, - expectedError: true, - signFn: func(account accounts.Account, mimeType string, data []byte) ([]byte, error) { - return nil, fmt.Errorf("signing failed") - }, - description: "Should return error when signing function fails", - }, - { - name: "empty accounts list", - bal: &types.BlockAccessListEncode{ - Version: 0, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{}, - }, - expectedError: false, - signFn: mockSignFn, - description: "Should successfully sign even with empty accounts list", - }, - { - name: "multiple accounts", - bal: &types.BlockAccessListEncode{ - Version: 2, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1111111111111111111111111111111111111111"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - {Key: common.HexToHash("0x02"), TxIndex: 1, Dirty: true}, - }, - }, - { - Address: common.HexToAddress("0x2222222222222222222222222222222222222222"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x03"), TxIndex: 2, Dirty: false}, - }, - }, - }, - }, - expectedError: false, - signFn: mockSignFn, - description: "Should successfully sign with multiple accounts", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Set up Parlia with the test signing function - parlia.signFn = tt.signFn - - // Call SignBAL - err := parlia.SignBAL(tt.bal) - - // Check results - if tt.expectedError { - if err == nil { - t.Errorf("Expected error but got none. %s", tt.description) - } - } else { - if err != nil { - t.Errorf("Expected no error but got: %v. %s", err, tt.description) - } - // Verify signature was copied to SignData - if tt.bal != nil && len(tt.bal.SignData) != 65 { - t.Errorf("Expected SignData to be 65 bytes, got %d", len(tt.bal.SignData)) - } - // Verify signature content (for successful cases) - if tt.bal != nil && !tt.expectedError { - expectedSig := "test_signature_data_for_testing_purposes_123456789012345678901234" - if string(tt.bal.SignData[:len(expectedSig)]) != expectedSig { - t.Errorf("SignData was not properly set") - } - } - } - }) - } -} - -func TestVerifyBAL(t *testing.T) { - // Setup test environment - signerKey, _ := crypto.GenerateKey() - signerAddr := crypto.PubkeyToAddress(signerKey.PublicKey) - - // Helper function to create a properly signed BAL - createBlockWithBAL := func(addr common.Address, version uint32, signLength int, accounts []types.AccountAccessListEncode) *types.Block { - header := &types.Header{ - ParentHash: types.EmptyRootHash, - Number: big.NewInt(10), - Coinbase: addr, - } - block := types.NewBlock(header, nil, nil, nil) - bal := &types.BlockAccessListEncode{ - Version: version, - Number: block.Number().Uint64(), - Hash: block.Hash(), - SignData: make([]byte, signLength), - Accounts: accounts, - } - - // RLP encode the data - data, _ := rlp.EncodeToBytes([]interface{}{bal.Version, bal.Number, bal.Hash, bal.Accounts}) - - // Create signature using the test key - hash := crypto.Keccak256(data) - sig, _ := crypto.Sign(hash, signerKey) - copy(bal.SignData, sig) - block = block.WithBAL(bal) - return block - } - - // Create a Parlia instance - parlia := &Parlia{} - - tests := []struct { - name string - block *types.Block - expectedError bool - description string - }{ - { - name: "valid signature verification", - block: createBlockWithBAL(signerAddr, 0, 65, []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1234567890123456789012345678901234567890"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - }, - }, - }), - expectedError: false, - description: "Should successfully verify a properly signed BAL", - }, - { - name: "invalid version", - block: createBlockWithBAL(signerAddr, 1, 65, []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1234567890123456789012345678901234567890"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - }, - }, - }), - expectedError: true, - description: "Should fail when version is invalid", - }, - { - name: "invalid signature length - too short", - block: createBlockWithBAL(signerAddr, 0, 64, []types.AccountAccessListEncode{}), - expectedError: true, - description: "Should fail when signature is too short", - }, - { - name: "invalid signature length - too long", - block: createBlockWithBAL(signerAddr, 0, 66, []types.AccountAccessListEncode{}), - expectedError: true, - description: "Should fail when signature is too long", - }, - { - name: "empty signature", - block: createBlockWithBAL(signerAddr, 0, 0, []types.AccountAccessListEncode{}), - expectedError: true, - description: "Should fail with empty signature", - }, - { - name: "signer mismatch", - block: createBlockWithBAL(common.HexToAddress("0x1234567890123456789012345678901234567890"), 0, 65, []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1234567890123456789012345678901234567890"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - }, - }, - }), - expectedError: true, - description: "Should fail when signer address doesn't match recovered address", - }, - { - name: "empty accounts list", - block: createBlockWithBAL(signerAddr, 0, 65, []types.AccountAccessListEncode{}), - expectedError: false, - description: "Should successfully verify BAL with empty accounts", - }, - { - name: "multiple accounts", - block: createBlockWithBAL(signerAddr, 0, 65, []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1111111111111111111111111111111111111111"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - {Key: common.HexToHash("0x02"), TxIndex: 1, Dirty: true}, - }, - }, - { - Address: common.HexToAddress("0x2222222222222222222222222222222222222222"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x03"), TxIndex: 2, Dirty: false}, - }, - }, - }), - expectedError: false, - description: "Should successfully verify BAL with multiple accounts", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - err := parlia.VerifyBAL(tt.block, tt.block.BAL()) - if tt.expectedError { - if err == nil { - t.Errorf("Expected error but got none. %s", tt.description) - } - } else { - if err != nil { - t.Errorf("Expected no error but got: %v. %s", err, tt.description) - } - } - }) - } -} - -func TestVerifyBAL_EdgeCases(t *testing.T) { - // Test with different key to ensure proper signature verification - key1, _ := crypto.GenerateKey() - key2, _ := crypto.GenerateKey() - addr1 := crypto.PubkeyToAddress(key1.PublicKey) - addr2 := crypto.PubkeyToAddress(key2.PublicKey) - - parlia := &Parlia{} - - header1 := &types.Header{ - ParentHash: types.EmptyRootHash, - Number: big.NewInt(10), - Coinbase: addr1, - } - block1 := types.NewBlock(header1, nil, nil, nil) - // Create BAL signed with key1 - bal := &types.BlockAccessListEncode{ - Version: 0, - Number: block1.Number().Uint64(), - Hash: block1.Hash(), - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1234567890123456789012345678901234567890"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - }, - }, - }, - } - - // Sign with key1 - data, _ := rlp.EncodeToBytes([]interface{}{bal.Version, bal.Number, bal.Hash, bal.Accounts}) - hash := crypto.Keccak256(data) - sig, _ := crypto.Sign(hash, key1) - copy(bal.SignData, sig) - - // Should succeed with addr1 - err := parlia.VerifyBAL(block1, bal) - if err != nil { - t.Errorf("Verification with correct signer failed: %v", err) - } - - // Should fail with addr2 (different key) - header2 := &types.Header{ - ParentHash: types.EmptyRootHash, - Number: big.NewInt(10), - Coinbase: addr2, - } - block2 := types.NewBlock(header2, nil, nil, nil) - err = parlia.VerifyBAL(block2, bal) - if err == nil { - t.Error("Expected verification to fail with different signer address") - } -} - -func TestVerifyBAL_TooLargeData(t *testing.T) { - // Test with large amount of data to ensure RLP encoding works correctly - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - parlia := &Parlia{} - - // Create BAL with many accounts - accounts := make([]types.AccountAccessListEncode, 20000) - for i := 0; i < 20000; i++ { - accounts[i] = types.AccountAccessListEncode{ - Address: common.BigToAddress(big.NewInt(int64(i))), - StorageItems: []types.StorageAccessItem{ - {Key: common.BigToHash(big.NewInt(int64(i))), TxIndex: uint32(i), Dirty: i%2 == 0}, - {Key: common.BigToHash(big.NewInt(int64(i + 1000))), TxIndex: uint32(i + 1), Dirty: i%3 == 0}, - }, - } - } - - header := &types.Header{ - ParentHash: types.EmptyRootHash, - Number: big.NewInt(10), - Coinbase: addr, - } - block := types.NewBlock(header, nil, nil, nil) - bal := &types.BlockAccessListEncode{ - Version: 0, - Number: block.Number().Uint64(), - Hash: block.Hash(), - SignData: make([]byte, 65), - Accounts: accounts, - } - - // Sign the large data - data, err := rlp.EncodeToBytes([]interface{}{bal.Version, bal.Number, bal.Hash, bal.Accounts}) - if err != nil { - t.Fatalf("Failed to RLP encode large data: %v", err) - } - - hash := crypto.Keccak256(data) - sig, err := crypto.Sign(hash, key) - if err != nil { - t.Fatalf("Failed to sign large data: %v", err) - } - copy(bal.SignData, sig) - - // Verify the signature - err = parlia.VerifyBAL(block, bal) - if err.Error() != "data is too large" { - t.Errorf("Failed to verify BAL with large data: %v", err) - } -} - -func TestSignBAL_VerifyBAL_Integration(t *testing.T) { - // Test complete sign-verify cycle - key, _ := crypto.GenerateKey() - addr := crypto.PubkeyToAddress(key.PublicKey) - - // Create mock signing function - mockSignFn := func(account accounts.Account, mimeType string, data []byte) ([]byte, error) { - if account.Address != addr { - return nil, fmt.Errorf("wrong address") - } - if mimeType != accounts.MimetypeParlia { - return nil, fmt.Errorf("wrong mime type") - } - // Use the actual private key to sign - hash := crypto.Keccak256(data) - return crypto.Sign(hash, key) - } - - parlia := &Parlia{ - val: addr, - signFn: mockSignFn, - } - - testCases := []struct { - name string - version uint32 - accounts []types.AccountAccessListEncode - }{ - { - name: "empty accounts", - version: 0, - accounts: []types.AccountAccessListEncode{}, - }, - { - name: "single account", - version: 0, - accounts: []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1234567890123456789012345678901234567890"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - {Key: common.HexToHash("0x02"), TxIndex: 1, Dirty: true}, - }, - }, - }, - }, - { - name: "multiple accounts", - version: 0, - accounts: []types.AccountAccessListEncode{ - { - Address: common.HexToAddress("0x1111111111111111111111111111111111111111"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - }, - }, - { - Address: common.HexToAddress("0x2222222222222222222222222222222222222222"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x02"), TxIndex: 1, Dirty: true}, - {Key: common.HexToHash("0x03"), TxIndex: 2, Dirty: false}, - }, - }, - }, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - header := &types.Header{ - ParentHash: types.EmptyRootHash, - Number: big.NewInt(10), - Coinbase: addr, - } - block := types.NewBlock(header, nil, nil, nil) - // Create BAL - bal := &types.BlockAccessListEncode{ - Version: tc.version, - Number: block.Number().Uint64(), - Hash: block.Hash(), - SignData: make([]byte, 65), - Accounts: tc.accounts, - } - - // Sign the BAL - err := parlia.SignBAL(bal) - if err != nil { - t.Fatalf("SignBAL failed: %v", err) - } - - // Verify signature length - if len(bal.SignData) != 65 { - t.Errorf("Expected SignData to be 65 bytes, got %d", len(bal.SignData)) - } - - // Verify the BAL with correct signer - err = parlia.VerifyBAL(block, bal) - if err != nil { - t.Errorf("VerifyBAL failed with correct signer: %v", err) - } - }) - } -} diff --git a/core/blockchain.go b/core/blockchain.go index 6150fa2fc8..dc98248bf4 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -230,9 +230,6 @@ type BlockChainConfig struct { // StateSizeTracking indicates whether the state size tracking is enabled. StateSizeTracking bool - - // EnableBAL enables the block access list feature - EnableBAL bool } // DefaultConfig returns the default config. @@ -1314,7 +1311,6 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, time uint64, root common.Ha rawdb.DeleteReceipts(db, hash, num) rawdb.DeleteTd(db, hash, num) rawdb.DeleteBlobSidecars(db, hash, num) - rawdb.DeleteBAL(db, hash, num) } // Todo(rjl493456442) txlookup, log index, etc } @@ -1823,7 +1819,6 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [ if bc.chainConfig.IsCancun(block.Number(), block.Time()) { rawdb.WriteBlobSidecars(batch, block.Hash(), block.NumberU64(), block.Sidecars()) } - rawdb.WriteBAL(batch, block.Hash(), block.NumberU64(), block.BAL()) // Write everything belongs to the blocks into the database. So that // we can ensure all components of body is completed(body, receipts) @@ -1902,7 +1897,6 @@ func (bc *BlockChain) writeBlockWithoutState(block *types.Block, td *big.Int) (e if bc.chainConfig.IsCancun(block.Number(), block.Time()) { rawdb.WriteBlobSidecars(blockBatch, block.Hash(), block.NumberU64(), block.Sidecars()) } - rawdb.WriteBAL(blockBatch, block.Hash(), block.NumberU64(), block.BAL()) if err := blockBatch.Write(); err != nil { log.Crit("Failed to write block into disk", "err", err) } @@ -1949,7 +1943,6 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. if bc.chainConfig.IsCancun(block.Number(), block.Time()) { rawdb.WriteBlobSidecars(blockBatch, block.Hash(), block.NumberU64(), block.Sidecars()) } - rawdb.WriteBAL(blockBatch, block.Hash(), block.NumberU64(), block.BAL()) if bc.db.HasSeparateStateStore() { rawdb.WritePreimages(bc.db.GetStateStore(), statedb.Preimages()) } else { @@ -2519,7 +2512,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s defer interrupt.Store(true) // terminate the prefetch at the end needBadSharedStorage := bc.chainConfig.NeedBadSharedStorage(block.Number()) - needPrefetch := needBadSharedStorage || (!bc.cfg.NoPrefetch && len(block.Transactions()) >= prefetchTxNumber) || block.BAL() != nil + needPrefetch := needBadSharedStorage || (!bc.cfg.NoPrefetch && len(block.Transactions()) >= prefetchTxNumber) if !needPrefetch { statedb, err = state.New(parentRoot, bc.statedb) if err != nil { @@ -2557,17 +2550,11 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s storageCacheMissMeter.Mark(stats.StorageMiss) }() - interruptChan := make(chan struct{}) - defer close(interruptChan) go func(start time.Time, throwaway *state.StateDB, block *types.Block) { // Disable tracing for prefetcher executions. vmCfg := bc.cfg.VmConfig vmCfg.Tracer = nil - if block.BAL() != nil { - bc.prefetcher.PrefetchBAL(block, throwaway, interruptChan) - } else { - bc.prefetcher.Prefetch(block.Transactions(), block.Header(), block.GasLimit(), throwaway, vmCfg, &interrupt) - } + bc.prefetcher.Prefetch(block.Transactions(), block.Header(), block.GasLimit(), throwaway, vmCfg, &interrupt) blockPrefetchExecuteTimer.Update(time.Since(start)) if interrupt.Load() { diff --git a/core/blockchain_insert.go b/core/blockchain_insert.go index acfa58d3c6..550bd192ea 100644 --- a/core/blockchain_insert.go +++ b/core/blockchain_insert.go @@ -62,7 +62,7 @@ func (st *insertStats) report(chain []*types.Block, index int, snapDiffItems, sn context := []interface{}{ "number", end.Number(), "hash", end.Hash(), "miner", end.Coinbase(), "blocks", st.processed, "txs", txs, "blobs", blobs, "mgas", float64(st.usedGas) / 1000000, - "elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps, "BAL", end.BAL() != nil, + "elapsed", common.PrettyDuration(elapsed), "mgasps", mgasps, } blockInsertMgaspsGauge.Update(int64(mgasps)) if timestamp := time.Unix(int64(end.Time()), 0); time.Since(timestamp) > time.Minute { diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index 26ae7c7b8a..72c0ab9571 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -213,10 +213,6 @@ func (bc *BlockChain) GetBlock(hash common.Hash, number uint64) *types.Block { sidecars := rawdb.ReadBlobSidecars(bc.db, hash, number) block = block.WithSidecars(sidecars) - bal := rawdb.ReadBAL(bc.db, hash, number) - if bal != nil { - block = block.WithBAL(bal) - } // Cache the found block for next time and return bc.blockCache.Add(block.Hash(), block) return block @@ -490,9 +486,6 @@ func (bc *BlockChain) State() (*state.StateDB, error) { // StateAt returns a new mutable state based on a particular point in time. func (bc *BlockChain) StateAt(root common.Hash) (*state.StateDB, error) { stateDb, err := state.New(root, bc.statedb) - if bc.cfg.EnableBAL { - stateDb.InitBlockAccessList() - } if err != nil { return nil, err } @@ -515,9 +508,6 @@ func (bc *BlockChain) StateWithCacheAt(root common.Hash) (*state.StateDB, error) return nil, err } stateDb, err := state.NewWithReader(root, bc.statedb, process) - if bc.cfg.EnableBAL { - stateDb.InitBlockAccessList() - } if err != nil { return nil, err } diff --git a/core/rawdb/accessors_chain.go b/core/rawdb/accessors_chain.go index cf8bc994a4..e6cc71ade6 100644 --- a/core/rawdb/accessors_chain.go +++ b/core/rawdb/accessors_chain.go @@ -951,47 +951,6 @@ func DeleteBlobSidecars(db ethdb.KeyValueWriter, hash common.Hash, number uint64 } } -// ReadBALRLP retrieves all the block access list belonging to a block in RLP encoding. -func ReadBALRLP(db ethdb.Reader, hash common.Hash, number uint64) rlp.RawValue { - // BAL is only in kv DB, will not be put into ancient DB - data, _ := db.Get(blockBALKey(number, hash)) - return data -} - -// ReadBAL retrieves the block access list belonging to a block. -func ReadBAL(db ethdb.Reader, hash common.Hash, number uint64) *types.BlockAccessListEncode { - data := ReadBALRLP(db, hash, number) - if len(data) == 0 { - return nil - } - var ret types.BlockAccessListEncode - if err := rlp.DecodeBytes(data, &ret); err != nil { - log.Error("Invalid BAL RLP", "hash", hash, "err", err) - return nil - } - return &ret -} - -func WriteBAL(db ethdb.KeyValueWriter, hash common.Hash, number uint64, bal *types.BlockAccessListEncode) { - if bal == nil { - return - } - data, err := rlp.EncodeToBytes(bal) - if err != nil { - log.Crit("Failed to encode block BAL", "err", err) - } - - if err := db.Put(blockBALKey(number, hash), data); err != nil { - log.Crit("Failed to store block BAL", "err", err) - } -} - -func DeleteBAL(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { - if err := db.Delete(blockBALKey(number, hash)); err != nil { - log.Crit("Failed to delete block BAL", "err", err) - } -} - // WriteAncientHeaderChain writes the supplied headers along with nil block // bodies and receipts into the ancient store. It's supposed to be used for // storing chain segment before the chain cutoff. @@ -1034,7 +993,6 @@ func DeleteBlock(db ethdb.KeyValueWriter, hash common.Hash, number uint64) { DeleteBody(db, hash, number) DeleteTd(db, hash, number) DeleteBlobSidecars(db, hash, number) // it is safe to delete non-exist blob - DeleteBAL(db, hash, number) } // DeleteBlockWithoutNumber removes all block data associated with a hash, except @@ -1045,7 +1003,6 @@ func DeleteBlockWithoutNumber(db ethdb.KeyValueWriter, hash common.Hash, number DeleteBody(db, hash, number) DeleteTd(db, hash, number) DeleteBlobSidecars(db, hash, number) - DeleteBAL(db, hash, number) } const badBlockToKeep = 10 diff --git a/core/rawdb/accessors_chain_test.go b/core/rawdb/accessors_chain_test.go index c23c338fef..7e6ec34b76 100644 --- a/core/rawdb/accessors_chain_test.go +++ b/core/rawdb/accessors_chain_test.go @@ -1122,376 +1122,3 @@ func TestHeadersRLPStorage(t *testing.T) { checkSequence(1, 1) // Only block 1 checkSequence(1, 2) // Genesis + block 1 } - -// Tests BAL (Block Access List) storage and retrieval operations. -func TestBALStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Create test BAL data - bal := &types.BlockAccessListEncode{ - Version: 1, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{ - { - TxIndex: 0, - Address: common.HexToAddress("0x1234567890123456789012345678901234567890"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - {Key: common.HexToHash("0x02"), TxIndex: 1, Dirty: true}, - }, - }, - { - TxIndex: 1, - Address: common.HexToAddress("0x2222222222222222222222222222222222222222"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x03"), TxIndex: 2, Dirty: false}, - }, - }, - }, - } - - // Fill SignData with test data - copy(bal.SignData, []byte("test_signature_data_for_bal_testing_12345678901234567890123456789")) - - hash := common.HexToHash("0x123456789abcdef") - number := uint64(42) - - // Test non-existent BAL retrieval - if entry := ReadBAL(db, hash, number); entry != nil { - t.Fatalf("Non-existent BAL returned: %v", entry) - } - if entry := ReadBALRLP(db, hash, number); len(entry) != 0 { - t.Fatalf("Non-existent raw BAL returned: %v", entry) - } - - // Test BAL storage and retrieval - WriteBAL(db, hash, number, bal) - if entry := ReadBAL(db, hash, number); entry == nil { - t.Fatalf("Stored BAL not found") - } else if !balEqual(entry, bal) { - t.Fatalf("Retrieved BAL mismatch: have %v, want %v", entry, bal) - } - - // Test raw BAL retrieval - if entry := ReadBALRLP(db, hash, number); len(entry) == 0 { - t.Fatalf("Stored raw BAL not found") - } - - // Test BAL deletion - DeleteBAL(db, hash, number) - if entry := ReadBAL(db, hash, number); entry != nil { - t.Fatalf("Deleted BAL still returned: %v", entry) - } - if entry := ReadBALRLP(db, hash, number); len(entry) != 0 { - t.Fatalf("Deleted raw BAL still returned: %v", entry) - } -} - -func TestBALRLPStorage(t *testing.T) { - db := NewMemoryDatabase() - - // Test different BAL configurations - testCases := []struct { - name string - bal *types.BlockAccessListEncode - hash common.Hash - number uint64 - }{ - { - name: "empty accounts", - bal: &types.BlockAccessListEncode{ - Version: 0, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{}, - }, - hash: common.HexToHash("0x1111"), - number: 1, - }, - { - name: "single account with multiple storage items", - bal: &types.BlockAccessListEncode{ - Version: 2, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{ - { - TxIndex: 0, - Address: common.HexToAddress("0xabcdefabcdefabcdefabcdefabcdefabcdefabcd"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x0a"), TxIndex: 0, Dirty: true}, - {Key: common.HexToHash("0x0b"), TxIndex: 1, Dirty: false}, - {Key: common.HexToHash("0x0c"), TxIndex: 2, Dirty: true}, - }, - }, - }, - }, - hash: common.HexToHash("0x2222"), - number: 2, - }, - { - name: "multiple accounts", - bal: &types.BlockAccessListEncode{ - Version: ^uint32(0), // Max uint32 value - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{ - { - TxIndex: 0, - Address: common.HexToAddress("0x1111111111111111111111111111111111111111"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - }, - }, - { - TxIndex: 1, - Address: common.HexToAddress("0x3333333333333333333333333333333333333333"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x04"), TxIndex: 3, Dirty: true}, - {Key: common.HexToHash("0x05"), TxIndex: 4, Dirty: false}, - }, - }, - { - TxIndex: 2, - Address: common.HexToAddress("0x4444444444444444444444444444444444444444"), - StorageItems: []types.StorageAccessItem{}, - }, - }, - }, - hash: common.HexToHash("0x3333"), - number: 100, - }, - } - - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Fill SignData with unique test data - sigData := fmt.Sprintf("test_signature_for_%s_123456789012345678901234567890123456789012345678901234567890", tc.name) - copy(tc.bal.SignData, []byte(sigData)) - - // Store BAL - WriteBAL(db, tc.hash, tc.number, tc.bal) - - // Test RLP retrieval - rawData := ReadBALRLP(db, tc.hash, tc.number) - if len(rawData) == 0 { - t.Fatalf("Failed to store/retrieve raw BAL data") - } - - // Test structured retrieval - retrieved := ReadBAL(db, tc.hash, tc.number) - if retrieved == nil { - t.Fatalf("Failed to retrieve structured BAL") - } - - // Compare values - if !balEqual(retrieved, tc.bal) { - t.Fatalf("Retrieved BAL doesn't match stored BAL") - } - - // Test deletion - DeleteBAL(db, tc.hash, tc.number) - if ReadBAL(db, tc.hash, tc.number) != nil { - t.Fatalf("BAL not properly deleted") - } - }) - } -} - -func TestBALCorruptedData(t *testing.T) { - db := NewMemoryDatabase() - hash := common.HexToHash("0x9999") - number := uint64(123) - - // Store corrupted RLP data directly - corruptedData := []byte{0xff, 0xff, 0xff, 0xff} // Invalid RLP - if err := db.Put(blockBALKey(number, hash), corruptedData); err != nil { - t.Fatalf("Failed to store corrupted data: %v", err) - } - - // ReadBALRLP should return the corrupted data - rawData := ReadBALRLP(db, hash, number) - if !bytes.Equal(rawData, corruptedData) { - t.Fatalf("ReadBALRLP should return raw data even if corrupted") - } - - // ReadBAL should return nil for corrupted data - bal := ReadBAL(db, hash, number) - if bal != nil { - t.Fatalf("ReadBAL should return nil for corrupted data, got: %v", bal) - } -} - -func TestBALLargeData(t *testing.T) { - db := NewMemoryDatabase() - - // Create BAL with large amount of data - accounts := make([]types.AccountAccessListEncode, 1000) - for i := 0; i < 1000; i++ { - storageItems := make([]types.StorageAccessItem, 10) - for j := 0; j < 10; j++ { - storageItems[j] = types.StorageAccessItem{ - Key: common.BigToHash(big.NewInt(int64(i*10 + j))), - TxIndex: uint32(i*10 + j), - Dirty: (i+j)%2 == 0, - } - } - accounts[i] = types.AccountAccessListEncode{ - TxIndex: uint32(i), - Address: common.BigToAddress(big.NewInt(int64(i))), - StorageItems: storageItems, - } - } - - bal := &types.BlockAccessListEncode{ - Version: 12345, - SignData: make([]byte, 65), - Accounts: accounts, - } - - // Fill SignData - copy(bal.SignData, []byte("large_data_test_signature_123456789012345678901234567890123456789")) - - hash := common.HexToHash("0xaaaa") - number := uint64(999) - - // Test storage and retrieval of large data - WriteBAL(db, hash, number, bal) - - retrieved := ReadBAL(db, hash, number) - if retrieved == nil { - t.Fatalf("Failed to retrieve large BAL data") - } - - if !balEqual(retrieved, bal) { - t.Fatalf("Large BAL data integrity check failed") - } - - // Test deletion - DeleteBAL(db, hash, number) - if ReadBAL(db, hash, number) != nil { - t.Fatalf("Large BAL data not properly deleted") - } -} - -func TestBALMultipleBlocks(t *testing.T) { - db := NewMemoryDatabase() - - // Store BALs for multiple blocks - blocks := []struct { - hash common.Hash - number uint64 - bal *types.BlockAccessListEncode - }{ - { - hash: common.HexToHash("0xaaaa"), - number: 1, - bal: &types.BlockAccessListEncode{ - Version: 1, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{ - { - TxIndex: 0, - Address: common.HexToAddress("0x1111111111111111111111111111111111111111"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x01"), TxIndex: 0, Dirty: false}, - }, - }, - }, - }, - }, - { - hash: common.HexToHash("0xbbbb"), - number: 2, - bal: &types.BlockAccessListEncode{ - Version: 2, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{ - { - TxIndex: 0, - Address: common.HexToAddress("0x2222222222222222222222222222222222222222"), - StorageItems: []types.StorageAccessItem{ - {Key: common.HexToHash("0x02"), TxIndex: 1, Dirty: true}, - }, - }, - }, - }, - }, - { - hash: common.HexToHash("0xcccc"), - number: 3, - bal: &types.BlockAccessListEncode{ - Version: 3, - SignData: make([]byte, 65), - Accounts: []types.AccountAccessListEncode{}, - }, - }, - } - - // Store all BALs - for i, block := range blocks { - sigData := fmt.Sprintf("signature_for_block_%d_123456789012345678901234567890123456789012345678901234567890", i) - copy(block.bal.SignData, []byte(sigData)) - WriteBAL(db, block.hash, block.number, block.bal) - } - - // Verify all can be retrieved independently - for i, block := range blocks { - retrieved := ReadBAL(db, block.hash, block.number) - if retrieved == nil { - t.Fatalf("Failed to retrieve BAL for block %d", i) - } - if !balEqual(retrieved, block.bal) { - t.Fatalf("BAL mismatch for block %d", i) - } - } - - // Delete middle block - DeleteBAL(db, blocks[1].hash, blocks[1].number) - - // Verify first and third blocks still exist - if ReadBAL(db, blocks[0].hash, blocks[0].number) == nil { - t.Fatalf("Block 0 BAL was incorrectly deleted") - } - if ReadBAL(db, blocks[1].hash, blocks[1].number) != nil { - t.Fatalf("Block 1 BAL was not deleted") - } - if ReadBAL(db, blocks[2].hash, blocks[2].number) == nil { - t.Fatalf("Block 2 BAL was incorrectly deleted") - } -} - -// Helper function to compare two BlockAccessListEncode structs -func balEqual(a, b *types.BlockAccessListEncode) bool { - if a == nil && b == nil { - return true - } - if a == nil || b == nil { - return false - } - if a.Version != b.Version { - return false - } - if !bytes.Equal(a.SignData, b.SignData) { - return false - } - if len(a.Accounts) != len(b.Accounts) { - return false - } - for i, accountA := range a.Accounts { - accountB := b.Accounts[i] - if accountA.TxIndex != accountB.TxIndex { - return false - } - if accountA.Address != accountB.Address { - return false - } - if len(accountA.StorageItems) != len(accountB.StorageItems) { - return false - } - for j, storageA := range accountA.StorageItems { - storageB := accountB.StorageItems[j] - if storageA.Key != storageB.Key || storageA.TxIndex != storageB.TxIndex || storageA.Dirty != storageB.Dirty { - return false - } - } - } - return true -} diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index 5df4fbccb3..56cbe66b5b 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -225,6 +225,8 @@ func blockBlobSidecarsKey(number uint64, hash common.Hash) []byte { } // blockBALKey = blockBALPrefix + blockNumber (uint64 big endian) + blockHash +// +//nolint:unused func blockBALKey(number uint64, hash common.Hash) []byte { return append(append(BlockBALPrefix, encodeBlockNumber(number)...), hash.Bytes()...) } diff --git a/core/state/statedb.go b/core/state/statedb.go index a68441e15f..27dec4a5df 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -135,9 +135,6 @@ type StateDB struct { accessList *accessList accessEvents *AccessEvents - // block level access list - blockAccessList *types.BlockAccessListRecord - // Transient storage transientStorage transientStorage @@ -191,7 +188,6 @@ func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, erro preimages: make(map[common.Hash][]byte), journal: newJournal(), accessList: newAccessList(), - blockAccessList: nil, transientStorage: newTransientStorage(), } if db.TrieDB().IsVerkle() { @@ -200,13 +196,6 @@ func NewWithReader(root common.Hash, db Database, reader Reader) (*StateDB, erro return sdb, nil } -func (s *StateDB) InitBlockAccessList() { - if s.blockAccessList != nil { - log.Warn("prepareBAL blockAccessList is not nil") - } - s.blockAccessList = &types.BlockAccessListRecord{Accounts: make(map[common.Address]types.AccountAccessListRecord)} -} - func (s *StateDB) SetNeedBadSharedStorage(needBadSharedStorage bool) { s.needBadSharedStorage = needBadSharedStorage } @@ -365,43 +354,6 @@ func (s *StateDB) GetNonce(addr common.Address) uint64 { return 0 } -func (s *StateDB) PreloadAccount(addr common.Address) { - if s.Empty(addr) { - return - } - s.GetCode(addr) -} - -func (s *StateDB) PreloadStorage(addr common.Address, key common.Hash) { - if s.Empty(addr) { - return - } - s.GetState(addr, key) -} -func (s *StateDB) PreloadAccountTrie(addr common.Address) { - if s.prefetcher == nil { - return - } - - addressesToPrefetch := []common.Address{addr} - if err := s.prefetcher.prefetch(common.Hash{}, s.originalRoot, common.Address{}, addressesToPrefetch, nil, false); err != nil { - log.Error("Failed to prefetch addresses", "addresses", len(addressesToPrefetch), "err", err) - } -} - -func (s *StateDB) PreloadStorageTrie(addr common.Address, key common.Hash) { - if s.prefetcher == nil { - return - } - obj := s.getStateObject(addr) - if obj == nil { - return - } - if err := s.prefetcher.prefetch(obj.addrHash, obj.origin.Root, obj.address, nil, []common.Hash{key}, true); err != nil { - log.Error("Failed to prefetch storage slot", "addr", obj.address, "key", key, "err", err) - } -} - // GetStorageRoot retrieves the storage root from the given address or empty // if object not found. func (s *StateDB) GetStorageRoot(addr common.Address) common.Hash { @@ -451,7 +403,6 @@ func (s *StateDB) GetCodeHash(addr common.Address) common.Hash { func (s *StateDB) GetState(addr common.Address, hash common.Hash) common.Hash { stateObject := s.getStateObject(addr) if stateObject != nil { - s.blockAccessList.AddStorage(addr, hash, uint32(s.txIndex), false) return stateObject.GetState(hash) } return common.Hash{} @@ -543,7 +494,6 @@ func (s *StateDB) SetCode(addr common.Address, code []byte, reason tracing.CodeC } func (s *StateDB) SetState(addr common.Address, key, value common.Hash) common.Hash { - s.blockAccessList.AddStorage(addr, key, uint32(s.txIndex), true) if stateObject := s.getOrNewStateObject(addr); stateObject != nil { return stateObject.SetState(key, value) } @@ -673,7 +623,6 @@ func (s *StateDB) deleteStateObject(addr common.Address) { // getStateObject retrieves a state object given by the address, returning nil if // the object is not found or was deleted in this execution context. func (s *StateDB) getStateObject(addr common.Address) *stateObject { - s.blockAccessList.AddAccount(addr, uint32(s.txIndex)) // Prefer live objects if any is available if obj := s.stateObjects[addr]; obj != nil { return obj @@ -773,14 +722,6 @@ func (s *StateDB) StateForPrefetch() *StateDB { return state } -func (s *StateDB) TransferBlockAccessList(prev *StateDB) { - if prev == nil { - return - } - s.blockAccessList = prev.blockAccessList - prev.blockAccessList = nil -} - // Copy creates a deep, independent copy of the state. // Snapshots of the copied state cannot be applied to the copy. func (s *StateDB) Copy() *StateDB { @@ -809,7 +750,6 @@ func (s *StateDB) Copy() *StateDB { // empty lists, so we do it anyway to not blow up if we ever decide copy them // in the middle of a transaction. accessList: s.accessList.Copy(), - blockAccessList: nil, transientStorage: s.transientStorage.Copy(), journal: s.journal.copy(), } @@ -1677,56 +1617,6 @@ func (s *StateDB) AccessEvents() *AccessEvents { return s.accessEvents } -func (s *StateDB) DumpAccessList(block *types.Block) { - if s.blockAccessList == nil { - return - } - accountCount := 0 - storageCount := 0 - dirtyStorageCount := 0 - for addr, account := range s.blockAccessList.Accounts { - accountCount++ - log.Debug(" DumpAccessList Address", "address", addr.Hex(), "txIndex", account.TxIndex) - for _, storageItem := range account.StorageItems { - log.Debug(" DumpAccessList Storage Item", "key", storageItem.Key.Hex(), "txIndex", storageItem.TxIndex, "dirty", storageItem.Dirty) - storageCount++ - if storageItem.Dirty { - dirtyStorageCount++ - } - } - } - log.Info("DumpAccessList", "blockNumber", block.NumberU64(), "GasUsed", block.GasUsed(), - "accountCount", accountCount, "storageCount", storageCount, "dirtyStorageCount", dirtyStorageCount) -} - -// GetEncodedBlockAccessList: convert BlockAccessListRecord to BlockAccessListEncode -func (s *StateDB) GetEncodedBlockAccessList(block *types.Block) *types.BlockAccessListEncode { - if s.blockAccessList == nil { - return nil - } - // encode block access list to rlp to propagate with the block - blockAccessList := types.BlockAccessListEncode{ - Version: 0, - Number: block.NumberU64(), - Hash: block.Hash(), - SignData: make([]byte, 65), - Accounts: make([]types.AccountAccessListEncode, 0), - } - for addr, account := range s.blockAccessList.Accounts { - accountAccessList := types.AccountAccessListEncode{ - TxIndex: account.TxIndex, - Address: addr, - StorageItems: make([]types.StorageAccessItem, 0), - } - for _, storageItem := range account.StorageItems { - accountAccessList.StorageItems = append(accountAccessList.StorageItems, storageItem) - } - blockAccessList.Accounts = append(blockAccessList.Accounts, accountAccessList) - } - - return &blockAccessList -} - func (s *StateDB) GetDirtyAccounts() []common.Address { accounts := make([]common.Address, 0, len(s.mutations)) for account := range s.mutations { diff --git a/core/state_prefetcher.go b/core/state_prefetcher.go index a82f6646b2..5af32e891d 100644 --- a/core/state_prefetcher.go +++ b/core/state_prefetcher.go @@ -25,14 +25,11 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" "golang.org/x/sync/errgroup" ) const prefetchMiningThread = 3 -const prefetchThreadBALSnapshot = 8 -const prefetchThreadBALTrie = 8 const checkInterval = 10 // statePrefetcher is a basic Prefetcher that executes transactions from a block @@ -132,147 +129,6 @@ func (p *statePrefetcher) Prefetch(transactions types.Transactions, header *type return } -func (p *statePrefetcher) PrefetchBALSnapshot(balPrefetch *types.BlockAccessListPrefetch, block *types.Block, txSize int, statedb *state.StateDB, interruptChan <-chan struct{}) { - accChan := make(chan struct { - txIndex uint32 - accAddr common.Address - }, prefetchThreadBALSnapshot) - - keyChan := make(chan struct { - txIndex uint32 - accAddr common.Address - key common.Hash - }, prefetchThreadBALSnapshot) - - // prefetch snapshot cache - for i := 0; i < prefetchThreadBALSnapshot; i++ { - go func() { - newStatedb := statedb.Copy() - for { - select { - case accAddr := <-accChan: - log.Debug("PrefetchBALSnapshot", "txIndex", accAddr.txIndex, "accAddr", accAddr.accAddr) - newStatedb.PreloadAccount(accAddr.accAddr) - case item := <-keyChan: - log.Debug("PrefetchBALSnapshot", "txIndex", item.txIndex, "accAddr", item.accAddr, "key", item.key) - newStatedb.PreloadStorage(item.accAddr, item.key) - case <-interruptChan: - return - } - } - }() - } - for txIndex := 0; txIndex < txSize; txIndex++ { - txAccessList := balPrefetch.AccessListItems[uint32(txIndex)] - for accAddr, storageItems := range txAccessList.Accounts { - select { - case accChan <- struct { - txIndex uint32 - accAddr common.Address - }{ - txIndex: uint32(txIndex), - accAddr: accAddr, - }: - case <-interruptChan: - return - } - for _, storageItem := range storageItems { - select { - case keyChan <- struct { - txIndex uint32 - accAddr common.Address - key common.Hash - }{ - txIndex: uint32(txIndex), - accAddr: accAddr, - key: storageItem.Key, - }: - case <-interruptChan: - return - } - } - } - } - log.Debug("PrefetchBALSnapshot dispatch finished") -} - -func (p *statePrefetcher) PrefetchBALTrie(balPrefetch *types.BlockAccessListPrefetch, block *types.Block, statedb *state.StateDB, interruptChan <-chan struct{}) { - accItemsChan := make(chan struct { - txIndex uint32 - accAddr common.Address - items []types.StorageAccessItemPrefetch - }, prefetchThreadBALTrie) - - for i := 0; i < prefetchThreadBALTrie; i++ { - go func() { - newStatedb := statedb.Copy() - for { - select { - case accItem := <-accItemsChan: - newStatedb.PreloadAccountTrie(accItem.accAddr) - log.Debug("PrefetchBALTrie", "txIndex", accItem.txIndex, "accAddr", accItem.accAddr) - for _, storageItem := range accItem.items { - if storageItem.Dirty { - log.Debug("PrefetchBALTrie", "txIndex", accItem.txIndex, "accAddr", accItem.accAddr, "storageItem", storageItem.Key, "dirty", storageItem.Dirty) - statedb.PreloadStorageTrie(accItem.accAddr, storageItem.Key) - } - } - case <-interruptChan: - return - } - } - }() - } - - for txIndex, txAccessList := range balPrefetch.AccessListItems { - for accAddr, storageItems := range txAccessList.Accounts { - select { - case accItemsChan <- struct { - txIndex uint32 - accAddr common.Address - items []types.StorageAccessItemPrefetch - }{ - txIndex: txIndex, - accAddr: accAddr, - items: storageItems, - }: - case <-interruptChan: - log.Warn("PrefetchBALTrie interrupted") - return - } - } - } - log.Debug("PrefetchBALTrie dispatch finished") -} - -func (p *statePrefetcher) PrefetchBAL(block *types.Block, statedb *state.StateDB, interruptChan <-chan struct{}) { - if block.BAL() == nil { - return - } - transactions := block.Transactions() - blockAccessList := block.BAL() - - // get index sorted block access list, each transaction has a list of accounts, each account has a list of storage items - // txIndex 0: - // account1: storage1_1, storage1_2, storage1_3 - // account2: storage2_1, storage2_2, storage2_3 - // txIndex 1: - // account3: storage3_1, storage3_2, storage3_3 - // ... - balPrefetch := types.BlockAccessListPrefetch{ - AccessListItems: make(map[uint32]types.TxAccessListPrefetch), - } - for _, account := range blockAccessList.Accounts { - balPrefetch.Update(&account) - } - - // prefetch snapshot cache - go p.PrefetchBALSnapshot(&balPrefetch, block, len(transactions), statedb, interruptChan) - - // prefetch MPT trie node cache - go p.PrefetchBALTrie(&balPrefetch, block, statedb, interruptChan) -} - // PrefetchMining processes the state changes according to the Ethereum rules by running // the transaction messages using the statedb, but any changes are discarded. The // only goal is to warm the state caches. Only used for mining stage. diff --git a/core/state_processor.go b/core/state_processor.go index 4299f37666..19c78b3942 100644 --- a/core/state_processor.go +++ b/core/state_processor.go @@ -185,7 +185,7 @@ func (p *StateProcessor) Process(block *types.Block, statedb *state.StateDB, cfg for _, receipt := range receipts { allLogs = append(allLogs, receipt.Logs...) } - statedb.DumpAccessList(block) + return &ProcessResult{ Receipts: receipts, Requests: requests, diff --git a/core/types.go b/core/types.go index e27395f5c3..2e27fcd5d5 100644 --- a/core/types.go +++ b/core/types.go @@ -49,8 +49,6 @@ type Prefetcher interface { Prefetch(transactions types.Transactions, header *types.Header, gasLimit uint64, statedb *state.StateDB, cfg vm.Config, interrupt *atomic.Bool) // PrefetchMining used for pre-caching transaction signatures and state trie nodes. Only used for mining stage. PrefetchMining(txs TransactionsByPriceAndNonce, header *types.Header, gasLimit uint64, statedb *state.StateDB, cfg vm.Config, interruptCh <-chan struct{}, txCurr **types.Transaction) - // prefetch based on block access list - PrefetchBAL(block *types.Block, statedb *state.StateDB, interruptChan <-chan struct{}) } // Processor is an interface for processing blocks using a given initial state. diff --git a/core/types/block.go b/core/types/block.go index 6b81e63a97..7dc9f4f30e 100644 --- a/core/types/block.go +++ b/core/types/block.go @@ -235,123 +235,6 @@ type Body struct { Withdrawals []*Withdrawal `rlp:"optional"` } -// StorageAccessItem is a single storage key that is accessed in a block. -type StorageAccessItem struct { - TxIndex uint32 // index of the first transaction in the block that accessed the storage - Dirty bool // true if the storage was modified in the block, false if it was read only - Key common.Hash -} - -// AccountAccessListEncode & BlockAccessListEncode are for BAL serialization. -type AccountAccessListEncode struct { - TxIndex uint32 // index of the first transaction in the block that accessed the account - Address common.Address - StorageItems []StorageAccessItem -} - -type BlockAccessListEncode struct { - Version uint32 // Version of the access list format - Number uint64 // number of the block that the BAL is for - Hash common.Hash // hash of the block that the BAL is for - SignData []byte // sign data for BAL - Accounts []AccountAccessListEncode -} - -// TxAccessListPrefetch & BlockAccessListPrefetch are for BAL prefetch -type StorageAccessItemPrefetch struct { - Dirty bool - Key common.Hash -} - -type TxAccessListPrefetch struct { - Accounts map[common.Address][]StorageAccessItemPrefetch -} - -type BlockAccessListPrefetch struct { - AccessListItems map[uint32]TxAccessListPrefetch -} - -func (b *BlockAccessListPrefetch) Update(aclEncode *AccountAccessListEncode) { - if aclEncode == nil { - return - } - accAddr := aclEncode.Address - b.PrepareTxAccount(aclEncode.TxIndex, accAddr) - for _, storageItem := range aclEncode.StorageItems { - b.PrepareTxStorage(accAddr, storageItem) - } -} - -func (b *BlockAccessListPrefetch) PrepareTxStorage(accAddr common.Address, storageItem StorageAccessItem) { - b.PrepareTxAccount(storageItem.TxIndex, accAddr) - txAccessList := b.AccessListItems[storageItem.TxIndex] - txAccessList.Accounts[accAddr] = append(txAccessList.Accounts[accAddr], StorageAccessItemPrefetch{ - Dirty: storageItem.Dirty, - Key: storageItem.Key, - }) -} -func (b *BlockAccessListPrefetch) PrepareTxAccount(txIndex uint32, addr common.Address) { - // create the tx access list if not exists - if _, ok := b.AccessListItems[txIndex]; !ok { - b.AccessListItems[txIndex] = TxAccessListPrefetch{ - Accounts: make(map[common.Address][]StorageAccessItemPrefetch), - } - } - // create the account access list if not exists - if _, ok := b.AccessListItems[txIndex].Accounts[addr]; !ok { - b.AccessListItems[txIndex].Accounts[addr] = make([]StorageAccessItemPrefetch, 0) - } -} - -// BlockAccessListRecord & BlockAccessListRecord are used to record access list during tx execution. -type AccountAccessListRecord struct { - TxIndex uint32 // index of the first transaction in the block that accessed the account - StorageItems map[common.Hash]StorageAccessItem -} - -type BlockAccessListRecord struct { - Version uint32 // Version of the access list format - Accounts map[common.Address]AccountAccessListRecord -} - -func (b *BlockAccessListRecord) AddAccount(addr common.Address, txIndex uint32) { - if b == nil { - return - } - - if _, ok := b.Accounts[addr]; !ok { - b.Accounts[addr] = AccountAccessListRecord{ - TxIndex: txIndex, - StorageItems: make(map[common.Hash]StorageAccessItem), - } - } -} - -func (b *BlockAccessListRecord) AddStorage(addr common.Address, key common.Hash, txIndex uint32, dirty bool) { - if b == nil { - return - } - - if _, ok := b.Accounts[addr]; !ok { - b.Accounts[addr] = AccountAccessListRecord{ - TxIndex: txIndex, - StorageItems: make(map[common.Hash]StorageAccessItem), - } - } - - if _, ok := b.Accounts[addr].StorageItems[key]; !ok { - b.Accounts[addr].StorageItems[key] = StorageAccessItem{ - TxIndex: txIndex, - Dirty: dirty, - Key: key, - } - } else { - storageItem := b.Accounts[addr].StorageItems[key] - storageItem.Dirty = dirty - b.Accounts[addr].StorageItems[key] = storageItem - } -} - // Block represents an Ethereum block. // // Note the Block type tries to be 'immutable', and contains certain caches that rely @@ -391,10 +274,6 @@ type Block struct { // sidecars provides DA check sidecars BlobSidecars - - // bal provides block access list - bal *BlockAccessListEncode - balSize atomic.Uint64 } // "external" block encoding. used for eth protocol, etc. @@ -617,19 +496,6 @@ func (b *Block) Size() uint64 { return uint64(c) } -func (b *Block) BALSize() uint64 { - if b.bal == nil { - return 0 - } - if size := b.balSize.Load(); size > 0 { - return size - } - c := writeCounter(0) - rlp.Encode(&c, b.bal) - b.balSize.Store(uint64(c)) - return uint64(c) -} - func (b *Block) SetRoot(root common.Hash) { b.header.Root = root } // SanityCheck can be used to prevent that unbounded fields are @@ -642,10 +508,6 @@ func (b *Block) Sidecars() BlobSidecars { return b.sidecars } -func (b *Block) BAL() *BlockAccessListEncode { - return b.bal -} - func (b *Block) CleanSidecars() { b.sidecars = make(BlobSidecars, 0) } @@ -701,7 +563,6 @@ func (b *Block) WithSeal(header *Header) *Block { withdrawals: b.withdrawals, witness: b.witness, sidecars: b.sidecars, - bal: b.bal, } } @@ -715,7 +576,6 @@ func (b *Block) WithBody(body Body) *Block { withdrawals: slices.Clone(body.Withdrawals), witness: b.witness, sidecars: b.sidecars, - bal: b.bal, } for i := range body.Uncles { block.uncles[i] = CopyHeader(body.Uncles[i]) @@ -731,7 +591,6 @@ func (b *Block) WithWithdrawals(withdrawals []*Withdrawal) *Block { uncles: b.uncles, witness: b.witness, sidecars: b.sidecars, - bal: b.bal, } if withdrawals != nil { block.withdrawals = make([]*Withdrawal, len(withdrawals)) @@ -748,7 +607,6 @@ func (b *Block) WithSidecars(sidecars BlobSidecars) *Block { uncles: b.uncles, withdrawals: b.withdrawals, witness: b.witness, - bal: b.bal, } if sidecars != nil { block.sidecars = make(BlobSidecars, len(sidecars)) @@ -757,23 +615,6 @@ func (b *Block) WithSidecars(sidecars BlobSidecars) *Block { return block } -func (b *Block) WithBAL(bal *BlockAccessListEncode) *Block { - block := &Block{ - header: b.header, - transactions: b.transactions, - uncles: b.uncles, - withdrawals: b.withdrawals, - witness: b.witness, - sidecars: b.sidecars, - } - block.bal = bal - return block -} - -func (b *Block) UpdateBAL(bal *BlockAccessListEncode) { - b.bal = bal -} - func (b *Block) WithWitness(witness *ExecutionWitness) *Block { return &Block{ header: b.header, diff --git a/eth/backend.go b/eth/backend.go index d5ac85ddaa..625571c66a 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -339,7 +339,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { options = &core.BlockChainConfig{ TrieCleanLimit: config.TrieCleanCache, NoPrefetch: config.NoPrefetch, - EnableBAL: config.EnableBAL, TrieDirtyLimit: config.TrieDirtyCache, ArchiveMode: config.NoPruning, TrieTimeLimit: config.TrieTimeout, @@ -464,7 +463,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { RequiredBlocks: config.RequiredBlocks, DirectBroadcast: config.DirectBroadcast, EnableEVNFeatures: stack.Config().EnableEVNFeatures, - EnableBAL: config.EnableBAL, EVNNodeIdsWhitelist: stack.Config().P2P.EVNNodeIdsWhitelist, ProxyedValidatorAddresses: stack.Config().P2P.ProxyedValidatorAddresses, ProxyedNodeIds: stack.Config().P2P.ProxyedNodeIds, diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index c34ec2315c..ef84b0a121 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -117,7 +117,6 @@ type Config struct { NoPruning bool // Whether to disable pruning and flush everything to disk NoPrefetch bool // Whether to disable prefetching and only load state on demand - EnableBAL bool DirectBroadcast bool DisableSnapProtocol bool // Whether disable snap protocol RangeLimit bool diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 613ef4c808..a844b14ecf 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -30,7 +30,6 @@ func (c Config) MarshalTOML() (interface{}, error) { BscDiscoveryURLs []string NoPruning bool NoPrefetch bool - EnableBAL bool DirectBroadcast bool DisableSnapProtocol bool RangeLimit bool @@ -108,7 +107,6 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.BscDiscoveryURLs = c.BscDiscoveryURLs enc.NoPruning = c.NoPruning enc.NoPrefetch = c.NoPrefetch - enc.EnableBAL = c.EnableBAL enc.DirectBroadcast = c.DirectBroadcast enc.DisableSnapProtocol = c.DisableSnapProtocol enc.RangeLimit = c.RangeLimit @@ -190,7 +188,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { BscDiscoveryURLs []string NoPruning *bool NoPrefetch *bool - EnableBAL *bool DirectBroadcast *bool DisableSnapProtocol *bool RangeLimit *bool @@ -295,9 +292,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.NoPrefetch != nil { c.NoPrefetch = *dec.NoPrefetch } - if dec.EnableBAL != nil { - c.EnableBAL = *dec.EnableBAL - } if dec.DirectBroadcast != nil { c.DirectBroadcast = *dec.DirectBroadcast } diff --git a/eth/fetcher/block_fetcher.go b/eth/fetcher/block_fetcher.go index f157250b1c..d432d64cd3 100644 --- a/eth/fetcher/block_fetcher.go +++ b/eth/fetcher/block_fetcher.go @@ -914,7 +914,7 @@ func (f *BlockFetcher) importBlocks(op *blockOrHeaderInject) { hash := block.Hash() // Run the import on a new thread - log.Debug("Importing propagated block", "peer", peer, "number", block.Number(), "hash", hash, "balSize", block.BALSize()) + log.Debug("Importing propagated block", "peer", peer, "number", block.Number(), "hash", hash) go func() { // If the parent's unknown, abort insertion parent := f.getBlock(block.ParentHash()) diff --git a/eth/handler.go b/eth/handler.go index c1cee8f648..1ea417074f 100644 --- a/eth/handler.go +++ b/eth/handler.go @@ -143,7 +143,6 @@ type handlerConfig struct { PeerSet *peerSet EnableQuickBlockFetching bool EnableEVNFeatures bool - EnableBAL bool EVNNodeIdsWhitelist []enode.ID ProxyedValidatorAddresses []common.Address ProxyedNodeIds []enode.ID @@ -154,7 +153,6 @@ type handler struct { networkID uint64 disablePeerTxBroadcast bool enableEVNFeatures bool - enableBAL bool evnNodeIdsWhitelistMap map[enode.ID]struct{} proxyedValidatorAddressMap map[common.Address]struct{} proxyedNodeIdsMap map[enode.ID]struct{} @@ -228,7 +226,6 @@ func newHandler(config *handlerConfig) (*handler, error) { requiredBlocks: config.RequiredBlocks, directBroadcast: config.DirectBroadcast, enableEVNFeatures: config.EnableEVNFeatures, - enableBAL: config.EnableBAL, evnNodeIdsWhitelistMap: make(map[enode.ID]struct{}), proxyedValidatorAddressMap: make(map[common.Address]struct{}), proxyedNodeIdsMap: make(map[enode.ID]struct{}), @@ -358,9 +355,6 @@ func newHandler(config *handlerConfig) (*handler, error) { for i, item := range res { block := types.NewBlockWithHeader(item.Header).WithBody(types.Body{Transactions: item.Txs, Uncles: item.Uncles}) block = block.WithSidecars(item.Sidecars) - if item.BAL != nil && h.chain.Engine().VerifyBAL(block, item.BAL) == nil { - block = block.WithBAL(item.BAL) - } block.ReceivedAt = time.Now() block.ReceivedFrom = p.ID() if err := block.SanityCheck(); err != nil { @@ -483,10 +477,6 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error { peer.Log().Error("Bsc extension barrier failed", "err", err) return err } - if bscExt != nil && bscExt.Version() == bsc.Bsc3 { - peer.CanHandleBAL.Store(true) - log.Debug("runEthPeer", "bscExt.Version", bscExt.Version(), "CanHandleBAL", peer.CanHandleBAL.Load()) - } // Execute the Ethereum handshake var ( head = h.chain.CurrentHeader() @@ -857,7 +847,6 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) { log.Debug("Broadcast block to peer", "hash", hash, "peer", peer.ID(), "EVNPeerFlag", peer.EVNPeerFlag.Load(), - "CanHandleBAL", peer.CanHandleBAL.Load(), ) peer.AsyncSendNewBlock(block, td) } @@ -870,7 +859,6 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) { log.Debug("Broadcast block to proxyed peer", "hash", hash, "peer", peer.ID(), "EVNPeerFlag", peer.EVNPeerFlag.Load(), - "CanHandleBAL", peer.CanHandleBAL.Load(), ) peer.AsyncSendNewBlock(block, td) proxyedPeersCnt++ @@ -886,7 +874,6 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) { log.Debug("Broadcast block to EVN peer", "hash", hash, "peer", peer.ID(), "EVNPeerFlag", peer.EVNPeerFlag.Load(), - "CanHandleBAL", peer.CanHandleBAL.Load(), ) peer.AsyncSendNewBlock(block, td) evnPeersCnt++ @@ -908,7 +895,7 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) { if h.chain.HasBlock(hash, block.NumberU64()) { for _, peer := range peers { log.Debug("Announced block to peer", "hash", hash, "peer", peer.ID(), - "EVNPeerFlag", peer.EVNPeerFlag.Load(), "CanHandleBAL", peer.CanHandleBAL.Load()) + "EVNPeerFlag", peer.EVNPeerFlag.Load()) peer.AsyncSendNewBlockHash(block) } log.Debug("Announced block", "hash", hash, "recipients", len(peers), "duration", common.PrettyDuration(time.Since(block.ReceivedAt))) diff --git a/eth/handler_eth.go b/eth/handler_eth.go index eb3f231be2..d56269f420 100644 --- a/eth/handler_eth.go +++ b/eth/handler_eth.go @@ -171,10 +171,6 @@ func (h *ethHandler) handleBlockBroadcast(peer *eth.Peer, packet *eth.NewBlockPa if sidecars != nil { block = block.WithSidecars(sidecars) } - if packet.Bal != nil && h.chain.Engine().VerifyBAL(block, packet.Bal) == nil { - block = block.WithBAL(packet.Bal) - } - // Schedule the block for import log.Debug("handleBlockBroadcast", "peer", peer.ID(), "block", block.Number(), "hash", block.Hash()) h.blockFetcher.Enqueue(peer.ID(), block) diff --git a/eth/protocols/bsc/handler.go b/eth/protocols/bsc/handler.go index e83ca2dd19..1beaf113e7 100644 --- a/eth/protocols/bsc/handler.go +++ b/eth/protocols/bsc/handler.go @@ -24,7 +24,7 @@ const ( // softResponseLimit is the target maximum size of replies. The hard cap on // the wire is maxMessageSize (10MB); 8MB leaves headroom for outer RLP/p2p - // framing. Each entry's measured size includes sidecars and BAL. + // framing. Each entry's measured size includes sidecars. softResponseLimit = 8 * 1024 * 1024 ) diff --git a/eth/protocols/bsc/protocol.go b/eth/protocols/bsc/protocol.go index 7c86269c2e..3f60c3f19a 100644 --- a/eth/protocols/bsc/protocol.go +++ b/eth/protocols/bsc/protocol.go @@ -12,7 +12,6 @@ import ( const ( Bsc1 = 1 Bsc2 = 2 - Bsc3 = 3 // to BAL process ) // ProtocolName is the official short name of the `bsc` protocol used during @@ -21,11 +20,11 @@ const ProtocolName = "bsc" // ProtocolVersions are the supported versions of the `bsc` protocol (first // is primary). -var ProtocolVersions = []uint{Bsc1, Bsc2, Bsc3} +var ProtocolVersions = []uint{Bsc1, Bsc2} // protocolLengths are the number of implemented message corresponding to // different protocol versions. -var protocolLengths = map[uint]uint64{Bsc1: 2, Bsc2: 4, Bsc3: 4} +var protocolLengths = map[uint]uint64{Bsc1: 2, Bsc2: 4} // maxMessageSize is the maximum cap on the size of a protocol message. const maxMessageSize = 10 * 1024 * 1024 @@ -83,9 +82,8 @@ type BlockData struct { Header *types.Header Txs []*types.Transaction Uncles []*types.Header - Withdrawals []*types.Withdrawal `rlp:"optional"` - Sidecars types.BlobSidecars `rlp:"optional"` - BAL *types.BlockAccessListEncode `rlp:"optional"` + Withdrawals []*types.Withdrawal `rlp:"optional"` + Sidecars types.BlobSidecars `rlp:"optional"` } // NewBlockData creates a new BlockData object from a block @@ -96,7 +94,6 @@ func NewBlockData(block *types.Block) *BlockData { Uncles: block.Uncles(), Withdrawals: block.Withdrawals(), Sidecars: block.Sidecars(), - BAL: block.BAL(), } } diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index ca9b142e7f..c5e6afdd74 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -380,13 +380,6 @@ func handleNewBlock(backend Backend, msg Decoder, peer *Peer) error { return fmt.Errorf("%w: message %v: %v", errDecode, msg, err) } - if ann.Bal != nil { - log.Debug("handleNewBlock, BAL", "number", ann.Block.NumberU64(), "hash", ann.Block.Hash(), "peer", peer.ID(), - "version", ann.Bal.Version, "signData", len(ann.Bal.SignData), "accounts", len(ann.Bal.Accounts), "balSize", ann.Block.BALSize()) - } else { - log.Debug("handleNewBlock, no BAL", "number", ann.Block.NumberU64(), "hash", ann.Block.Hash(), "peer", peer.ID(), - "txNum", len(ann.Block.Transactions()), "balSize", ann.Block.BALSize()) - } // Now that we have our packet, perform operations using the interface methods if err := ann.sanityCheck(); err != nil { return err diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go index b70806b0de..b172795fcf 100644 --- a/eth/protocols/eth/peer.go +++ b/eth/protocols/eth/peer.go @@ -26,7 +26,6 @@ import ( mapset "github.com/deckarep/golang-set/v2" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/p2p" "github.com/ethereum/go-ethereum/p2p/enode" "github.com/ethereum/go-ethereum/p2p/tracker" @@ -318,23 +317,11 @@ func (p *Peer) AsyncSendNewBlockHash(block *types.Block) { func (p *Peer) SendNewBlock(block *types.Block, td *big.Int) error { // Mark all the block hash as known, but ensure we don't overflow our limits p.knownBlocks.Add(block.Hash()) - bal := block.BAL() - if !p.CanHandleBAL.Load() { - bal = nil - } - if bal != nil { - log.Debug("SendNewBlock", "number", block.NumberU64(), "hash", block.Hash(), "peer", p.ID(), - "balSize", block.BALSize(), "version", bal.Version, "canHandleBAL", p.CanHandleBAL.Load()) - } else { - log.Debug("SendNewBlock no BAL", "number", block.NumberU64(), "hash", block.Hash(), "peer", p.ID(), - "txNum", len(block.Transactions()), "canHandleBAL", p.CanHandleBAL.Load()) - } return p2p.Send(p.rw, NewBlockMsg, &NewBlockPacket{ Block: block, TD: td, Sidecars: block.Sidecars(), - Bal: bal, }) } diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go index 84d9428d1f..e9e417d7d1 100644 --- a/eth/protocols/eth/protocol.go +++ b/eth/protocols/eth/protocol.go @@ -238,8 +238,7 @@ type BlockHeadersRLPPacket struct { type NewBlockPacket struct { Block *types.Block TD *big.Int - Sidecars types.BlobSidecars `rlp:"optional"` - Bal *types.BlockAccessListEncode `rlp:"optional"` + Sidecars types.BlobSidecars `rlp:"optional"` } // sanityCheck verifies that the values are reasonable, as a DoS protection diff --git a/miner/worker.go b/miner/worker.go index 25eb7eb424..2f5d0eb660 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -622,13 +622,6 @@ func (w *worker) resultLoop() { w.recentMinedBlocks.Add(block.NumberU64(), []common.Hash{block.ParentHash()}) } - // add BAL to the block - bal := task.state.GetEncodedBlockAccessList(block) - if bal != nil && w.engine.SignBAL(bal) == nil { - block = block.WithBAL(bal) - } - task.state.DumpAccessList(block) - // Commit block and state to database. start := time.Now() status, err := w.chain.WriteBlockAndSetHead(block, receipts, logs, task.state, w.mux) @@ -645,7 +638,7 @@ func (w *worker) resultLoop() { stats.SendBlockTime.Store(time.Now().UnixMilli()) 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))) + "block size", block.Size(), "elapsed", common.PrettyDuration(time.Since(task.createdAt))) w.mux.Post(core.NewMinedBlockEvent{Block: block}) case <-w.exitCh: diff --git a/node/config.go b/node/config.go index 8e18fc7d62..bc8679756a 100644 --- a/node/config.go +++ b/node/config.go @@ -104,9 +104,6 @@ type Config struct { // EnableQuickBlockFetching indicates whether to fetch new blocks using new messages. EnableQuickBlockFetching bool `toml:",omitempty"` - // EnableBAL enables the block access list feature - EnableBAL bool `toml:",omitempty"` - // RangeLimit enable 5000 blocks limit when handle range query RangeLimit bool `toml:",omitempty"` diff --git a/p2p/peer.go b/p2p/peer.go index e3362bfc85..4c9726f78f 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -132,9 +132,6 @@ type Peer struct { // Indicates whether this peer is proxyed. ProxyedPeerFlag atomic.Bool - - // it indicates the peer can handle BAL(block access list) packet - CanHandleBAL atomic.Bool } // NewPeer returns a peer for testing purposes. diff --git a/params/network_params.go b/params/network_params.go index ae5ca01c2d..5881cf3e22 100644 --- a/params/network_params.go +++ b/params/network_params.go @@ -22,9 +22,6 @@ package params const ( // StableStateThreshold is the reserve number of block state save to disk before delete ancientdb StableStateThreshold uint64 = 128 - - // MaxBALSize is the maximum bytes of the rlp encoded block access list: 1MB - MaxBALSize uint64 = 1048576 ) var ( From 3020997c6d6230395292caf562dcb52497c51780 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Wed, 20 May 2026 18:41:38 +0800 Subject: [PATCH 09/48] consensus/parlia: extract VerifyUnsealedHeader from verifyHeader (#3694) --- consensus/parlia/parlia.go | 181 +++++++++++++++++-------------------- 1 file changed, 83 insertions(+), 98 deletions(-) diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index 4e79dfe413..a3e9db48b2 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -264,9 +264,6 @@ type Parlia struct { validatorSetABI abi.ABI slashABI abi.ABI stakeHubABI abi.ABI - - // The fields below are for testing only - fakeDiff bool // Skip difficulty verifications } // New creates a Parlia consensus engine. @@ -576,23 +573,35 @@ func (p *Parlia) verifyVoteAttestation(chain consensus.ChainHeaderReader, header // looking those up from the database. This is useful for concurrently verifying // a batch of new headers. func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { - if header.Number == nil { - return errUnknownBlock - } - // Don't waste time checking blocks from the future if header.Time > uint64(time.Now().Unix()) { return consensus.ErrFutureBlock } - // Check that the extra-data contains the vanity, validators and signature. + + if err := p.VerifyUnsealedHeader(chain, header, parents); err != nil { + return err + } + + // All basic checks passed, verify the seal and return + return p.verifySeal(chain, header, parents) +} + +// VerifyUnsealedHeader performs all header validity checks that do not require +// a valid seal signature. It is used to validate a locally proposed block before +// sealing: it runs the same structural, fork-rule, and cascading-field checks as +// VerifyHeader but skips verifySeal (no signature yet) and verifyVoteAttestation +// (vote attestation is embedded by the sealer and not present before sealing). +func (p *Parlia) VerifyUnsealedHeader(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error { + // check extra data if len(header.Extra) < extraVanity { return errMissingVanity } if len(header.Extra) < extraVanity+extraSeal { return errMissingSignature } - - // check extra data + if header.Number == nil { + return errUnknownBlock + } number := header.Number.Uint64() epochLength, err := p.epochLength(chain, header, parents) if err != nil { @@ -618,52 +627,11 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H return fmt.Errorf("invalid MixDigest, have %#x, expected the last two bytes to represent milliseconds", header.MixDigest) } } + // Ensure that the block doesn't contain any uncles which are meaningless in PoA if header.UncleHash != types.EmptyUncleHash { return errInvalidUncleHash } - // Ensure that the block's difficulty is meaningful (may not be correct at this point) - if number > 0 { - if header.Difficulty == nil { - return errInvalidDifficulty - } - } - - parent, err := p.getParent(chain, header, parents) - if err != nil { - return err - } - - // Verify the block's gas usage and (if applicable) verify the base fee. - if !chain.Config().IsLondon(header.Number) { - // Verify BaseFee not present before EIP-1559 fork. - if header.BaseFee != nil { - return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee) - } - } else if err := eip1559.VerifyEIP1559Header(chain.Config(), parent, header); err != nil { - // Verify the header's EIP-1559 attributes. - return err - } - - cancun := chain.Config().IsCancun(header.Number, header.Time) - if !cancun { - switch { - case header.ExcessBlobGas != nil: - return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) - case header.BlobGasUsed != nil: - return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) - case header.WithdrawalsHash != nil: - return fmt.Errorf("invalid WithdrawalsHash, have %#x, expected nil", header.WithdrawalsHash) - } - } else { - switch { - case !header.EmptyWithdrawalsHash(): - return errors.New("header has wrong WithdrawalsHash") - } - if err := eip4844.VerifyEIP4844Header(chain.Config(), parent, header); err != nil { - return err - } - } bohr := chain.Config().IsBohr(header.Number, header.Time) if !bohr { @@ -702,12 +670,30 @@ func (p *Parlia) verifyCascadingFields(chain consensus.ChainHeaderReader, header return nil } - parent, err := p.getParent(chain, header, parents) + snap, err := p.snapshot(chain, number-1, header.ParentHash, parents) if err != nil { return err } - snap, err := p.snapshot(chain, number-1, header.ParentHash, parents) + if _, ok := snap.Validators[header.Coinbase]; !ok { + return errUnauthorizedValidator(header.Coinbase.String()) + } + if snap.SignRecently(header.Coinbase) { + return errRecentlySigned + } + + if header.Difficulty == nil { + return errInvalidDifficulty + } + inturn := snap.inturn(header.Coinbase) + if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { + return errWrongDifficulty + } + if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { + return errWrongDifficulty + } + + parent, err := p.getParent(chain, header, parents) if err != nil { return err } @@ -717,6 +703,36 @@ func (p *Parlia) verifyCascadingFields(chain consensus.ChainHeaderReader, header return err } + // Verify the block's gas usage and (if applicable) verify the base fee. + if !chain.Config().IsLondon(header.Number) { + // Verify BaseFee not present before EIP-1559 fork. + if header.BaseFee != nil { + return fmt.Errorf("invalid baseFee before fork: have %d, expected 'nil'", header.BaseFee) + } + } else if err := eip1559.VerifyEIP1559Header(chain.Config(), parent, header); err != nil { + // Verify the header's EIP-1559 attributes. + return err + } + + cancun := chain.Config().IsCancun(header.Number, header.Time) + if !cancun { + switch { + case header.ExcessBlobGas != nil: + return fmt.Errorf("invalid excessBlobGas: have %d, expected nil", header.ExcessBlobGas) + case header.BlobGasUsed != nil: + return fmt.Errorf("invalid blobGasUsed: have %d, expected nil", header.BlobGasUsed) + case header.WithdrawalsHash != nil: + return fmt.Errorf("invalid WithdrawalsHash, have %#x, expected nil", header.WithdrawalsHash) + } + } else { + if !header.EmptyWithdrawalsHash() { + return errors.New("header has wrong WithdrawalsHash") + } + if err := eip4844.VerifyEIP4844Header(chain.Config(), parent, header); err != nil { + return err + } + } + // Verify that the gas limit is <= 2^63-1 capacity := uint64(0x7fffffffffffffff) if header.GasLimit > capacity { @@ -742,18 +758,7 @@ func (p *Parlia) verifyCascadingFields(chain consensus.ChainHeaderReader, header return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit-1) } - // Verify vote attestation for fast finality. - if err := p.verifyVoteAttestation(chain, header, parents); err != nil { - log.Warn("Verify vote attestation failed", "error", err, "hash", header.Hash(), "number", header.Number, - "parent", header.ParentHash, "coinbase", header.Coinbase, "extra", common.Bytes2Hex(header.Extra)) - verifyVoteAttestationErrorCounter.Inc(1) - if chain.Config().IsPlato(header.Number) { - return err - } - } - - // All basic checks passed, verify the seal and return - return p.verifySeal(chain, header, parents) + return nil } // snapshot retrieves the authorization snapshot at a given point in time. @@ -924,12 +929,6 @@ func (p *Parlia) VerifyRequests(header *types.Header, Requests [][]byte) error { return nil } -// VerifySeal implements consensus.Engine, checking whether the signature contained -// in the header satisfies the consensus protocol requirements. -func (p *Parlia) VerifySeal(chain consensus.ChainReader, header *types.Header) error { - return p.verifySeal(chain, header, nil) -} - // verifySeal checks whether the signature contained in the header satisfies the // consensus protocol requirements. The method accepts an optional list of parent // headers that aren't yet part of the local blockchain to generate the snapshots @@ -940,10 +939,15 @@ func (p *Parlia) verifySeal(chain consensus.ChainHeaderReader, header *types.Hea if number == 0 { return errUnknownBlock } - // Retrieve the snapshot needed to verify this header and cache it - snap, err := p.snapshot(chain, number-1, header.ParentHash, parents) - if err != nil { - return err + + // Verify vote attestation for fast finality. + if err := p.verifyVoteAttestation(chain, header, parents); err != nil { + log.Warn("Verify vote attestation failed", "error", err, "hash", header.Hash(), "number", header.Number, + "parent", header.ParentHash, "coinbase", header.Coinbase, "extra", common.Bytes2Hex(header.Extra)) + verifyVoteAttestationErrorCounter.Inc(1) + if chain.Config().IsPlato(header.Number) { + return err + } } // Resolve the authorization key and check against validators @@ -967,25 +971,6 @@ func (p *Parlia) verifySeal(chain consensus.ChainHeaderReader, header *types.Hea p.recentHeaders.Add(key, header.Hash()) } - if _, ok := snap.Validators[signer]; !ok { - return errUnauthorizedValidator(signer.String()) - } - - if snap.SignRecently(signer) { - return errRecentlySigned - } - - // Ensure that the difficulty corresponds to the turn-ness of the signer - if !p.fakeDiff { - inturn := snap.inturn(signer) - if inturn && header.Difficulty.Cmp(diffInTurn) != 0 { - return errWrongDifficulty - } - if !inturn && header.Difficulty.Cmp(diffNoTurn) != 0 { - return errWrongDifficulty - } - } - return nil } @@ -1167,7 +1152,7 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header } // Set the correct difficulty - header.Difficulty = CalcDifficulty(snap, p.val) + header.Difficulty = calcDifficulty(snap, p.val) // Ensure the extra data has all it's components if len(header.Extra) < extraVanity-nextForkHashSize { @@ -1840,13 +1825,13 @@ func (p *Parlia) CalcDifficulty(chain consensus.ChainHeaderReader, time uint64, if err != nil { return nil } - return CalcDifficulty(snap, p.val) + return calcDifficulty(snap, p.val) } // CalcDifficulty is the difficulty adjustment algorithm. It returns the difficulty // that a new block should have based on the previous blocks in the chain and the // current signer. -func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int { +func calcDifficulty(snap *Snapshot, signer common.Address) *big.Int { if snap.inturn(signer) { return new(big.Int).Set(diffInTurn) } From 47089506e7770a3c1c5743fd08118d1ab7c0654e Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Fri, 22 May 2026 14:00:58 +0800 Subject: [PATCH 10/48] eth/filters: fix race in pending tx and new heads subscriptions (#33990) (#3686) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `TestSubscribePendingTxHashes` hangs indefinitely because pending tx events are permanently missed due to a race condition in `NewPendingTransactions` (and `NewHeads`). Both handlers called their event subscription functions (`SubscribePendingTxs`, `SubscribeNewHeads`) inside goroutines, so the RPC handler returned the subscription ID to the client before the filter was installed in the event loop. When the client then sent a transaction, the event fired but no filter existed to catch it — the event was silently lost. - Move `SubscribePendingTxs` and `SubscribeNewHeads` calls out of goroutines so filters are installed synchronously before the RPC response is sent, matching the pattern already used by `Logs` and `TransactionReceipts` --- 💬 We'd love your input! Share your thoughts on Copilot coding agent in our [2 minute survey](https://gh.io/copilot-coding-agent-survey). --------- Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: s1na <1591639+s1na@users.noreply.github.com> --- eth/filters/api.go | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/eth/filters/api.go b/eth/filters/api.go index e21c82e6f2..6b27cd2f5b 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -175,11 +175,13 @@ func (api *FilterAPI) NewPendingTransactions(ctx context.Context, fullTx *bool) return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported } - rpcSub := notifier.CreateSubscription() + var ( + rpcSub = notifier.CreateSubscription() + txs = make(chan []*types.Transaction, 128) + pendingTxSub = api.events.SubscribePendingTxs(txs) + ) gopool.Submit(func() { - txs := make(chan []*types.Transaction, 128) - pendingTxSub := api.events.SubscribePendingTxs(txs) defer pendingTxSub.Unsubscribe() chainConfig := api.sys.backend.ChainConfig() @@ -309,11 +311,13 @@ func (api *FilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, error) { return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported } - rpcSub := notifier.CreateSubscription() + var ( + rpcSub = notifier.CreateSubscription() + headers = make(chan *types.Header) + headersSub = api.events.SubscribeNewHeads(headers) + ) gopool.Submit(func() { - headers := make(chan *types.Header) - headersSub := api.events.SubscribeNewHeads(headers) defer headersSub.Unsubscribe() for { From c951fe2d3e221786d33adbd31cf536d33d186db3 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Fri, 22 May 2026 14:01:24 +0800 Subject: [PATCH 11/48] eth/filters: rangeLogs should error on invalid block range (#33763) (#3688) * eth/filters: rangeLogs should error on invalid block range (#33763) Fixes log filter to reject out of order block ranges. * eth/filters: fix testFilters --------- Co-authored-by: vickkkkkyy --- eth/filters/filter.go | 2 +- eth/filters/filter_test.go | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/eth/filters/filter.go b/eth/filters/filter.go index b5b3812e25..f719eb766b 100644 --- a/eth/filters/filter.go +++ b/eth/filters/filter.go @@ -389,7 +389,7 @@ func (f *Filter) rangeLogs(ctx context.Context, firstBlock, lastBlock uint64) ([ } if firstBlock > lastBlock { - return nil, nil + return nil, errInvalidBlockRange } mb := f.sys.backend.NewMatcherBackend() defer mb.Close() diff --git a/eth/filters/filter_test.go b/eth/filters/filter_test.go index 1d67820cb5..1d9014af5f 100644 --- a/eth/filters/filter_test.go +++ b/eth/filters/filter_test.go @@ -360,7 +360,8 @@ func testFilters(t *testing.T, history uint64, noHistory bool) { want: `[{"address":"0xff00000000000000000000000000000000000000","topics":["0x0000000000000000000000000000000000000000000000000000746f70696333"],"data":"0x","blockNumber":"0x3e7","transactionHash":"0x53e3675800c6908424b61b35a44e51ca4c73ca603e58a65b32c67968b4f42200","transactionIndex":"0x0","blockHash":"0x2e4620a2b426b0612ec6cad9603f466723edaed87f98c9137405dd4f7a2409ff","logIndex":"0x0","removed":false}]`, }, { - f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil), + f: sys.NewRangeFilter(int64(rpc.LatestBlockNumber), int64(rpc.FinalizedBlockNumber), nil, nil, false), + err: errInvalidBlockRange.Error(), }, { f: sys.NewRangeFilter(int64(rpc.SafeBlockNumber), int64(rpc.LatestBlockNumber), nil, nil), From 86b8d9895984a36ce73043bab1055b386650a121 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Mon, 1 Jun 2026 17:13:24 +0800 Subject: [PATCH 12/48] internal/ethapi: limit number of calls to eth_simulateV1 (#34616) (#3681) Later on we can consider making these limits configurable if the use-case arose. Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com> --- internal/ethapi/api.go | 10 ++++++++++ internal/ethapi/simulate.go | 8 ++++++++ 2 files changed, 18 insertions(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 52ddcce568..7fe84f001f 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1143,6 +1143,16 @@ func (api *BlockChainAPI) SimulateV1(ctx context.Context, opts simOpts, blockNrO } else if len(opts.BlockStateCalls) > maxSimulateBlocks { return nil, &clientLimitExceededError{message: "too many blocks"} } + var totalCalls int + for _, block := range opts.BlockStateCalls { + if len(block.Calls) > maxSimulateCallsPerBlock { + return nil, &clientLimitExceededError{message: fmt.Sprintf("too many calls in block: %d > %d", len(block.Calls), maxSimulateCallsPerBlock)} + } + totalCalls += len(block.Calls) + if totalCalls > maxSimulateTotalCalls { + return nil, &clientLimitExceededError{message: fmt.Sprintf("too many calls: %d > %d", totalCalls, maxSimulateTotalCalls)} + } + } if blockNrOrHash == nil { n := rpc.BlockNumberOrHashWithNumber(rpc.LatestBlockNumber) blockNrOrHash = &n diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index 377ca33cab..729de6e6d3 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -44,6 +44,14 @@ const ( // in a single request. maxSimulateBlocks = 256 + // maxSimulateCallsPerBlock is the maximum number of calls allowed in a + // single simulated block. + maxSimulateCallsPerBlock = 5000 + + // maxSimulateTotalCalls is the maximum total number of calls allowed + // across all simulated blocks in a single request. + maxSimulateTotalCalls = 10000 + // timestampIncrement is the default increment between block timestamps. timestampIncrement = 12 ) From cb0973f4e5f26ef8419e0e5d633e9c32f71bacbf Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Mon, 1 Jun 2026 17:13:47 +0800 Subject: [PATCH 13/48] core: fix txLookupLock mutex leak on error returns in reorg() (#34039) (#3683) Co-authored-by: Mayveskii --- core/blockchain.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/blockchain.go b/core/blockchain.go index dc98248bf4..361be8c4bf 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -3011,6 +3011,7 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error // as the txlookups should be changed atomically, and all subsequent // reads should be blocked until the mutation is complete. bc.txLookupLock.Lock() + defer bc.txLookupLock.Unlock() // Reorg can be executed, start reducing the chain's old blocks and appending // the new blocks @@ -3117,9 +3118,6 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Header) error // Reset the tx lookup cache to clear stale txlookup cache. bc.txLookupCache.Purge() - // Release the tx-lookup lock after mutation. - bc.txLookupLock.Unlock() - return nil } From b7585c148559f13f2f2c7527028bcb5076dbb5c3 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Mon, 1 Jun 2026 17:15:44 +0800 Subject: [PATCH 14/48] core, internal/ethapi: fix incorrect max-initcode RPC error mapping (#3687) * core, internal/ethapi: fix incorrect max-initcode RPC error mapping (#34067) Problem: The max-initcode sentinel moved from core to vm, but RPC pre-check mapping still depended on core.ErrMaxInitCodeSizeExceeded. This mismatch could surface inconsistent error mapping when oversized initcode is submitted through JSON-RPC. Solution: - Remove core.ErrMaxInitCodeSizeExceeded from the core pre-check error set. - Map max-initcode validation errors in RPC from vm.ErrMaxInitCodeSizeExceeded. - Keep the RPC error code mapping unchanged (-38025). Impact: - Restores consistent max-initcode error mapping after the sentinel move. - Preserves existing JSON-RPC client expectations for error code -38025. - No consensus, state, or protocol behavior changes. * core/txpool: fix reference ErrMaxInitCodeSizeExceeded --------- Co-authored-by: Daniel Liu <139250065@qq.com> --- core/error.go | 4 ---- core/state_transition.go | 2 +- core/txpool/validation.go | 3 ++- internal/ethapi/errors.go | 2 +- 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/core/error.go b/core/error.go index 43002ce40b..1446e6e28f 100644 --- a/core/error.go +++ b/core/error.go @@ -68,10 +68,6 @@ var ( // have enough funds for transfer(topmost call only). ErrInsufficientFundsForTransfer = errors.New("insufficient funds for transfer") - // ErrMaxInitCodeSizeExceeded is returned if creation transaction provides the init code bigger - // than init code size limit. - ErrMaxInitCodeSizeExceeded = errors.New("max initcode size exceeded") - // ErrInsufficientBalanceWitness is returned if the transaction sender has enough // funds to cover the transfer, but not enough to pay for witness access/modification // costs for the transaction diff --git a/core/state_transition.go b/core/state_transition.go index 13c6433b75..2bfd1720b3 100644 --- a/core/state_transition.go +++ b/core/state_transition.go @@ -496,7 +496,7 @@ func (st *stateTransition) execute() (*ExecutionResult, error) { // Check whether the init code size has been exceeded. if rules.IsShanghai && contractCreation && len(msg.Data) > params.MaxInitCodeSize { - return nil, fmt.Errorf("%w: code size %v limit %v", ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) + return nil, fmt.Errorf("%w: code size %v limit %v", vm.ErrMaxInitCodeSizeExceeded, len(msg.Data), params.MaxInitCodeSize) } // Execute the preparatory steps for state transition which includes: diff --git a/core/txpool/validation.go b/core/txpool/validation.go index 1ec9aac07a..1c9e19b94b 100644 --- a/core/txpool/validation.go +++ b/core/txpool/validation.go @@ -25,6 +25,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" @@ -87,7 +88,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types } // Check whether the init code size has been exceeded if rules.IsShanghai && tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { - return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) + return fmt.Errorf("%w: code size %v, limit %v", vm.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) } if rules.IsOsaka && tx.Gas() > params.MaxTxGas { return fmt.Errorf("%w (cap: %d, tx: %d)", core.ErrGasLimitTooHigh, params.MaxTxGas, tx.Gas()) diff --git a/internal/ethapi/errors.go b/internal/ethapi/errors.go index 9908ca38c2..22baf39a19 100644 --- a/internal/ethapi/errors.go +++ b/internal/ethapi/errors.go @@ -146,7 +146,7 @@ func txValidationError(err error) *invalidTxError { return &invalidTxError{Message: err.Error(), Code: errCodeIntrinsicGas} case errors.Is(err, core.ErrInsufficientFundsForTransfer): return &invalidTxError{Message: err.Error(), Code: errCodeInsufficientFunds} - case errors.Is(err, core.ErrMaxInitCodeSizeExceeded): + case errors.Is(err, vm.ErrMaxInitCodeSizeExceeded): return &invalidTxError{Message: err.Error(), Code: errCodeMaxInitCodeSizeExceeded} } return &invalidTxError{ From 81eee44b2f0300f467db32e68c02fe4e491150d6 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Tue, 2 Jun 2026 16:46:31 +0800 Subject: [PATCH 15/48] internal/ethapi: limit number of getProofs keys (#34617) (#3680) * internal/ethapi: limit number of getProofs keys (#34617) We can consider making this limit configurable if ever the need arose. * internal/ethapi: remove maxGetStorageSlots --------- Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com> --- internal/ethapi/api.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 7fe84f001f..76225c43c3 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -62,6 +62,10 @@ const UnHealthyTimeout = 5 * time.Second // allowed to produce in order to speed up calculations. const estimateGasErrorRatio = 0.015 +// maxGetProofKeys is the maximum number of storage keys that can be +// requested in a single eth_getProof call. +const maxGetProofKeys = 1024 + var errBlobTxNotSupported = errors.New("signing blob transactions not supported") var errSubClosed = errors.New("chain subscription closed") @@ -374,6 +378,9 @@ func (n *proofList) Delete(key []byte) error { // GetProof returns the Merkle-proof for a given account and optionally some storage keys. func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address, storageKeys []string, blockNrOrHash rpc.BlockNumberOrHash) (*AccountResult, error) { + if len(storageKeys) > maxGetProofKeys { + return nil, &invalidParamsError{fmt.Sprintf("too many storage keys requested (max %d, got %d)", maxGetProofKeys, len(storageKeys))} + } var ( keys = make([]common.Hash, len(storageKeys)) keyLengths = make([]int, len(storageKeys)) @@ -406,6 +413,9 @@ func (api *BlockChainAPI) GetProof(ctx context.Context, address common.Address, } // Create the proofs for the storageKeys. for i, key := range keys { + if err := ctx.Err(); err != nil { + return nil, err + } // Output key encoding is a bit special: if the input was a 32-byte hash, it is // returned as such. Otherwise, we apply the QUANTITY encoding mandated by the // JSON-RPC spec for getProof. This behavior exists to preserve backwards From a89043dfa694e617cb1cee0c6da703615b34faa9 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Wed, 3 Jun 2026 14:17:16 +0800 Subject: [PATCH 16/48] internal/ethapi: fix gas cap for eth_simulateV1 (#33952) (#3682) Fixes a regression in #33593 where a block gas limit > gasCap resulted in more execution than the gas cap. Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com> --- internal/ethapi/api.go | 15 +++------ internal/ethapi/api_test.go | 5 ++- internal/ethapi/simulate.go | 55 ++++++++++++++++++++++++++++---- internal/ethapi/simulate_test.go | 5 ++- 4 files changed, 60 insertions(+), 20 deletions(-) diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 76225c43c3..c1e9f2c5b3 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -1171,17 +1171,12 @@ func (api *BlockChainAPI) SimulateV1(ctx context.Context, opts simOpts, blockNrO if state == nil || err != nil { return nil, err } - gasCap := api.b.RPCGasCap() - if gasCap == 0 { - gasCap = gomath.MaxUint64 - } sim := &simulator{ - b: api.b, - state: state, - base: base, - chainConfig: api.b.ChainConfig(), - // Each tx and all the series of txes shouldn't consume more gas than cap - gp: new(core.GasPool).AddGas(gasCap), + b: api.b, + state: state, + base: base, + chainConfig: api.b.ChainConfig(), + budget: newGasBudget(api.b.RPCGasCap()), traceTransfers: opts.TraceTransfers, validate: opts.Validation, fullTx: opts.ReturnFullTransactions, diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 4163de350c..89dea5ee44 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -25,7 +25,6 @@ import ( "errors" "fmt" "maps" - "math" "math/big" "os" "path/filepath" @@ -2544,7 +2543,7 @@ func TestSimulateV1ChainLinkage(t *testing.T) { state: stateDB, base: baseHeader, chainConfig: backend.ChainConfig(), - gp: new(core.GasPool).AddGas(math.MaxUint64), + budget: newGasBudget(0), traceTransfers: false, validate: false, fullTx: false, @@ -2629,7 +2628,7 @@ func TestSimulateV1TxSender(t *testing.T) { state: stateDB, base: baseHeader, chainConfig: backend.ChainConfig(), - gp: new(core.GasPool).AddGas(math.MaxUint64), + budget: newGasBudget(0), traceTransfers: false, validate: false, fullTx: true, diff --git a/internal/ethapi/simulate.go b/internal/ethapi/simulate.go index 729de6e6d3..e7dabada59 100644 --- a/internal/ethapi/simulate.go +++ b/internal/ethapi/simulate.go @@ -21,6 +21,7 @@ import ( "encoding/json" "errors" "fmt" + "math" "math/big" "time" @@ -176,6 +177,39 @@ func (m *simChainHeadReader) GetVerifiedBlockByHash(hash common.Hash) *types.Hea return m.Backend.Chain().GetVerifiedBlockByHash(hash) } +// gasBudget tracks the remaining gas allowed across all simulated blocks. +// It enforces the RPC-level gas cap to prevent DoS. +type gasBudget struct { + remaining uint64 +} + +// newGasBudget creates a gas budget with the given cap. +// A cap of 0 is treated as unlimited. +func newGasBudget(cap uint64) *gasBudget { + if cap == 0 { + cap = math.MaxUint64 + } + return &gasBudget{remaining: cap} +} + +// cap returns the given gas value clamped to the remaining budget. +func (b *gasBudget) cap(gas uint64) uint64 { + if gas > b.remaining { + return b.remaining + } + return gas +} + +// consume deducts the given amount from the budget. +// Returns an error if the amount exceeds the remaining budget. +func (b *gasBudget) consume(amount uint64) error { + if amount > b.remaining { + return fmt.Errorf("RPC gas cap exhausted: need %d, remaining %d", amount, b.remaining) + } + b.remaining -= amount + return nil +} + // simulator is a stateful object that simulates a series of blocks. // it is not safe for concurrent use. type simulator struct { @@ -183,7 +217,7 @@ type simulator struct { state *state.StateDB base *types.Header chainConfig *params.ChainConfig - gp *core.GasPool + budget *gasBudget traceTransfers bool validate bool fullTx bool @@ -269,6 +303,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, } var ( gasUsed, blobGasUsed uint64 + gp = new(core.GasPool).AddGas(blockContext.GasLimit) txes = make([]*types.Transaction, len(block.Calls)) callResults = make([]simCallResult, len(block.Calls)) receipts = make([]*types.Receipt, len(block.Calls)) @@ -317,7 +352,7 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, sim.state.SetTxContext(txHash, i) // EoA check is always skipped, even in validation mode. msg := call.ToMessage(header.BaseFee, !sim.validate) - result, err := applyMessageWithEVM(ctx, evm, msg, timeout, sim.gp) + result, err := applyMessageWithEVM(ctx, evm, msg, timeout, gp) if err != nil { txErr := txValidationError(err) return nil, nil, nil, txErr @@ -332,6 +367,13 @@ func (sim *simulator) processBlock(ctx context.Context, block *simBlock, header, gasUsed += result.UsedGas receipts[i] = core.MakeReceipt(evm, result, sim.state, blockContext.BlockNumber, common.Hash{}, blockContext.Time, tx, gasUsed, root) blobGasUsed += receipts[i].BlobGasUsed + + // Make sure the gas cap is still enforced. It's only for + // internally protection. + if err := sim.budget.consume(result.UsedGas); err != nil { + return nil, nil, nil, err + } + logs := tracer.Logs() callRes := simCallResult{ReturnValue: result.Return(), Logs: logs, GasUsed: hexutil.Uint64(result.UsedGas)} if result.Failed() { @@ -408,10 +450,11 @@ func (sim *simulator) sanitizeCall(call *TransactionArgs, state vm.StateDB, head if *gasUsed+uint64(*call.Gas) > blockContext.GasLimit { return &blockGasLimitReachedError{fmt.Sprintf("block gas limit reached: %d >= %d", gasUsed, blockContext.GasLimit)} } - if err := call.CallDefaults(sim.gp.Gas(), header.BaseFee, sim.chainConfig.ChainID); err != nil { - return err - } - return nil + // Clamp to the cross-block gas budget. + gas := sim.budget.cap(uint64(*call.Gas)) + call.Gas = (*hexutil.Uint64)(&gas) + + return call.CallDefaults(0, header.BaseFee, sim.chainConfig.ChainID) } func (sim *simulator) activePrecompiles(base *types.Header) vm.PrecompiledContracts { diff --git a/internal/ethapi/simulate_test.go b/internal/ethapi/simulate_test.go index c747b76477..6a83e744de 100644 --- a/internal/ethapi/simulate_test.go +++ b/internal/ethapi/simulate_test.go @@ -80,7 +80,10 @@ func TestSimulateSanitizeBlockOrder(t *testing.T) { err: "block timestamps must be in order: 72 <= 72", }, } { - sim := &simulator{base: &types.Header{Number: big.NewInt(int64(tc.baseNumber)), Time: tc.baseTimestamp}} + sim := &simulator{ + base: &types.Header{Number: big.NewInt(int64(tc.baseNumber)), Time: tc.baseTimestamp}, + budget: newGasBudget(0), + } res, err := sim.sanitizeChain(tc.blocks) if err != nil { if err.Error() == tc.err { From 46d72d716dd2708bce8b76d6bd55e4d8ae3f3b04 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Mon, 8 Jun 2026 09:59:40 +0800 Subject: [PATCH 17/48] core/tracing: fix nonce revert edge case (#33978) (#3685) We got a report for a bug in the tracing journal which has the responsibility to emit events for all state that must be reverted. The edge case is as follows: on CREATE operations the nonce is incremented. When a create frame reverts, the nonce increment associated with it does **not** revert. This works fine on master. Now one step further: if the parent frame reverts tho, the nonce **should** revert and there is the bug. Co-authored-by: Sina M <1591639+s1na@users.noreply.github.com> --- core/tracing/journal.go | 16 ++++++++++++---- core/tracing/journal_test.go | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/core/tracing/journal.go b/core/tracing/journal.go index 62a70d6c27..560c937115 100644 --- a/core/tracing/journal.go +++ b/core/tracing/journal.go @@ -155,10 +155,18 @@ func (j *journal) OnBalanceChange(addr common.Address, prev, new *big.Int, reaso } func (j *journal) OnNonceChangeV2(addr common.Address, prev, new uint64, reason NonceChangeReason) { - // When a contract is created, the nonce of the creator is incremented. - // This change is not reverted when the creation fails. - if reason != NonceChangeContractCreator { - j.entries = append(j.entries, nonceChange{addr: addr, prev: prev, new: new}) + j.entries = append(j.entries, nonceChange{addr: addr, prev: prev, new: new}) + if reason == NonceChangeContractCreator { + // When a contract is created via CREATE/CREATE2, the creator's nonce is + // incremented. The EVM does not revert this when the CREATE frame itself + // fails (the nonce change happens before the EVM snapshot). However, if + // a parent frame reverts, the nonce must be reverted along with everything + // else. + // + // To achieve this, advance the current frame's revision point past this + // entry. The CREATE frame's revert won't touch it (it's below the revision), + // but a parent frame's revert will (it's above the parent's revision). + j.revisions[len(j.revisions)-1] = len(j.entries) } if j.hooks.OnNonceChangeV2 != nil { j.hooks.OnNonceChangeV2(addr, prev, new, reason) diff --git a/core/tracing/journal_test.go b/core/tracing/journal_test.go index e00447f5f3..488d192502 100644 --- a/core/tracing/journal_test.go +++ b/core/tracing/journal_test.go @@ -219,6 +219,42 @@ func TestNonceIncOnCreate(t *testing.T) { } } +// TestNonceIncOnCreateParentReverts checks that the creator's nonce increment +// from CREATE survives the CREATE frame's own revert but is properly reverted +// when the parent call frame reverts. +func TestNonceIncOnCreateParentReverts(t *testing.T) { + const opCREATE = 0xf0 + + tr := &testTracer{t: t} + wr, err := WrapWithJournal(&Hooks{OnNonceChange: tr.OnNonceChange}) + if err != nil { + t.Fatalf("failed to wrap test tracer: %v", err) + } + + addr := common.HexToAddress("0x1234") + { + // Parent call frame + wr.OnEnter(0, 0, addr, addr, nil, 1000, big.NewInt(0)) + { + // CREATE frame — creator nonce incremented, then CREATE reverts + wr.OnEnter(1, opCREATE, addr, addr, nil, 1000, big.NewInt(0)) + wr.OnNonceChangeV2(addr, 0, 1, NonceChangeContractCreator) + wr.OnExit(1, nil, 100, errors.New("revert"), true) + } + // After CREATE reverts, nonce should still be 1 + if tr.nonce != 1 { + t.Fatalf("nonce after CREATE revert: got %v, want 1", tr.nonce) + } + // Parent frame also reverts + wr.OnExit(0, nil, 150, errors.New("revert"), true) + } + + // After parent reverts, nonce should be back to 0 + if tr.nonce != 0 { + t.Fatalf("nonce after parent revert: got %v, want 0", tr.nonce) + } +} + func TestOnNonceChangeV2(t *testing.T) { tr := &testTracer{t: t} wr, err := WrapWithJournal(&Hooks{OnNonceChangeV2: tr.OnNonceChangeV2}) From 4e4afee98a03e83f57a214906d7eb754c038c286 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:53:26 +0800 Subject: [PATCH 18/48] crypto: add hash length check in nocgo VerifySignature (#33839) (#3700) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick of go-ethereum 8581125a2 (PR #33839). The cgo path in secp256k1/secp256.go already rejects non-32-byte hashes, but the nocgo (pure-Go) path did not. PR #33104 added the check to Sign and sigToPub but missed VerifySignature. Without it, a wrong-length hash gets passed to decred's Verify and silently gives a bogus result — a truncated hash may match a different signature, an extended hash silently ignores extra bytes. Co-authored-by: Claude Opus 4.7 (1M context) --- crypto/signature_nocgo.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index 25ef01b3ed..6ac1946829 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -99,7 +99,7 @@ func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) { // The public key should be in compressed (33 bytes) or uncompressed (65 bytes) format. // The signature should have the 64 byte [R || S] format. func VerifySignature(pubkey, hash, signature []byte) bool { - if len(signature) != 64 { + if len(signature) != 64 || len(hash) != DigestLength { return false } var r, s secp256k1.ModNScalar From d0e8f9b6d12a1e1796c6f3011730839c58849872 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:54:12 +0800 Subject: [PATCH 19/48] p2p/discover: decouple nodeFeed from Table mutex in waitForNodes (#34898) (#3710) Fixes #34881 This fixes a hang in `Table.waitForNodes`. It is a replacement for PRs - #34890 doesn't really fix the issue, just makes it less likely - #33665 tries to fix it by moving the feed send outside of the lock I created this PR because I want to keep the synchronous node feed sending in `Table.nodeAdded`. --------- Co-authored-by: Felix Lange Co-authored-by: Csaba Kiraly --- p2p/discover/table.go | 55 +++++++++++++++++++++++++++++--------- p2p/discover/table_test.go | 40 +++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 12 deletions(-) diff --git a/p2p/discover/table.go b/p2p/discover/table.go index 14dcb8fe3c..dade4c36da 100644 --- a/p2p/discover/table.go +++ b/p2p/discover/table.go @@ -764,6 +764,41 @@ func (tab *Table) deleteNode(n *enode.Node) { // waitForNodes blocks until the table contains at least n nodes. func (tab *Table) waitForNodes(ctx context.Context, n int) error { + // Wrap ctx so the forwarder goroutine exits when waitForNodes returns, + // regardless of whether the caller's ctx is canceled. + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + // Set up a notification channel that gets unblocked when there was any activity on + // the table. Ultimately this reads from the table's nodeFeed, but can't use the feed + // directly on the same goroutine that takes Table.mutex, it would deadlock. + var notify chan struct{} + var notifyErr error + initsub := func() event.Subscription { + notify = make(chan struct{}, 1) + newnode := make(chan *enode.Node, 1) + sub := tab.nodeFeed.Subscribe(newnode) + go func() { + defer close(notify) + for { + select { + case <-newnode: + select { + case notify <- struct{}{}: + default: + } + case <-ctx.Done(): + notifyErr = ctx.Err() + return + case <-tab.closeReq: + notifyErr = errClosed + return + } + } + }() + return sub + } + getlength := func() (count int) { for _, b := range &tab.buckets { count += len(b.entries) @@ -771,28 +806,24 @@ func (tab *Table) waitForNodes(ctx context.Context, n int) error { return count } - var ch chan *enode.Node for { tab.mutex.Lock() if getlength() >= n { tab.mutex.Unlock() return nil } - if ch == nil { - // Init subscription. - ch = make(chan *enode.Node) - sub := tab.nodeFeed.Subscribe(ch) + if notify == nil { + // Lazily init the subscription. Do this while holding the + // lock so we don't miss any events that change the node count. + sub := initsub() defer sub.Unsubscribe() } tab.mutex.Unlock() - // Wait for a node add event. - select { - case <-ch: - case <-ctx.Done(): - return ctx.Err() - case <-tab.closeReq: - return errClosed + // Wait for table event. + if _, ok := <-notify; !ok { + break } } + return notifyErr } diff --git a/p2p/discover/table_test.go b/p2p/discover/table_test.go index ae981f8b28..1e7881423e 100644 --- a/p2p/discover/table_test.go +++ b/p2p/discover/table_test.go @@ -17,6 +17,7 @@ package discover import ( + "context" "crypto/ecdsa" "fmt" "math/rand" @@ -529,6 +530,45 @@ func quickcfg() *quick.Config { } } +// This test checks that waitForNodes does not block addFoundNode. +// See https://github.com/ethereum/go-ethereum/issues/34881. +func TestTable_waitForNodesLocking(t *testing.T) { + transport := newPingRecorder() + tab, db := newTestTable(transport, Config{}) + defer db.Close() + defer tab.close() + <-tab.initDone + + // waitForNodes will never reach this count, so it stays subscribed + // to nodeFeed and looping for the duration of the test. + waitCtx, cancelWait := context.WithCancel(context.Background()) + defer cancelWait() + waitDone := make(chan struct{}) + go func() { + defer close(waitDone) + tab.waitForNodes(waitCtx, 1<<20) + }() + + // Call addFoundNode in loop to send to the feed. + addDone := make(chan struct{}) + go func() { + defer close(addDone) + for i := range 10000 { + d := 240 + (i % 17) + n := nodeAtDistance(tab.self().ID(), d, intIP(i)) + tab.addFoundNode(n, true) + } + }() + + select { + case <-addDone: + cancelWait() + <-waitDone + case <-time.After(10 * time.Second): + t.Fatal("deadlock detected: add loop did not finish within 10s") + } +} + func newkey() *ecdsa.PrivateKey { key, err := crypto.GenerateKey() if err != nil { From d17d9a7ef123fc20ea3b1fbc320cc315729c4182 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Mon, 8 Jun 2026 13:55:05 +0800 Subject: [PATCH 20/48] eth/downloader: drop invalid peers + fix deliver index (#34745, #34870) (#3708) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * eth/downloader: drop peers sending invalid bodies or receipts (#34745) Cherry-pick of go-ethereum 75a64ee34 (PR #34745). - Fixes an error shadowing issue in the deliver() function, where a stale result from GetDeliverySlot caused the original failure to be overwritten by errStaleDelivery. - Adds errInvalidBody and errInvalidReceipt propagation via res.Done so the eth protocol handler tears down the connection of peers sending invalid responses, instead of just adjusting capacity while keeping the peer connected. Co-Authored-By: Claude Opus 4.7 (1M context) * eth/downloader: use batch index in deliver reconstruct (#34870) Cherry-pick of go-ethereum 5b837e578 (PR #34870). reconstruct() indexes into the parallel response slices (bodies, receipts). After PR #34745 (now applied in this stack) moved `accepted++` inside the success branch, passing `accepted` to `reconstruct()` underflowed the response index whenever an earlier header in the same batch hit a stale slot — the next successful slot would read from the wrong response slice element. Switch to the loop's range index `k`, which always tracks the response position regardless of stale gaps. NOTE: based on `fix/downloader-drop-invalid-peers` (PR #3699) — must land after / merged together with that PR. Co-Authored-By: Claude Opus 4.7 (1M context) --------- Co-authored-by: Claude Opus 4.7 (1M context) --- eth/downloader/downloader_test.go | 35 ++++++++++++++++++- eth/downloader/fetchers_concurrent.go | 49 +++++++++++++++++---------- eth/downloader/queue.go | 33 +++++++++--------- 3 files changed, 82 insertions(+), 35 deletions(-) diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go index 7a0dcb4590..158994c689 100644 --- a/eth/downloader/downloader_test.go +++ b/eth/downloader/downloader_test.go @@ -116,6 +116,7 @@ func (dl *downloadTester) newPeer(id string, version uint, blocks []*types.Block id: id, chain: newTestBlockchain(blocks), withholdHeaders: make(map[common.Hash]struct{}), + dropped: make(chan error, 1), } dl.peers[id] = peer @@ -144,6 +145,9 @@ type downloadTesterPeer struct { chain *core.BlockChain withholdHeaders map[common.Hash]struct{} + corruptBodies bool // if set, the peer serves incorrect bodies + + dropped chan error // signaled when res.Done receives an error } func (dlp *downloadTesterPeer) MarkLagging() { @@ -279,6 +283,11 @@ func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *et txsHashes[i] = types.DeriveSha(types.Transactions(body.Transactions), hasher) uncleHashes[i] = types.CalcUncleHash(body.Uncles) } + if dlp.corruptBodies { + for i := range txsHashes { + txsHashes[i] = common.Hash{0xff} + } + } req := ð.Request{ Peer: dlp.id, } @@ -291,10 +300,16 @@ func (dlp *downloadTesterPeer) RequestBodies(hashes []common.Hash, sink chan *et WithdrawalRoots: withdrawalHashes, }, Time: 1, - Done: make(chan error, 1), // Ignore the returned status + Done: make(chan error), } go func() { sink <- res + if err := <-res.Done; err != nil { + select { + case dlp.dropped <- err: + default: + } + } }() return req, nil } @@ -1263,3 +1278,21 @@ func TestRemoteHeaderRequestSpan(t *testing.T) { } } } + +// TestInvalidBodyPeerDrop verifies that a peer serving corrupted block bodies +// is signalled through res.Done so the eth protocol handler can drop it. +func TestInvalidBodyPeerDrop(t *testing.T) { + tester := newTester(t) + defer tester.terminate() + + chain := testChainBase.shorten(blockCacheMaxItems - 15) + peer := tester.newPeer("corrupt", eth.ETH68, chain.blocks[1:]) + peer.corruptBodies = true + + go tester.sync("corrupt", nil, FullSync) + select { + case <-peer.dropped: + case <-time.After(1 * time.Minute): + t.Fatal("peer was not dropped") + } +} diff --git a/eth/downloader/fetchers_concurrent.go b/eth/downloader/fetchers_concurrent.go index 2e485d028d..cb0f4ba63d 100644 --- a/eth/downloader/fetchers_concurrent.go +++ b/eth/downloader/fetchers_concurrent.go @@ -357,25 +357,32 @@ func (d *Downloader) concurrentFetch(queue typedQueue, beaconMode bool) error { delete(pending, res.Req.Peer) delete(stales, res.Req.Peer) - // Signal the dispatcher that the round trip is done. We'll drop the - // peer if the data turns out to be junk. - res.Done <- nil - res.Req.Close() - // If the peer was previously banned and failed to deliver its pack // in a reasonable time frame, ignore its message. - if peer := d.peers.Peer(res.Req.Peer); peer != nil { - // Deliver the received chunk of data and check chain validity - accepted, err := queue.deliver(peer, res) - if errors.Is(err, errInvalidChain) { - return err - } - // Unless a peer delivered something completely else than requested (usually - // caused by a timed out request which came through in the end), set it to - // idle. If the delivery's stale, the peer should have already been idled. - if !errors.Is(err, errStaleDelivery) { - queue.updateCapacity(peer, accepted, res.Time) - } + peer := d.peers.Peer(res.Req.Peer) + if peer == nil { + res.Done <- nil + res.Req.Close() + continue + } + // Deliver the received chunk of data and check chain validity + accepted, err := queue.deliver(peer, res) + // Unless a peer delivered something completely else than requested (usually + // caused by a timed out request which came through in the end), set it to + // idle. If the delivery's stale, the peer should have already been idled. + if !errors.Is(err, errStaleDelivery) { + queue.updateCapacity(peer, accepted, res.Time) + } + res.Done <- validityErrorOfRequest(err) + res.Req.Close() + + if errors.Is(err, errInvalidChain) { + // errInvalidChain is the signal that processing of items failed internally, + // even though the items were validly encoded. + // + // This can be due to invalid blocks, or a database error. + // The sync cycle should be aborted for such errors, so we return it here. + return err } case cont := <-queue.waker(): @@ -386,3 +393,11 @@ func (d *Downloader) concurrentFetch(queue typedQueue, beaconMode bool) error { } } } + +// validityErrorOfRequest returns err if it is related to block validity, and nil otherwise. +func validityErrorOfRequest(err error) error { + if errors.Is(err, errInvalidBody) || errors.Is(err, errInvalidReceipt) { + return err + } + return nil +} diff --git a/eth/downloader/queue.go b/eth/downloader/queue.go index 8f2845f240..e9e93dd6fa 100644 --- a/eth/downloader/queue.go +++ b/eth/downloader/queue.go @@ -918,10 +918,10 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, } // Assemble each of the results with their headers and retrieved data parts var ( - accepted int - failure error - i int - hashes []common.Hash + accepted int + failure error + i int + foundStale bool ) for _, header := range request.Headers { // Short circuit assembly if no more fetch results are found @@ -933,42 +933,41 @@ func (q *queue) deliver(id string, taskPool map[common.Hash]*types.Header, failure = err break } - hashes = append(hashes, header.Hash()) i++ } - for _, header := range request.Headers[:i] { + for k, header := range request.Headers[:i] { if res, stale, err := q.resultCache.GetDeliverySlot(header.Number.Uint64()); err == nil && !stale { - reconstruct(accepted, res) + reconstruct(k, res) + accepted++ } else { - // else: between here and above, some other peer filled this result, + // Between here and above, some other peer filled this result, // or it was indeed a no-op. This should not happen, but if it does it's // not something to panic about log.Error("Delivery stale", "stale", stale, "number", header.Number.Uint64(), "err", err) - failure = errStaleDelivery + foundStale = true } // Clean up a successful fetch - delete(taskPool, hashes[accepted]) - accepted++ + delete(taskPool, header.Hash()) } resDropMeter.Mark(int64(results - accepted)) // Return all failed or missing fetches to the queue - for _, header := range request.Headers[accepted:] { + for _, header := range request.Headers[i:] { taskQueue.Push(header, -int64(header.Number.Uint64())) } // Wake up Results if accepted > 0 { q.active.Signal() } - if failure == nil { - return accepted, nil + if failure != nil { + return accepted, failure } // If none of the data was good, it's a stale delivery - if accepted > 0 { - return accepted, fmt.Errorf("partial failure: %v", failure) + if foundStale { + return accepted, errStaleDelivery } - return accepted, fmt.Errorf("%w: %v", failure, errStaleDelivery) + return accepted, nil } // Prepare configures the result cache to allow accepting and caching inbound From a89c7ad0b26c117897c9c8bbc598316722ad3796 Mon Sep 17 00:00:00 2001 From: wayen <19421226+flywukong@users.noreply.github.com> Date: Mon, 8 Jun 2026 15:10:03 +0800 Subject: [PATCH 21/48] ethdb,trie: remove multidb code from bsc (#3716) * cmd, core/rawdb: remove multidatabase CLI support * node, eth: remove multidatabase open wiring * core, trie, eth: read state from the single database * ethdb, core/rawdb: remove the StateStore abstraction --- cmd/geth/chaincmd.go | 20 +---- cmd/geth/dbcmd.go | 95 ++++----------------- cmd/geth/main.go | 1 - cmd/utils/flags.go | 25 ------ core/blockchain.go | 6 +- core/rawdb/accessors_trie.go | 6 +- core/rawdb/ancient_utils.go | 11 +-- core/rawdb/database.go | 158 ----------------------------------- core/rawdb/table.go | 16 ---- core/state/pruner/pruner.go | 27 ++---- core/state/sync_test.go | 10 +-- eth/backend.go | 2 +- eth/protocols/snap/sync.go | 53 +++--------- ethdb/database.go | 14 ---- ethdb/memorydb/memorydb.go | 9 -- ethdb/remotedb/remotedb.go | 16 ---- node/errors.go | 7 +- node/node.go | 59 ------------- trie/sync.go | 30 ++----- trie/sync_test.go | 16 ++-- triedb/database.go | 19 ++--- 21 files changed, 71 insertions(+), 529 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 7a5a3452ac..9d207c6ba8 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -77,7 +77,6 @@ var ( utils.OverrideBPO2, utils.OverridePasteur, utils.OverrideVerkle, - // utils.MultiDataBaseFlag, }, utils.DatabaseFlags), Description: ` The init command initializes a new genesis block and definition for the network. @@ -378,17 +377,6 @@ func initGenesis(ctx *cli.Context) error { chaindb := utils.MakeChainDatabase(ctx, stack, false) defer chaindb.Close() - name := "chaindata" - // if the trie data dir has been set, new trie db with a new state database - if ctx.IsSet(utils.MultiDataBaseFlag.Name) { - statediskdb, dbErr := stack.OpenDatabaseWithFreezer(name+"/state", 0, 0, "", "", false) - if dbErr != nil { - utils.Fatalf("Failed to open separate trie database: %v", dbErr) - } - chaindb.SetStateStore(statediskdb) - log.Warn("Multi-database is an experimental feature") - } - triedb := utils.MakeTrieDatabase(ctx, stack, chaindb, ctx.Bool(utils.CachePreimagesFlag.Name), false, genesis.IsVerkle(), false) defer triedb.Close() @@ -399,7 +387,7 @@ func initGenesis(ctx *cli.Context) error { if compatErr != nil { utils.Fatalf("Failed to write chain config: %v", compatErr) } - log.Info("Successfully wrote genesis state", "database", name, "hash", hash.String()) + log.Info("Successfully wrote genesis state", "hash", hash.String()) return nil } @@ -772,12 +760,6 @@ func dumpGenesis(ctx *cli.Context) error { } defer db.Close() - // set the separate state & block database - if stack.CheckIfMultiDataBase() && err == nil { - stateDiskDb := utils.MakeStateDataBase(ctx, stack, true) - db.SetStateStore(stateDiskDb) - } - genesis, err = core.ReadGenesis(db) if err != nil { utils.Fatalf("failed to read genesis: %s", err) diff --git a/cmd/geth/dbcmd.go b/cmd/geth/dbcmd.go index 75971473fb..09901fac76 100644 --- a/cmd/geth/dbcmd.go +++ b/cmd/geth/dbcmd.go @@ -550,7 +550,7 @@ func checkStateContent(ctx *cli.Context) error { lastLog = time.Now() ) - it = rawdb.NewKeyLengthIterator(db.GetStateStore().NewIterator(prefix, start), 32) + it = rawdb.NewKeyLengthIterator(db.NewIterator(prefix, start), 32) for it.Next() { count++ k := it.Key() @@ -593,10 +593,6 @@ func dbStats(ctx *cli.Context) error { defer db.Close() showDBStats(db) - if db.HasSeparateStateStore() { - fmt.Println("show stats of state store") - showDBStats(db.GetStateStore()) - } return nil } @@ -611,30 +607,14 @@ func dbCompact(ctx *cli.Context) error { log.Info("Stats before compaction") showDBStats(db) - if stack.CheckIfMultiDataBase() { - fmt.Println("show stats of state store") - showDBStats(db.GetStateStore()) - } - log.Info("Triggering compaction") if err := db.Compact(nil, nil); err != nil { log.Error("Compact err", "error", err) return err } - if stack.CheckIfMultiDataBase() { - if err := db.GetStateStore().Compact(nil, nil); err != nil { - log.Error("Compact err", "error", err) - return err - } - } - log.Info("Stats after compaction") showDBStats(db) - if stack.CheckIfMultiDataBase() { - fmt.Println("show stats of state store after compaction") - showDBStats(db.GetStateStore()) - } return nil } @@ -654,12 +634,7 @@ func dbGet(ctx *cli.Context) error { log.Info("Could not decode the key", "error", err) return err } - opDb := db - if stack.CheckIfMultiDataBase() && rawdb.DataTypeByKey(key) == rawdb.StateDataType { - opDb = db.GetStateStore() - } - - data, err := opDb.Get(key) + data, err := db.Get(key) if err != nil { log.Info("Get operation failed", "key", fmt.Sprintf("%#x", key), "error", err) return err @@ -676,10 +651,8 @@ func dbTrieGet(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - var db ethdb.Database - chaindb := utils.MakeChainDatabase(ctx, stack, true) - db = chaindb.GetStateStore() - defer chaindb.Close() + db := utils.MakeChainDatabase(ctx, stack, true) + defer db.Close() scheme := ctx.String(utils.StateSchemeFlag.Name) if scheme == "" { @@ -744,10 +717,8 @@ func dbTrieDelete(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) defer stack.Close() - var db ethdb.Database - chaindb := utils.MakeChainDatabase(ctx, stack, true) - db = chaindb.GetStateStore() - defer chaindb.Close() + db := utils.MakeChainDatabase(ctx, stack, true) + defer db.Close() scheme := ctx.String(utils.StateSchemeFlag.Name) if scheme == "" { @@ -815,16 +786,11 @@ func dbDelete(ctx *cli.Context) error { log.Info("Could not decode the key", "error", err) return err } - opDb := db - if opDb.HasSeparateStateStore() && rawdb.DataTypeByKey(key) == rawdb.StateDataType { - opDb = db.GetStateStore() - } - - data, err := opDb.Get(key) + data, err := db.Get(key) if err == nil { fmt.Printf("Previous value: %#x\n", data) } - if err = opDb.Delete(key); err != nil { + if err = db.Delete(key); err != nil { log.Info("Delete operation returned an error", "key", fmt.Sprintf("%#x", key), "error", err) return err } @@ -843,36 +809,8 @@ func dbDeleteTrieState(ctx *cli.Context) error { db := utils.MakeChainDatabase(ctx, stack, false) defer db.Close() - var ( - err error - start = time.Now() - ) - - // If separate trie db exists, delete all files in the db folder - if db.HasSeparateStateStore() { - statePath := filepath.Join(stack.ResolvePath("chaindata"), "state") - log.Info("Removing separate trie database", "path", statePath) - err = filepath.Walk(statePath, func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - if path != statePath { - fileInfo, err := os.Lstat(path) - if err != nil { - return err - } - if !fileInfo.IsDir() { - os.Remove(path) - } - } - return nil - }) - log.Info("Separate trie database deleted", "err", err, "elapsed", common.PrettyDuration(time.Since(start))) - return err - } - // Delete KV pairs from the database - err = rawdb.DeleteTrieState(db) + err := rawdb.DeleteTrieState(db) if err != nil { return err } @@ -891,7 +829,7 @@ func dbDeleteTrieState(ctx *cli.Context) error { } log.Info("Removing ancient state database", "path", dbPath) - start = time.Now() + start := time.Now() filepath.Walk(dbPath, func(path string, info os.FileInfo, err error) error { if dbPath == path { return nil @@ -935,16 +873,11 @@ func dbPut(ctx *cli.Context) error { return err } - opDb := db - if db.HasSeparateStateStore() && rawdb.DataTypeByKey(key) == rawdb.StateDataType { - opDb = db.GetStateStore() - } - - data, err = opDb.Get(key) + data, err = db.Get(key) if err == nil { fmt.Printf("Previous value: %#x\n", data) } - return opDb.Put(key, value) + return db.Put(key, value) } // dbDumpTrie shows the key-value slots of a given storage trie @@ -1035,7 +968,7 @@ func freezerInspect(ctx *cli.Context) error { stack, _ := makeConfigNode(ctx) ancient := stack.ResolveAncient("chaindata", ctx.String(utils.AncientFlag.Name)) stack.Close() - return rawdb.InspectFreezerTable(ancient, freezer, table, start, end, stack.CheckIfMultiDataBase()) + return rawdb.InspectFreezerTable(ancient, freezer, table, start, end) } func importLDBdata(ctx *cli.Context) error { @@ -1307,7 +1240,7 @@ func inspectHistory(ctx *cli.Context) error { if header == nil { return 0, fmt.Errorf("block #%d is not existent", blockNumber) } - id := rawdb.ReadStateID(db.GetStateStore(), header.Root) + id := rawdb.ReadStateID(db, header.Root) if id == nil { first, last, err := triedb.HistoryRange() if err == nil { diff --git a/cmd/geth/main.go b/cmd/geth/main.go index b4d00d40c5..46ba1e36e9 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -134,7 +134,6 @@ var ( utils.CacheSnapshotFlag, // utils.CacheNoPrefetchFlag, utils.CachePreimagesFlag, - // utils.MultiDataBaseFlag, utils.PruneAncientDataFlag, // deprecated utils.CacheLogSizeFlag, utils.FDLimitFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index c0749f5a23..1d56caff57 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -97,12 +97,6 @@ var ( Value: flags.DirectoryString(node.DefaultDataDir()), Category: flags.EthCategory, } - MultiDataBaseFlag = &cli.BoolFlag{ - Name: "multidatabase", - Usage: "Enable a separated state database, it will be created subdirectory called state, " + - "Users can copy this state directory to another directory or disk, and then create a symbolic link to the state directory under the chaindata", - Category: flags.EthCategory, - } DirectBroadcastFlag = &cli.BoolFlag{ Name: "directbroadcast", Usage: "Enable directly broadcast mined block to all peers", @@ -2638,9 +2632,6 @@ func parseDBFeatures(cfg *ethconfig.Config, stack *node.Node) string { } else if cfg.StateScheme == rawdb.HashScheme { features = append(features, "HBSS") } - if stack.CheckIfMultiDataBase() { - features = append(features, "MultiDB") - } if cfg.PruneAncientData || cfg.BlockHistory > 0 { features = append(features, "PruneBlocks") } @@ -2767,11 +2758,6 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb. EraDirectory: ctx.String(EraFlag.Name), } chainDb, err = stack.OpenDatabaseWithOptions("chaindata", options) - // set the separate state database - if stack.CheckIfMultiDataBase() && err == nil { - stateDiskDb := MakeStateDataBase(ctx, stack, readonly) - chainDb.SetStateStore(stateDiskDb) - } } if err != nil { Fatalf("Could not open database: %v", err) @@ -2779,17 +2765,6 @@ func MakeChainDatabase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb. return chainDb } -// MakeStateDataBase open a separate state database using the flags passed to the client and will hard crash if it fails. -func MakeStateDataBase(ctx *cli.Context, stack *node.Node, readonly bool) ethdb.Database { - cache := ctx.Int(CacheFlag.Name) * ctx.Int(CacheDatabaseFlag.Name) / 100 - handles := MakeDatabaseHandles(ctx.Int(FDLimitFlag.Name)) * 90 / 100 - statediskdb, err := stack.OpenDatabaseWithFreezer("chaindata/state", cache, handles, "", "", readonly) - if err != nil { - Fatalf("Failed to open separate trie database: %v", err) - } - return statediskdb -} - // tryMakeReadOnlyDatabase try to open the chain database in read-only mode, // or fallback to write mode if the database is not initialized. // diff --git a/core/blockchain.go b/core/blockchain.go index 361be8c4bf..0f92fd2204 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -1943,11 +1943,7 @@ func (bc *BlockChain) writeBlockWithState(block *types.Block, receipts []*types. if bc.chainConfig.IsCancun(block.Number(), block.Time()) { rawdb.WriteBlobSidecars(blockBatch, block.Hash(), block.NumberU64(), block.Sidecars()) } - if bc.db.HasSeparateStateStore() { - rawdb.WritePreimages(bc.db.GetStateStore(), statedb.Preimages()) - } else { - rawdb.WritePreimages(blockBatch, statedb.Preimages()) - } + rawdb.WritePreimages(blockBatch, statedb.Preimages()) if err := blockBatch.Write(); err != nil { log.Crit("Failed to write block into disk", "err", err) } diff --git a/core/rawdb/accessors_trie.go b/core/rawdb/accessors_trie.go index c0fb62b9ac..ce1a0b2c41 100644 --- a/core/rawdb/accessors_trie.go +++ b/core/rawdb/accessors_trie.go @@ -243,12 +243,12 @@ func DeleteTrieNode(db ethdb.KeyValueWriter, owner common.Hash, path []byte, has // if the state is not present in database. func ReadStateScheme(db ethdb.Database) string { // Check if state in path-based scheme is present. - if HasAccountTrieNode(db.StateStoreReader(), nil) { + if HasAccountTrieNode(db, nil) { return PathScheme } // The root node might be deleted during the initial snap sync, check // the persistent state id then. - if id := ReadPersistentStateID(db.StateStoreReader()); id != 0 { + if id := ReadPersistentStateID(db); id != 0 { return PathScheme } // Check if verkle state in path-based scheme is present. @@ -268,7 +268,7 @@ func ReadStateScheme(db ethdb.Database) string { if header == nil { return "" // empty datadir } - if !HasLegacyTrieNode(db.StateStoreReader(), header.Root) { + if !HasLegacyTrieNode(db, header.Root) { return "" // no state in disk } return HashScheme diff --git a/core/rawdb/ancient_utils.go b/core/rawdb/ancient_utils.go index d1db8401cb..216eda4b8d 100644 --- a/core/rawdb/ancient_utils.go +++ b/core/rawdb/ancient_utils.go @@ -91,9 +91,6 @@ func inspectFreezers(db ethdb.Database) ([]freezerInfo, error) { infos = append(infos, info) case MerkleStateFreezerName, VerkleStateFreezerName: - if db.HasSeparateStateStore() { - continue - } datadir, err := db.AncientDatadir() if err != nil { return nil, err @@ -177,7 +174,7 @@ func inspectIncrFreezers(db *snapDBWrapper) ([]freezerInfo, error) { // ancient indicates the path of root ancient directory where the chain freezer can // be opened. Start and end specify the range for dumping out indexes. // Note this function can only be used for debugging purposes. -func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64, multiDatabase bool) error { +func InspectFreezerTable(ancient string, freezerName string, tableName string, start, end int64) error { var ( path string tables map[string]freezerTableConfig @@ -187,11 +184,7 @@ func InspectFreezerTable(ancient string, freezerName string, tableName string, s path, tables = resolveChainFreezerDir(ancient), chainFreezerTableConfigs case MerkleStateFreezerName, VerkleStateFreezerName: - if multiDatabase { - path, tables = filepath.Join(filepath.Dir(ancient)+"/state/ancient", freezerName), stateFreezerTableConfigs - } else { - path, tables = filepath.Join(ancient, freezerName), stateFreezerTableConfigs - } + path, tables = filepath.Join(ancient, freezerName), stateFreezerTableConfigs default: return fmt.Errorf("unknown freezer, supported ones: %v", freezers) } diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 3b4abf71b7..3b8ac24ba9 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -49,15 +49,6 @@ type freezerdb struct { readOnly bool ancientRoot string - - stateStore ethdb.Database -} - -func (frdb *freezerdb) StateStoreReader() ethdb.Reader { - if frdb.stateStore == nil { - return frdb - } - return frdb.stateStore } // AncientDatadir returns the path of root ancient directory. @@ -75,35 +66,12 @@ func (frdb *freezerdb) Close() error { if err := frdb.KeyValueStore.Close(); err != nil { errs = append(errs, err) } - if frdb.HasSeparateStateStore() { - if err := frdb.GetStateStore().Close(); err != nil { - errs = append(errs, err) - } - } if len(errs) != 0 { return fmt.Errorf("%v", errs) } return nil } -func (frdb *freezerdb) SetStateStore(state ethdb.Database) { - if frdb.stateStore != nil { - frdb.stateStore.Close() - } - frdb.stateStore = state -} - -func (frdb *freezerdb) GetStateStore() ethdb.Database { - if frdb.stateStore != nil { - return frdb.stateStore - } - return frdb -} - -func (frdb *freezerdb) HasSeparateStateStore() bool { - return frdb.stateStore != nil -} - // Freeze is a helper method used for external testing to trigger and block until // a freeze cycle completes, without having to sleep for a minute to trigger the // automatic background run. @@ -130,7 +98,6 @@ func (frdb *freezerdb) SetupFreezerEnv(env *ethdb.FreezerEnv, blockHistory uint6 // nofreezedb is a database wrapper that disables freezer data retrievals. type nofreezedb struct { ethdb.KeyValueStore - stateStore ethdb.Database } // Ancient returns an error as we don't have a backing chain freezer. @@ -198,28 +165,6 @@ func (db *nofreezedb) SyncAncient() error { return errNotSupported } -func (db *nofreezedb) SetStateStore(state ethdb.Database) { - db.stateStore = state -} - -func (db *nofreezedb) GetStateStore() ethdb.Database { - if db.stateStore != nil { - return db.stateStore - } - return db -} - -func (db *nofreezedb) HasSeparateStateStore() bool { - return db.stateStore != nil -} - -func (db *nofreezedb) StateStoreReader() ethdb.Reader { - if db.stateStore != nil { - return db.stateStore - } - return db -} - func (db *nofreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { // Unlike other ancient-related methods, this method does not return // errNotSupported when invoked. @@ -321,10 +266,6 @@ func (db *emptyfreezedb) SyncAncient() error { return nil } -func (db *emptyfreezedb) GetStateStore() ethdb.Database { return db } -func (db *emptyfreezedb) SetStateStore(state ethdb.Database) {} -func (db *emptyfreezedb) StateStoreReader() ethdb.Reader { return db } -func (db *emptyfreezedb) HasSeparateStateStore() bool { return false } func (db *emptyfreezedb) ReadAncients(fn func(reader ethdb.AncientReaderOp) error) (err error) { return nil } @@ -623,43 +564,9 @@ func AncientInspect(db ethdb.Database) error { return nil } -type DataType int - -const ( - StateDataType DataType = iota - ChainDataType - Unknown -) - -func DataTypeByKey(key []byte) DataType { - switch { - // state - case IsLegacyTrieNode(key, key), - bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength, - IsAccountTrieNode(key), - IsStorageTrieNode(key): - return StateDataType - - default: - for _, meta := range [][]byte{ - fastTrieProgressKey, persistentStateIDKey, trieJournalKey, snapSyncStatusFlagKey} { - if bytes.Equal(key, meta) { - return StateDataType - } - } - return ChainDataType - } -} - // InspectDatabase traverses the entire database and checks the size // of all different categories of data. func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { - var trieIter ethdb.Iterator - if db.HasSeparateStateStore() { - trieIter = db.GetStateStore().NewIterator(keyPrefix, nil) - defer trieIter.Release() - } - var ( start = time.Now() count atomic.Int64 @@ -839,50 +746,6 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { return it.Error() } - // inspect separate trie db - if trieIter != nil { - count.Store(0) - logged := time.Now() - for trieIter.Next() { - var ( - key = trieIter.Key() - value = trieIter.Value() - size = common.StorageSize(len(key) + len(value)) - ) - total.Add(uint64(size)) - - switch { - case IsLegacyTrieNode(key, value): - legacyTries.add(size) - case bytes.HasPrefix(key, stateIDPrefix) && len(key) == len(stateIDPrefix)+common.HashLength: - stateLookups.add(size) - case IsAccountTrieNode(key): - accountTries.add(size) - case IsStorageTrieNode(key): - storageTries.add(size) - default: - var accounted bool - for _, meta := range [][]byte{ - fastTrieProgressKey, persistentStateIDKey, trieJournalKey, snapSyncStatusFlagKey} { - if bytes.Equal(key, meta) { - metadata.add(size) - accounted = true - break - } - } - if !accounted { - unaccounted.add(size) - } - } - count.Add(1) - if count.Load()%1000 == 0 && time.Since(logged) > 8*time.Second { - log.Info("Inspecting separate state database", "count", count.Load(), "elapsed", common.PrettyDuration(time.Since(start))) - logged = time.Now() - } - } - log.Info("Inspecting separate state database", "count", count.Load(), "elapsed", common.PrettyDuration(time.Since(start))) - } - var ( eg, ctx = errgroup.WithContext(context.Background()) workers = runtime.NumCPU() @@ -965,27 +828,6 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { total.Add(uint64(ancient.size())) } - // inspect ancient state in separate trie db if exist - if trieIter != nil { - stateAncients, err := inspectFreezers(db.GetStateStore()) - if err != nil { - return err - } - for _, ancient := range stateAncients { - for _, table := range ancient.sizes { - if ancient.name == "chain" { - break - } - stats = append(stats, []string{ - fmt.Sprintf("Ancient store (%s)", strings.Title(ancient.name)), - strings.Title(table.name), - table.size.String(), - fmt.Sprintf("%d", ancient.count()), - }) - } - total.Add(uint64(ancient.size())) - } - } table := newTableWriter(os.Stdout) table.SetHeader([]string{"Database", "Category", "Size", "Items"}) table.SetFooter([]string{"", "Total", common.StorageSize(total.Load()).String(), fmt.Sprintf("%d", count.Load())}) diff --git a/core/rawdb/table.go b/core/rawdb/table.go index d26166031e..98fc2736d7 100644 --- a/core/rawdb/table.go +++ b/core/rawdb/table.go @@ -220,22 +220,6 @@ func (t *table) NewBatch() ethdb.Batch { return &tableBatch{t.db.NewBatch(), t.prefix} } -func (t *table) SetStateStore(state ethdb.Database) { - panic("not implement") -} - -func (t *table) GetStateStore() ethdb.Database { - return nil -} - -func (t *table) HasSeparateStateStore() bool { - return false -} - -func (t *table) StateStoreReader() ethdb.Reader { - return nil -} - // NewBatchWithSize creates a write-only database batch with pre-allocated buffer. func (t *table) NewBatchWithSize(size int) ethdb.Batch { return &tableBatch{t.db.NewBatchWithSize(size), t.prefix} diff --git a/core/state/pruner/pruner.go b/core/state/pruner/pruner.go index e6a64f2413..58c777dbee 100644 --- a/core/state/pruner/pruner.go +++ b/core/state/pruner/pruner.go @@ -127,19 +127,13 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta // that the false-positive is low enough(~0.05%). The probability of the // dangling node is the state root is super low. So the dangling nodes in // theory will never ever be visited again. - var pruneDB ethdb.Database - if maindb != nil && maindb.HasSeparateStateStore() { - pruneDB = maindb.GetStateStore() - } else { - pruneDB = maindb - } var ( skipped, count int size common.StorageSize pstart = time.Now() logged = time.Now() - batch = pruneDB.NewBatch() - iter = pruneDB.NewIterator(nil, nil) + batch = maindb.NewBatch() + iter = maindb.NewIterator(nil, nil) ) for iter.Next() { key := iter.Key() @@ -183,7 +177,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta batch.Reset() iter.Release() - iter = pruneDB.NewIterator(nil, key) + iter = maindb.NewIterator(nil, key) } } } @@ -228,7 +222,7 @@ func prune(snaptree *snapshot.Tree, root common.Hash, maindb ethdb.Database, sta end = nil } log.Info("Compacting database", "range", fmt.Sprintf("%#x-%#x", start, end), "elapsed", common.PrettyDuration(time.Since(cstart))) - if err := pruneDB.Compact(start, end); err != nil { + if err := maindb.Compact(start, end); err != nil { log.Error("Database compaction failed", "error", err) return err } @@ -273,17 +267,10 @@ func (p *Pruner) Prune(root common.Hash) error { // Use the bottom-most diff layer as the target root = layers[len(layers)-1].Root() } - // if the separated state db has been set, use this db to prune data - var trienodedb ethdb.Database - if p.db != nil && p.db.HasSeparateStateStore() { - trienodedb = p.db.GetStateStore() - } else { - trienodedb = p.db - } // Ensure the root is really present. The weak assumption // is the presence of root can indicate the presence of the // entire trie. - if !rawdb.HasLegacyTrieNode(trienodedb, root) { + if !rawdb.HasLegacyTrieNode(p.db, root) { // The special case is for clique based networks, it's possible // that two consecutive blocks will have same root. In this case // snapshot difflayer won't be created. So HEAD-127 may not paired @@ -296,7 +283,7 @@ func (p *Pruner) Prune(root common.Hash) error { // as the pruning target. var found bool for i := len(layers) - 2; i >= 2; i-- { - if rawdb.HasLegacyTrieNode(trienodedb, layers[i].Root()) { + if rawdb.HasLegacyTrieNode(p.db, layers[i].Root()) { root = layers[i].Root() found = true log.Info("Selecting middle-layer as the pruning target", "root", root, "depth", i) @@ -304,7 +291,7 @@ func (p *Pruner) Prune(root common.Hash) error { } } if !found { - if blob := rawdb.ReadLegacyTrieNode(trienodedb, p.snaptree.DiskRoot()); len(blob) != 0 { + if blob := rawdb.ReadLegacyTrieNode(p.db, p.snaptree.DiskRoot()); len(blob) != 0 { root = p.snaptree.DiskRoot() found = true log.Info("Selecting disk-layer as the pruning target", "root", root) diff --git a/core/state/sync_test.go b/core/state/sync_test.go index f48f936cdb..cae0e0a936 100644 --- a/core/state/sync_test.go +++ b/core/state/sync_test.go @@ -272,7 +272,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool, s } } batch := dstDb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -377,7 +377,7 @@ func testIterativeDelayedStateSync(t *testing.T, scheme string) { nodeProcessed = len(nodeResults) } batch := dstDb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -481,7 +481,7 @@ func testIterativeRandomStateSync(t *testing.T, count int, scheme string) { } } batch := dstDb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -591,7 +591,7 @@ func testIterativeRandomDelayedStateSync(t *testing.T, scheme string) { } } batch := dstDb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -708,7 +708,7 @@ func testIncompleteStateSync(t *testing.T, scheme string) { } } batch := dstDb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() diff --git a/eth/backend.go b/eth/backend.go index 625571c66a..f643ccc489 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -176,7 +176,7 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { config.Miner.GasPrice = new(big.Int).Set(ethconfig.Defaults.Miner.GasPrice) } - chainDb, err := stack.OpenAndMergeDatabase(ChainData, ChainDBNamespace, false, config) + chainDb, err := stack.OpenDatabaseWithFreezer(ChainData, config.DatabaseCache, config.DatabaseHandles, config.DatabaseFreezer, ChainDBNamespace, false) if err != nil { return nil, err } diff --git a/eth/protocols/snap/sync.go b/eth/protocols/snap/sync.go index 8263932f2c..5f79003ff6 100644 --- a/eth/protocols/snap/sync.go +++ b/eth/protocols/snap/sync.go @@ -776,7 +776,6 @@ func (s *Syncer) Sync(root common.Hash, cancel chan struct{}) error { func (s *Syncer) loadSyncStatus() { var progress SyncProgress - stateDiskDB := s.db.GetStateStore() if status := rawdb.ReadSnapshotSyncStatus(s.db); status != nil { if err := json.Unmarshal(status, &progress); err != nil { log.Error("Failed to decode snap sync status", "err", err) @@ -795,7 +794,7 @@ func (s *Syncer) loadSyncStatus() { // Allocate batch for account trie generation task.genBatch = ethdb.HookedBatch{ - Batch: stateDiskDB.NewBatch(), + Batch: s.db.NewBatch(), OnPut: func(key []byte, value []byte) { s.accountBytes += common.StorageSize(len(key) + len(value)) }, @@ -810,7 +809,7 @@ func (s *Syncer) loadSyncStatus() { for accountHash, subtasks := range task.SubTasks { for _, subtask := range subtasks { subtask.genBatch = ethdb.HookedBatch{ - Batch: stateDiskDB.NewBatch(), + Batch: s.db.NewBatch(), OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, @@ -867,7 +866,7 @@ func (s *Syncer) loadSyncStatus() { last = common.MaxHash } batch := ethdb.HookedBatch{ - Batch: stateDiskDB.NewBatch(), + Batch: s.db.NewBatch(), OnPut: func(key []byte, value []byte) { s.accountBytes += common.StorageSize(len(key) + len(value)) }, @@ -1964,7 +1963,7 @@ func (s *Syncer) processAccountResponse(res *accountResponse) { } // Mark the healing tag if storage root node is inconsistent, or // it's non-existent due to storage chunking. - if !rawdb.HasTrieNode(s.db.StateStoreReader(), res.hashes[i], nil, account.Root, s.scheme) { + if !rawdb.HasTrieNode(s.db, res.hashes[i], nil, account.Root, s.scheme) { res.task.needHeal[i] = true } } else { @@ -2079,23 +2078,12 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { res.subTask.req = nil } - var usingMultDatabase bool batch := ethdb.HookedBatch{ - Batch: s.db.GetStateStore().NewBatch(), + Batch: s.db.NewBatch(), OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, } - var snapBatch ethdb.HookedBatch - if s.db.HasSeparateStateStore() { - usingMultDatabase = true - snapBatch = ethdb.HookedBatch{ - Batch: s.db.NewBatch(), - OnPut: func(key []byte, value []byte) { - s.storageBytes += common.StorageSize(len(key) + len(value)) - }, - } - } var ( slots int @@ -2167,7 +2155,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { } // Our first task is the one that was just filled by this response. batch := ethdb.HookedBatch{ - Batch: s.db.GetStateStore().NewBatch(), + Batch: s.db.NewBatch(), OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, @@ -2189,7 +2177,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { }) for r.Next() { batch := ethdb.HookedBatch{ - Batch: s.db.GetStateStore().NewBatch(), + Batch: s.db.NewBatch(), OnPut: func(key []byte, value []byte) { s.storageBytes += common.StorageSize(len(key) + len(value)) }, @@ -2269,11 +2257,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { // outdated during the sync, but it can be fixed later during the // snapshot generation. for j := 0; j < len(res.hashes[i]); j++ { - if usingMultDatabase { - rawdb.WriteStorageSnapshot(snapBatch, account, res.hashes[i][j], res.slots[i][j]) - } else { - rawdb.WriteStorageSnapshot(batch, account, res.hashes[i][j], res.slots[i][j]) - } + rawdb.WriteStorageSnapshot(batch, account, res.hashes[i][j], res.slots[i][j]) // If we're storing large contracts, generate the trie nodes // on the fly to not trash the gluing points if i == len(res.hashes)-1 && res.subTask != nil { @@ -2293,7 +2277,7 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { // If the chunk's root is an overflown but full delivery, // clear the heal request. accountHash := res.accounts[len(res.accounts)-1] - if root == res.subTask.root && rawdb.HasTrieNode(s.db.StateStoreReader(), accountHash, nil, root, s.scheme) { + if root == res.subTask.root && rawdb.HasTrieNode(s.db, accountHash, nil, root, s.scheme) { for i, account := range res.mainTask.res.hashes { if account == accountHash { res.mainTask.needHeal[i] = false @@ -2313,11 +2297,6 @@ func (s *Syncer) processStorageResponse(res *storageResponse) { if err := batch.Write(); err != nil { log.Crit("Failed to persist storage slots", "err", err) } - if usingMultDatabase { - if err := snapBatch.Write(); err != nil { - log.Crit("Failed to persist storage slots", "err", err) - } - } s.storageSynced += uint64(slots) log.Debug("Persisted set of storage slots", "accounts", len(res.hashes), "slots", slots, "bytes", s.storageBytes-oldStorageBytes) @@ -2416,25 +2395,13 @@ func (s *Syncer) commitHealer(force bool) { return } batch := s.db.NewBatch() - var stateBatch ethdb.Batch - var err error - if s.db.HasSeparateStateStore() { - stateBatch = s.db.GetStateStore().NewBatch() - err = s.healer.scheduler.Commit(batch, stateBatch) - } else { - err = s.healer.scheduler.Commit(batch, nil) - } + err := s.healer.scheduler.Commit(batch) if err != nil { log.Crit("Failed to commit healing data", "err", err) } if err := batch.Write(); err != nil { log.Crit("Failed to persist healing data", "err", err) } - if s.db.HasSeparateStateStore() { - if err := stateBatch.Write(); err != nil { - log.Crit("Failed to persist healing data", "err", err) - } - } log.Debug("Persisted set of healing data", "type", "trienodes", "bytes", common.StorageSize(batch.ValueSize())) } diff --git a/ethdb/database.go b/ethdb/database.go index 53bca2693c..d0aa1f3a8b 100644 --- a/ethdb/database.go +++ b/ethdb/database.go @@ -215,17 +215,11 @@ type AncientStater interface { AncientDatadir() (string, error) } -// StateStoreReader wraps the StateStoreReader method. -type StateStoreReader interface { - StateStoreReader() Reader -} - // Reader contains the methods required to read data from both key-value as well as // immutable ancient data. type Reader interface { KeyValueReader AncientReader - StateStoreReader } // AncientStore contains all the methods required to allow handling different @@ -237,12 +231,6 @@ type AncientStore interface { io.Closer } -type StateStore interface { - SetStateStore(state Database) - GetStateStore() Database - HasSeparateStateStore() bool -} - // ResettableAncientStore extends the AncientStore interface by adding a Reset method. type ResettableAncientStore interface { AncientStore @@ -254,8 +242,6 @@ type ResettableAncientStore interface { // Database contains all the methods required by the high level database to not // only access the key-value data store but also the ancient chain store. type Database interface { - StateStore - StateStoreReader AncientFreezer KeyValueStore diff --git a/ethdb/memorydb/memorydb.go b/ethdb/memorydb/memorydb.go index e69540f95e..6d9eb92ed4 100644 --- a/ethdb/memorydb/memorydb.go +++ b/ethdb/memorydb/memorydb.go @@ -44,8 +44,6 @@ var ( type Database struct { db map[string][]byte lock sync.RWMutex - - stateStore ethdb.Database } func (db *Database) ModifyAncients(f func(ethdb.AncientWriteOp) error) (int64, error) { @@ -290,13 +288,6 @@ func (db *Database) Len() int { return len(db.db) } -func (db *Database) StateStoreReader() ethdb.Reader { - if db.stateStore == nil { - return db - } - return db.stateStore -} - // keyvalue is a key-value tuple tagged with a deletion field to allow creating // memory-database write batches. type keyvalue struct { diff --git a/ethdb/remotedb/remotedb.go b/ethdb/remotedb/remotedb.go index 83018c1fa4..9e0e5e9de4 100644 --- a/ethdb/remotedb/remotedb.go +++ b/ethdb/remotedb/remotedb.go @@ -75,22 +75,6 @@ func (db *Database) AncientSize(kind string) (uint64, error) { panic("not supported") } -func (db *Database) SetStateStore(state ethdb.Database) { - panic("not supported") -} - -func (db *Database) GetStateStore() ethdb.Database { - panic("not supported") -} - -func (db *Database) HasSeparateStateStore() bool { - panic("not supported") -} - -func (db *Database) StateStoreReader() ethdb.Reader { - return db -} - func (db *Database) ReadAncients(fn func(op ethdb.AncientReaderOp) error) (err error) { return fn(db) } diff --git a/node/errors.go b/node/errors.go index b53f0c8083..f9188f8d99 100644 --- a/node/errors.go +++ b/node/errors.go @@ -24,10 +24,9 @@ import ( ) var ( - ErrDatadirUsed = errors.New("datadir already used by another process") - ErrNodeStopped = errors.New("node not started") - ErrNodeRunning = errors.New("node already running") - ErrSeprateDBDatadir = errors.New("datadir is not configured when using separate trie") + ErrDatadirUsed = errors.New("datadir already used by another process") + ErrNodeStopped = errors.New("node not started") + ErrNodeRunning = errors.New("node already running") datadirInUseErrnos = map[uint]bool{11: true, 32: true, 35: true} ) diff --git a/node/node.go b/node/node.go index 573a5f315a..2287d42033 100644 --- a/node/node.go +++ b/node/node.go @@ -34,7 +34,6 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/rawdb" - "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/ethdb/memorydb" "github.com/ethereum/go-ethereum/event" @@ -75,12 +74,8 @@ const ( initializingState = iota runningState closedState - chainDbMemoryPercentage = 50 - chainDbHandlesPercentage = 50 ) -const StateDBNamespace = "eth/db/statedata/" - // New creates a new P2P node, ready for protocol registration. func New(conf *Config) (*Node, error) { // Copy config and resolve the datadir so future changes to the current @@ -782,47 +777,6 @@ func (n *Node) OpenDatabase(name string, cache, handles int, namespace string, r }) } -func (n *Node) OpenAndMergeDatabase(name string, namespace string, readonly bool, config *ethconfig.Config) (ethdb.Database, error) { - var ( - err error - stateDiskDb ethdb.Database - chainDataHandles = config.DatabaseHandles - chainDbCache = config.DatabaseCache - stateDbCache, stateDbHandles int - ) - - isMultiDatabase := n.CheckIfMultiDataBase() - // Open the separated state database if the state directory exists - if isMultiDatabase { - // Resource allocation rules: - // 1) Allocate a fixed percentage of memory for chainDb based on chainDbMemoryPercentage & chainDbHandlesPercentage. - // 2) Allocate the remaining resources to stateDb. - chainDbCache = int(float64(config.DatabaseCache) * chainDbMemoryPercentage / 100) - chainDataHandles = int(float64(config.DatabaseHandles) * chainDbHandlesPercentage / 100) - - stateDbCache = config.DatabaseCache - chainDbCache - stateDbHandles = config.DatabaseHandles - chainDataHandles - } - - chainDB, err := n.OpenDatabaseWithFreezer(name, chainDbCache, chainDataHandles, config.DatabaseFreezer, namespace, readonly) - if err != nil { - return nil, err - } - - if isMultiDatabase { - // Allocate half of the handles and chainDbCache to this separate state data database - stateDiskDb, err = n.OpenDatabaseWithFreezer(name+"/state", stateDbCache, stateDbHandles, "", "eth/db/statedata/", readonly) - if err != nil { - return nil, err - } - - log.Warn("Multi-database is an experimental feature") - chainDB.SetStateStore(stateDiskDb) - } - - return chainDB, nil -} - // OpenDatabaseWithFreezer opens an existing database with the given name (or // creates one if no previous can be found) from within the node's data directory. // If the node has no data directory, an in-memory database is returned. @@ -837,19 +791,6 @@ func (n *Node) OpenDatabaseWithFreezer(name string, cache, handles int, ancient }) } -// CheckIfMultiDataBase check the state and block subdirectory of db, if subdirectory exists, return true -func (n *Node) CheckIfMultiDataBase() bool { - stateExist := true - - separateStateDir := filepath.Join(n.ResolvePath("chaindata"), "state") - fileInfo, stateErr := os.Stat(separateStateDir) - if os.IsNotExist(stateErr) || !fileInfo.IsDir() { - stateExist = false - } - - return stateExist -} - // ResolvePath returns the absolute path of a resource in the instance directory. func (n *Node) ResolvePath(x string) string { return n.config.ResolvePath(x) diff --git a/trie/sync.go b/trie/sync.go index 001eae7b39..8272b980e9 100644 --- a/trie/sync.go +++ b/trie/sync.go @@ -451,7 +451,7 @@ func (s *Sync) ProcessNode(result NodeSyncResult) error { // Commit flushes the data stored in the internal membatch out to persistent // storage, returning any occurred error. The whole data set will be flushed // in an atomic database batch. -func (s *Sync) Commit(dbw ethdb.Batch, stateBatch ethdb.Batch) error { +func (s *Sync) Commit(dbw ethdb.Batch) error { // Flush the pending node writes into database batch. var ( account int @@ -464,17 +464,9 @@ func (s *Sync) Commit(dbw ethdb.Batch, stateBatch ethdb.Batch) error { if op.del { // node deletion is only supported in path mode. if op.owner == (common.Hash{}) { - if stateBatch != nil { - rawdb.DeleteAccountTrieNode(stateBatch, op.path) - } else { - rawdb.DeleteAccountTrieNode(dbw, op.path) - } + rawdb.DeleteAccountTrieNode(dbw, op.path) } else { - if stateBatch != nil { - rawdb.DeleteStorageTrieNode(stateBatch, op.owner, op.path) - } else { - rawdb.DeleteStorageTrieNode(dbw, op.owner, op.path) - } + rawdb.DeleteStorageTrieNode(dbw, op.owner, op.path) } deletionGauge.Inc(1) } else { @@ -483,11 +475,7 @@ func (s *Sync) Commit(dbw ethdb.Batch, stateBatch ethdb.Batch) error { } else { storage += 1 } - if stateBatch != nil { - rawdb.WriteTrieNode(stateBatch, op.owner, op.path, op.hash, op.blob, s.scheme) - } else { - rawdb.WriteTrieNode(dbw, op.owner, op.path, op.hash, op.blob, s.scheme) - } + rawdb.WriteTrieNode(dbw, op.owner, op.path, op.hash, op.blob, s.scheme) } } accountNodeSyncedGauge.Inc(int64(account)) @@ -592,9 +580,9 @@ func (s *Sync) children(req *nodeRequest, object node) ([]*nodeRequest, error) { // the performance impact negligible. var exists bool if owner == (common.Hash{}) { - exists = rawdb.HasAccountTrieNode(s.database.StateStoreReader(), append(inner, key[:i]...)) + exists = rawdb.HasAccountTrieNode(s.database, append(inner, key[:i]...)) } else { - exists = rawdb.HasStorageTrieNode(s.database.StateStoreReader(), owner, append(inner, key[:i]...)) + exists = rawdb.HasStorageTrieNode(s.database, owner, append(inner, key[:i]...)) } if exists { s.membatch.delNode(owner, append(inner, key[:i]...)) @@ -733,14 +721,14 @@ func (s *Sync) commitCodeRequest(req *codeRequest) error { func (s *Sync) hasNode(owner common.Hash, path []byte, hash common.Hash) (exists bool, inconsistent bool) { // If node is running with hash scheme, check the presence with node hash. if s.scheme == rawdb.HashScheme { - return rawdb.HasLegacyTrieNode(s.database.StateStoreReader(), hash), false + return rawdb.HasLegacyTrieNode(s.database, hash), false } // If node is running with path scheme, check the presence with node path. var blob []byte if owner == (common.Hash{}) { - blob = rawdb.ReadAccountTrieNode(s.database.StateStoreReader(), path) + blob = rawdb.ReadAccountTrieNode(s.database, path) } else { - blob = rawdb.ReadStorageTrieNode(s.database.StateStoreReader(), owner, path) + blob = rawdb.ReadStorageTrieNode(s.database, owner, path) } exists = hash == crypto.Keccak256Hash(blob) inconsistent = !exists && len(blob) != 0 diff --git a/trie/sync_test.go b/trie/sync_test.go index fb5fb13ff0..2a8f601414 100644 --- a/trie/sync_test.go +++ b/trie/sync_test.go @@ -212,7 +212,7 @@ func testIterativeSync(t *testing.T, count int, bypath bool, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -278,7 +278,7 @@ func testIterativeDelayedSync(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -348,7 +348,7 @@ func testIterativeRandomSync(t *testing.T, count int, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -419,7 +419,7 @@ func testIterativeRandomDelayedSync(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -491,7 +491,7 @@ func testDuplicateAvoidanceSync(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -563,7 +563,7 @@ func testIncompleteSync(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -653,7 +653,7 @@ func testSyncOrdering(t *testing.T, scheme string) { } } batch := diskdb.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } batch.Write() @@ -723,7 +723,7 @@ func syncWithHookWriter(t *testing.T, root common.Hash, db ethdb.Database, srcDb } } batch := db.NewBatch() - if err := sched.Commit(batch, nil); err != nil { + if err := sched.Commit(batch); err != nil { t.Fatalf("failed to commit data: %v", err) } if hookWriter != nil { diff --git a/triedb/database.go b/triedb/database.go index 2f6fd24332..4c4834f9e5 100644 --- a/triedb/database.go +++ b/triedb/database.go @@ -95,11 +95,6 @@ type Database struct { // the legacy hash-based scheme is used by default. func NewDatabase(diskdb ethdb.Database, config *Config) *Database { // Sanitize the config and use the default one if it's not specified. - var triediskdb ethdb.Database - if diskdb != nil { - triediskdb = diskdb.GetStateStore() - } - dbScheme := rawdb.ReadStateScheme(diskdb) if config == nil { if dbScheme == rawdb.PathScheme { @@ -119,7 +114,7 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database { } var preimages *preimageStore if config.Preimages { - preimages = newPreimageStore(triediskdb) + preimages = newPreimageStore(diskdb) } db := &Database{ disk: diskdb, @@ -132,25 +127,25 @@ func NewDatabase(diskdb ethdb.Database, config *Config) *Database { * 3. Last, use the default scheme, namely hash scheme */ if config.HashDB != nil { - if rawdb.ReadStateScheme(triediskdb) == rawdb.PathScheme { + if rawdb.ReadStateScheme(diskdb) == rawdb.PathScheme { log.Warn("Incompatible state scheme", "old", rawdb.PathScheme, "new", rawdb.HashScheme) } - db.backend = hashdb.New(triediskdb, config.HashDB) + db.backend = hashdb.New(diskdb, config.HashDB) } else if config.PathDB != nil { - if rawdb.ReadStateScheme(triediskdb) == rawdb.HashScheme { + if rawdb.ReadStateScheme(diskdb) == rawdb.HashScheme { log.Warn("Incompatible state scheme", "old", rawdb.HashScheme, "new", rawdb.PathScheme) } - db.backend = pathdb.New(triediskdb, config.PathDB, config.IsVerkle) + db.backend = pathdb.New(diskdb, config.PathDB, config.IsVerkle) } else if strings.Compare(dbScheme, rawdb.PathScheme) == 0 { if config.PathDB == nil { config.PathDB = pathdb.Defaults } - db.backend = pathdb.New(triediskdb, config.PathDB, config.IsVerkle) + db.backend = pathdb.New(diskdb, config.PathDB, config.IsVerkle) } else { if config.HashDB == nil { config.HashDB = hashdb.Defaults } - db.backend = hashdb.New(triediskdb, config.HashDB) + db.backend = hashdb.New(diskdb, config.HashDB) } return db } From 811d8bb14a7e26679dd2dc8b9e5e7f04dcdf8fae Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:41:07 +0800 Subject: [PATCH 22/48] core/state: fix StateDB Reader Error Discard After Commit (#3709) --- core/state/statedb.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/state/statedb.go b/core/state/statedb.go index 27dec4a5df..24e32fc105 100644 --- a/core/state/statedb.go +++ b/core/state/statedb.go @@ -1464,7 +1464,7 @@ func (s *StateDB) commitAndFlush(block uint64, deleteEmptyObjects bool, noStorag s.TrieDBCommits += time.Since(start) } } - s.reader, _ = s.db.Reader(s.originalRoot) + s.reader, err = s.db.Reader(s.originalRoot) return ret, err } From 3309c4b1eddd6bc9dd73203c07f9e136b8f8a418 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Mon, 8 Jun 2026 16:45:26 +0800 Subject: [PATCH 23/48] triedb/pathdb: fix lookup sentinel collision with zero disk layer root (#34680) (#3706) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick of go-ethereum 3772bb536 (PR #34680). accountTip and storageTip both returned common.Hash{} as the "not found" sentinel. That collides with a legitimate disk-layer fallback when the disk layer's root is itself the zero hash — as is the case for a fresh verkle/bintrie database whose empty trie hashes to EmptyVerkleHash. Switch to a (hash, ok) return signature so callers can distinguish the two cases. Update lookupAccount/lookupStorage at the call sites. The upstream regression test (TestLookupZeroBaseRootFallback) depends on test helpers not present in BSC's layertree_test.go and is omitted; the existing pathdb test suite (TestAccountLookup / TestStorageLookup et al.) still exercises the happy path. This is defensive hardening — BSC does not activate verkle in production, so the zero-root collision is theoretical today. Recommended as prerequisite for future verkle adoption. Co-authored-by: Claude Opus 4.7 (1M context) --- triedb/pathdb/layertree.go | 8 ++++---- triedb/pathdb/lookup.go | 37 ++++++++++++++++++------------------- 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/triedb/pathdb/layertree.go b/triedb/pathdb/layertree.go index 16eb204f43..b2f2bebbe9 100644 --- a/triedb/pathdb/layertree.go +++ b/triedb/pathdb/layertree.go @@ -315,8 +315,8 @@ func (tree *layerTree) lookupAccount(accountHash common.Hash, state common.Hash) tree.lock.RLock() defer tree.lock.RUnlock() - tip := tree.lookup.accountTip(accountHash, state, tree.base.root) - if tip == (common.Hash{}) { + tip, ok := tree.lookup.accountTip(accountHash, state, tree.base.root) + if !ok { return nil, fmt.Errorf("[%#x] %w", state, errSnapshotStale) } l := tree.layers[tip] @@ -333,8 +333,8 @@ func (tree *layerTree) lookupStorage(accountHash common.Hash, slotHash common.Ha tree.lock.RLock() defer tree.lock.RUnlock() - tip := tree.lookup.storageTip(accountHash, slotHash, state, tree.base.root) - if tip == (common.Hash{}) { + tip, ok := tree.lookup.storageTip(accountHash, slotHash, state, tree.base.root) + if !ok { return nil, fmt.Errorf("[%#x] %w", state, errSnapshotStale) } l := tree.layers[tip] diff --git a/triedb/pathdb/lookup.go b/triedb/pathdb/lookup.go index 8b092730f8..f6b726cdea 100644 --- a/triedb/pathdb/lookup.go +++ b/triedb/pathdb/lookup.go @@ -85,12 +85,16 @@ func newLookup(head layer, descendant func(state common.Hash, ancestor common.Ha // stateID or is a descendant of it. // // If found, the account data corresponding to the supplied stateID resides -// in that layer. Otherwise, two scenarios are possible: +// in the layer identified by the returned hash (ok=true). Otherwise, +// (common.Hash{}, false) is returned to signal that the supplied stateID is +// stale. // -// (a) the account remains unmodified from the current disk layer up to the state -// layer specified by the stateID: fallback to the disk layer for data retrieval, -// (b) or the layer specified by the stateID is stale: reject the data retrieval. -func (l *lookup) accountTip(accountHash common.Hash, stateID common.Hash, base common.Hash) common.Hash { +// Note the returned hash may itself be common.Hash{} when the disk layer's +// root is zero — as is the case for a fresh verkle/bintrie database whose +// empty trie hashes to EmptyVerkleHash. Callers must therefore consult the +// boolean rather than comparing the returned hash against common.Hash{} +// directly. +func (l *lookup) accountTip(accountHash common.Hash, stateID common.Hash, base common.Hash) (common.Hash, bool) { // Traverse the mutation history from latest to oldest one. Several // scenarios are possible: // @@ -116,31 +120,26 @@ func (l *lookup) accountTip(accountHash common.Hash, stateID common.Hash, base c // containing the modified data. Otherwise, the current state may be ahead // of the requested one or belong to a different branch. if list[i] == stateID || l.descendant(stateID, list[i]) { - return list[i] + return list[i], true } } // No layer matching the stateID or its descendants was found. Use the // current disk layer as a fallback. if base == stateID || l.descendant(stateID, base) { - return base + return base, true } // The layer associated with 'stateID' is not the descendant of the current // disk layer, it's already stale, return nothing. - return common.Hash{} + return common.Hash{}, false } // storageTip traverses the layer list associated with the given account and // slot hash in reverse order to locate the first entry that either matches // the specified stateID or is a descendant of it. // -// If found, the storage data corresponding to the supplied stateID resides -// in that layer. Otherwise, two scenarios are possible: -// -// (a) the storage slot remains unmodified from the current disk layer up to -// the state layer specified by the stateID: fallback to the disk layer for -// data retrieval, (b) or the layer specified by the stateID is stale: reject -// the data retrieval. -func (l *lookup) storageTip(accountHash common.Hash, slotHash common.Hash, stateID common.Hash, base common.Hash) common.Hash { +// See accountTip for the returned-hash / ok convention — the same +// bintrie-zero-root caveat applies here. +func (l *lookup) storageTip(accountHash common.Hash, slotHash common.Hash, stateID common.Hash, base common.Hash) (common.Hash, bool) { list := l.storages[storageKey(accountHash, slotHash)] for i := len(list) - 1; i >= 0; i-- { // If the current state matches the stateID, or the requested state is a @@ -148,17 +147,17 @@ func (l *lookup) storageTip(accountHash common.Hash, slotHash common.Hash, state // containing the modified data. Otherwise, the current state may be ahead // of the requested one or belong to a different branch. if list[i] == stateID || l.descendant(stateID, list[i]) { - return list[i] + return list[i], true } } // No layer matching the stateID or its descendants was found. Use the // current disk layer as a fallback. if base == stateID || l.descendant(stateID, base) { - return base + return base, true } // The layer associated with 'stateID' is not the descendant of the current // disk layer, it's already stale, return nothing. - return common.Hash{} + return common.Hash{}, false } // addLayer traverses the state data retained in the specified diff layer and From 1d1d29dc3c1f309ae9bb46ab40c708fa0d1f25ab Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Mon, 8 Jun 2026 17:00:52 +0800 Subject: [PATCH 24/48] params: move Pasteur next to Mendel (#3717) --- cmd/geth/chaincmd.go | 10 ++-- cmd/geth/config.go | 8 ++-- cmd/geth/main.go | 2 +- cmd/utils/flags.go | 10 ++-- core/genesis.go | 8 ++-- eth/backend.go | 8 ++-- eth/catalyst/simulated_beacon.go | 2 +- eth/ethconfig/config.go | 6 +-- eth/ethconfig/gen_config.go | 12 ++--- eth/tracers/api.go | 8 ++-- params/config.go | 78 ++++++++++++++++---------------- params/forks/forks.go | 4 +- 12 files changed, 78 insertions(+), 78 deletions(-) diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go index 9d207c6ba8..d523217913 100644 --- a/cmd/geth/chaincmd.go +++ b/cmd/geth/chaincmd.go @@ -73,9 +73,9 @@ var ( utils.OverrideFermi, utils.OverrideOsaka, utils.OverrideMendel, + utils.OverridePasteur, utils.OverrideBPO1, utils.OverrideBPO2, - utils.OverridePasteur, utils.OverrideVerkle, }, utils.DatabaseFlags), Description: ` @@ -357,6 +357,10 @@ func initGenesis(ctx *cli.Context) error { v := ctx.Uint64(utils.OverrideMendel.Name) overrides.OverrideMendel = &v } + if ctx.IsSet(utils.OverridePasteur.Name) { + v := ctx.Uint64(utils.OverridePasteur.Name) + overrides.OverridePasteur = &v + } if ctx.IsSet(utils.OverrideBPO1.Name) { v := ctx.Uint64(utils.OverrideBPO1.Name) overrides.OverrideBPO1 = &v @@ -365,10 +369,6 @@ func initGenesis(ctx *cli.Context) error { v := ctx.Uint64(utils.OverrideBPO2.Name) overrides.OverrideBPO2 = &v } - if ctx.IsSet(utils.OverridePasteur.Name) { - v := ctx.Uint64(utils.OverridePasteur.Name) - overrides.OverridePasteur = &v - } if ctx.IsSet(utils.OverrideVerkle.Name) { v := ctx.Uint64(utils.OverrideVerkle.Name) overrides.OverrideVerkle = &v diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 6a3d462730..ab5fe3fdd4 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -278,6 +278,10 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { v := ctx.Uint64(utils.OverrideMendel.Name) cfg.Eth.OverrideMendel = &v } + if ctx.IsSet(utils.OverridePasteur.Name) { + v := ctx.Uint64(utils.OverridePasteur.Name) + cfg.Eth.OverridePasteur = &v + } if ctx.IsSet(utils.OverrideBPO1.Name) { v := ctx.Uint64(utils.OverrideBPO1.Name) cfg.Eth.OverrideBPO1 = &v @@ -286,10 +290,6 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { v := ctx.Uint64(utils.OverrideBPO2.Name) cfg.Eth.OverrideBPO2 = &v } - if ctx.IsSet(utils.OverridePasteur.Name) { - v := ctx.Uint64(utils.OverridePasteur.Name) - cfg.Eth.OverridePasteur = &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 46ba1e36e9..d0880407e2 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -76,9 +76,9 @@ var ( utils.OverrideFermi, utils.OverrideOsaka, utils.OverrideMendel, + utils.OverridePasteur, utils.OverrideBPO1, utils.OverrideBPO2, - utils.OverridePasteur, utils.OverrideVerkle, utils.OverrideGenesisFlag, utils.OverrideFullImmutabilityThreshold, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 1d56caff57..60a02760f5 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -313,6 +313,11 @@ var ( Usage: "Manually specify the Mendel fork timestamp, overriding the bundled setting", Category: flags.EthCategory, } + OverridePasteur = &cli.Uint64Flag{ + Name: "override.pasteur", + Usage: "Manually specify the Pasteur fork timestamp, overriding the bundled setting", + Category: flags.EthCategory, + } OverrideBPO1 = &cli.Uint64Flag{ Name: "override.bpo1", Usage: "Manually specify the bpo1 fork timestamp, overriding the bundled setting", @@ -323,11 +328,6 @@ var ( Usage: "Manually specify the bpo2 fork timestamp, overriding the bundled setting", Category: flags.EthCategory, } - OverridePasteur = &cli.Uint64Flag{ - Name: "override.pasteur", - Usage: "Manually specify the Pasteur 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/core/genesis.go b/core/genesis.go index 0fbabfeeb7..d743ee863d 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -273,9 +273,9 @@ type ChainOverrides struct { OverrideFermi *uint64 OverrideOsaka *uint64 OverrideMendel *uint64 + OverridePasteur *uint64 OverrideBPO1 *uint64 OverrideBPO2 *uint64 - OverridePasteur *uint64 OverrideVerkle *uint64 } @@ -311,15 +311,15 @@ func (o *ChainOverrides) apply(cfg *params.ChainConfig) error { if o.OverrideMendel != nil { cfg.MendelTime = o.OverrideMendel } + if o.OverridePasteur != nil { + cfg.PasteurTime = o.OverridePasteur + } if o.OverrideBPO1 != nil { cfg.BPO1Time = o.OverrideBPO1 } if o.OverrideBPO2 != nil { cfg.BPO2Time = o.OverrideBPO2 } - if o.OverridePasteur != nil { - cfg.PasteurTime = o.OverridePasteur - } if o.OverrideVerkle != nil { cfg.VerkleTime = o.OverrideVerkle } diff --git a/eth/backend.go b/eth/backend.go index f643ccc489..4bead869b5 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -260,6 +260,10 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { chainConfig.MendelTime = config.OverrideMendel overrides.OverrideMendel = config.OverrideMendel } + if config.OverridePasteur != nil { + chainConfig.PasteurTime = config.OverridePasteur + overrides.OverridePasteur = config.OverridePasteur + } if config.OverrideBPO1 != nil { chainConfig.BPO1Time = config.OverrideBPO1 overrides.OverrideBPO1 = config.OverrideBPO1 @@ -268,10 +272,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { chainConfig.BPO2Time = config.OverrideBPO2 overrides.OverrideBPO2 = config.OverrideBPO2 } - if config.OverridePasteur != nil { - chainConfig.PasteurTime = config.OverridePasteur - overrides.OverridePasteur = config.OverridePasteur - } if config.OverrideVerkle != nil { chainConfig.VerkleTime = config.OverrideVerkle overrides.OverrideVerkle = config.OverrideVerkle diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go index ee87301852..f2264216cf 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.Pasteur, forks.BPO5, forks.BPO4, forks.BPO3, forks.BPO2, forks.BPO1, forks.Mendel, forks.Osaka, + case forks.BPO5, forks.BPO4, forks.BPO3, forks.BPO2, forks.BPO1, forks.Pasteur, forks.Mendel, forks.Osaka, forks.Fermi, forks.Maxwell, forks.Lorentz, forks.Prague, forks.Cancun: return engine.PayloadV3 case forks.Paris, forks.Shanghai: diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index ef84b0a121..8297e21d55 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -230,15 +230,15 @@ type Config struct { // OverrideMendel (TODO: remove after the fork) OverrideMendel *uint64 `toml:",omitempty"` + // OverridePasteur (TODO: remove after the fork) + OverridePasteur *uint64 `toml:",omitempty"` + // OverrideBPO1 (TODO: remove after the fork) OverrideBPO1 *uint64 `toml:",omitempty"` // OverrideBPO2 (TODO: remove after the fork) OverrideBPO2 *uint64 `toml:",omitempty"` - // OverridePasteur (TODO: remove after the fork) - OverridePasteur *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 a844b14ecf..a7e0c4d398 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -78,9 +78,9 @@ func (c Config) MarshalTOML() (interface{}, error) { OverrideFermi *uint64 `toml:",omitempty"` OverrideOsaka *uint64 `toml:",omitempty"` OverrideMendel *uint64 `toml:",omitempty"` + OverridePasteur *uint64 `toml:",omitempty"` OverrideBPO1 *uint64 `toml:",omitempty"` OverrideBPO2 *uint64 `toml:",omitempty"` - OverridePasteur *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"` TxSyncDefaultTimeout time.Duration `toml:",omitempty"` TxSyncMaxTimeout time.Duration `toml:",omitempty"` @@ -155,9 +155,9 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.OverrideFermi = c.OverrideFermi enc.OverrideOsaka = c.OverrideOsaka enc.OverrideMendel = c.OverrideMendel + enc.OverridePasteur = c.OverridePasteur enc.OverrideBPO1 = c.OverrideBPO1 enc.OverrideBPO2 = c.OverrideBPO2 - enc.OverridePasteur = c.OverridePasteur enc.OverrideVerkle = c.OverrideVerkle enc.TxSyncDefaultTimeout = c.TxSyncDefaultTimeout enc.TxSyncMaxTimeout = c.TxSyncMaxTimeout @@ -236,9 +236,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { OverrideFermi *uint64 `toml:",omitempty"` OverrideOsaka *uint64 `toml:",omitempty"` OverrideMendel *uint64 `toml:",omitempty"` + OverridePasteur *uint64 `toml:",omitempty"` OverrideBPO1 *uint64 `toml:",omitempty"` OverrideBPO2 *uint64 `toml:",omitempty"` - OverridePasteur *uint64 `toml:",omitempty"` OverrideVerkle *uint64 `toml:",omitempty"` TxSyncDefaultTimeout *time.Duration `toml:",omitempty"` TxSyncMaxTimeout *time.Duration `toml:",omitempty"` @@ -436,15 +436,15 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.OverrideMendel != nil { c.OverrideMendel = dec.OverrideMendel } + if dec.OverridePasteur != nil { + c.OverridePasteur = dec.OverridePasteur + } if dec.OverrideBPO1 != nil { c.OverrideBPO1 = dec.OverrideBPO1 } if dec.OverrideBPO2 != nil { c.OverrideBPO2 = dec.OverrideBPO2 } - if dec.OverridePasteur != nil { - c.OverridePasteur = dec.OverridePasteur - } if dec.OverrideVerkle != nil { c.OverrideVerkle = dec.OverrideVerkle } diff --git a/eth/tracers/api.go b/eth/tracers/api.go index 3efcc83667..9c78866784 100644 --- a/eth/tracers/api.go +++ b/eth/tracers/api.go @@ -1313,6 +1313,10 @@ func overrideConfig(original *params.ChainConfig, override *params.ChainConfig) copy.MendelTime = timestamp canon = false } + if timestamp := override.PasteurTime; timestamp != nil { + copy.PasteurTime = timestamp + canon = false + } if timestamp := override.BPO1Time; timestamp != nil { copy.BPO1Time = timestamp canon = false @@ -1321,10 +1325,6 @@ func overrideConfig(original *params.ChainConfig, override *params.ChainConfig) copy.BPO2Time = timestamp canon = false } - if timestamp := override.PasteurTime; timestamp != nil { - copy.PasteurTime = timestamp - canon = false - } if timestamp := override.VerkleTime; timestamp != nil { copy.VerkleTime = timestamp canon = false diff --git a/params/config.go b/params/config.go index 8e9b40398a..5b9a7166f7 100644 --- a/params/config.go +++ b/params/config.go @@ -252,10 +252,10 @@ var ( FermiTime: newUint64(1768357800), // 2026-01-14 02:30:00 AM UTC OsakaTime: newUint64(1777343400), // 2026-04-28 02:30:00 AM UTC MendelTime: newUint64(1777343400), // 2026-04-28 02:30:00 AM UTC - BPO1Time: nil, // will be skipped in BSC - BPO2Time: nil, // will be skipped in BSC - AmsterdamTime: nil, PasteurTime: nil, + BPO1Time: nil, // will be skipped in BSC + BPO2Time: nil, // will be skipped in BSC + AmsterdamTime: nil, Parlia: &ParliaConfig{}, BlobScheduleConfig: &BlobScheduleConfig{ @@ -306,10 +306,10 @@ var ( FermiTime: newUint64(1762741500), // 2025-11-10 02:25:00 AM UTC OsakaTime: newUint64(1774319400), // 2026-03-24 02:30:00 AM UTC MendelTime: newUint64(1774319400), // 2026-03-24 02:30:00 AM UTC - BPO1Time: nil, // will be skipped in BSC - BPO2Time: nil, // will be skipped in BSC - AmsterdamTime: nil, PasteurTime: nil, + BPO1Time: nil, // will be skipped in BSC + BPO2Time: nil, // will be skipped in BSC + AmsterdamTime: nil, Parlia: &ParliaConfig{}, BlobScheduleConfig: &BlobScheduleConfig{ @@ -362,10 +362,10 @@ var ( // TODO: set them to `0` when passed on the mainnet OsakaTime: nil, MendelTime: nil, + PasteurTime: nil, BPO1Time: nil, // will be skipped in BSC BPO2Time: nil, // will be skipped in BSC AmsterdamTime: nil, - PasteurTime: nil, Parlia: &ParliaConfig{}, BlobScheduleConfig: &BlobScheduleConfig{ @@ -722,13 +722,13 @@ type ChainConfig struct { 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) + PasteurTime *uint64 `json:"pasteurTime,omitempty"` // Pasteur switch time (nil = no fork, 0 = already on pasteur) BPO1Time *uint64 `json:"bpo1Time,omitempty"` // BPO1 switch time (nil = no fork, 0 = already on bpo1) BPO2Time *uint64 `json:"bpo2Time,omitempty"` // BPO2 switch time (nil = no fork, 0 = already on bpo2) BPO3Time *uint64 `json:"bpo3Time,omitempty"` // BPO3 switch time (nil = no fork, 0 = already on bpo3) BPO4Time *uint64 `json:"bpo4Time,omitempty"` // BPO4 switch time (nil = no fork, 0 = already on bpo4) BPO5Time *uint64 `json:"bpo5Time,omitempty"` // BPO5 switch time (nil = no fork, 0 = already on bpo5) AmsterdamTime *uint64 `json:"amsterdamTime,omitempty"` // Amsterdam switch time (nil = no fork, 0 = already on amsterdam) - PasteurTime *uint64 `json:"pasteurTime,omitempty"` // PasteurTime switch time (nil = no fork, 0 = already on pasteurTime) VerkleTime *uint64 `json:"verkleTime,omitempty"` // Verkle switch time (nil = no fork, 0 = already on verkle) // TerminalTotalDifficulty is the amount of total difficulty reached by @@ -915,6 +915,11 @@ func (c *ChainConfig) String() string { MendelTime = big.NewInt(0).SetUint64(*c.MendelTime) } + var PasteurTime *big.Int + if c.PasteurTime != nil { + PasteurTime = big.NewInt(0).SetUint64(*c.PasteurTime) + } + var BPO1Time *big.Int if c.BPO1Time != nil { BPO1Time = big.NewInt(0).SetUint64(*c.BPO1Time) @@ -925,15 +930,10 @@ func (c *ChainConfig) String() string { BPO2Time = big.NewInt(0).SetUint64(*c.BPO2Time) } - var PasteurTime *big.Int - if c.PasteurTime != nil { - PasteurTime = big.NewInt(0).SetUint64(*c.PasteurTime) - } - 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, MendelTime: %v, BPO1Time: %v, BPO2Time: %v, PasteurTime: %v}", + "OsakaTime: %v, MendelTime: %v, PasteurTime: %v, BPO1Time: %v, BPO2Time: %v}", c.ChainID, engine, c.HomesteadBlock, @@ -981,9 +981,9 @@ func (c *ChainConfig) String() string { FermiTime, OsakaTime, MendelTime, + PasteurTime, BPO1Time, BPO2Time, - PasteurTime, ) } @@ -1444,6 +1444,20 @@ func (c *ChainConfig) IsOnMendel(currentBlockNumber *big.Int, lastBlockTime uint return !c.IsMendel(lastBlockNumber, lastBlockTime) && c.IsMendel(currentBlockNumber, currentBlockTime) } +// IsPasteur returns whether time is either equal to the Pasteur fork time or greater. +func (c *ChainConfig) IsPasteur(num *big.Int, time uint64) bool { + return c.IsLondon(num) && isTimestampForked(c.PasteurTime, time) +} + +// IsOnPasteur eturns whether currentBlockTime is either equal to the Pasteur fork time or greater firstly. +func (c *ChainConfig) IsOnPasteur(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.IsPasteur(lastBlockNumber, lastBlockTime) && c.IsPasteur(currentBlockNumber, currentBlockTime) +} + // IsBPO1 returns whether time is either equal to the BPO1 fork time or greater. func (c *ChainConfig) IsBPO1(num *big.Int, time uint64) bool { return c.IsLondon(num) && isTimestampForked(c.BPO1Time, time) @@ -1474,20 +1488,6 @@ func (c *ChainConfig) IsAmsterdam(num *big.Int, time uint64) bool { return c.IsLondon(num) && isTimestampForked(c.AmsterdamTime, time) } -// IsPasteur returns whether time is either equal to the Pasteur fork time or greater. -func (c *ChainConfig) IsPasteur(num *big.Int, time uint64) bool { - return c.IsLondon(num) && isTimestampForked(c.PasteurTime, time) -} - -// IsOnPasteur eturns whether currentBlockTime is either equal to the Pasteur fork time or greater firstly. -func (c *ChainConfig) IsOnPasteur(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.IsPasteur(lastBlockNumber, lastBlockTime) && c.IsPasteur(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) @@ -1575,6 +1575,7 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "fermiTime", timestamp: c.FermiTime}, {name: "osakaTime", timestamp: c.OsakaTime}, {name: "mendelTime", timestamp: c.MendelTime}, + {name: "pasteurTime", timestamp: c.PasteurTime}, {name: "verkleTime", timestamp: c.VerkleTime, optional: true}, {name: "bpo1", timestamp: c.BPO1Time, optional: true}, {name: "bpo2", timestamp: c.BPO2Time, optional: true}, @@ -1582,7 +1583,6 @@ func (c *ChainConfig) CheckConfigForkOrder() error { {name: "bpo4", timestamp: c.BPO4Time, optional: true}, {name: "bpo5", timestamp: c.BPO5Time, optional: true}, {name: "amsterdam", timestamp: c.AmsterdamTime, optional: true}, - {name: "pasteurTime", timestamp: c.PasteurTime, optional: true}, } { if lastFork.name != "" { switch { @@ -1804,6 +1804,9 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, if isForkTimestampIncompatible(c.MendelTime, newcfg.MendelTime, headTimestamp) { return newTimestampCompatError("Mendel fork timestamp", c.MendelTime, newcfg.MendelTime) } + if isForkTimestampIncompatible(c.PasteurTime, newcfg.PasteurTime, headTimestamp) { + return newTimestampCompatError("Pasteur fork timestamp", c.PasteurTime, newcfg.PasteurTime) + } if isForkTimestampIncompatible(c.VerkleTime, newcfg.VerkleTime, headTimestamp) { return newTimestampCompatError("Verkle fork timestamp", c.VerkleTime, newcfg.VerkleTime) } @@ -1825,9 +1828,6 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, headNumber *big.Int, if isForkTimestampIncompatible(c.AmsterdamTime, newcfg.AmsterdamTime, headTimestamp) { return newTimestampCompatError("Amsterdam fork timestamp", c.AmsterdamTime, newcfg.AmsterdamTime) } - if isForkTimestampIncompatible(c.PasteurTime, newcfg.PasteurTime, headTimestamp) { - return newTimestampCompatError("Pasteur fork timestamp", c.PasteurTime, newcfg.PasteurTime) - } return nil } @@ -1848,8 +1848,6 @@ func (c *ChainConfig) LatestFork(time uint64) forks.Fork { london := c.LondonBlock switch { - case c.IsPasteur(london, time): - return forks.Pasteur case c.IsAmsterdam(london, time): return forks.Amsterdam case c.IsBPO5(london, time): @@ -1862,6 +1860,8 @@ func (c *ChainConfig) LatestFork(time uint64) forks.Fork { return forks.BPO2 case c.IsBPO1(london, time): return forks.BPO1 + case c.IsPasteur(london, time): + return forks.Pasteur case c.IsMendel(london, time): return forks.Mendel case c.IsOsaka(london, time): @@ -1937,8 +1937,6 @@ func (c *ChainConfig) ActiveSystemContracts(time uint64) map[string]common.Addre // the fork isn't defined or isn't a time-based fork. func (c *ChainConfig) Timestamp(fork forks.Fork) *uint64 { switch { - case fork == forks.Pasteur: - return c.PasteurTime case fork == forks.Amsterdam: return c.AmsterdamTime case fork == forks.BPO5: @@ -1951,6 +1949,8 @@ func (c *ChainConfig) Timestamp(fork forks.Fork) *uint64 { return c.BPO2Time case fork == forks.BPO1: return c.BPO1Time + case fork == forks.Pasteur: + return c.PasteurTime case fork == forks.Mendel: return c.MendelTime case fork == forks.Osaka: @@ -2123,7 +2123,7 @@ type Rules struct { IsShanghai, IsKepler, IsFeynman, IsCancun, IsHaber bool IsBohr, IsPascal, IsPrague, IsLorentz, IsMaxwell bool IsFermi, IsOsaka, IsMendel bool - IsAmsterdam, IsPasteur, IsVerkle bool + IsPasteur, IsAmsterdam, IsVerkle bool } // Rules ensures c's ChainID is not nil. @@ -2169,8 +2169,8 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool, timestamp uint64) Rules IsFermi: c.IsFermi(num, timestamp), IsOsaka: (isMerge || c.IsInBSC()) && c.IsOsaka(num, timestamp), IsMendel: c.IsMendel(num, timestamp), - IsAmsterdam: (isMerge || c.IsInBSC()) && c.IsAmsterdam(num, timestamp), IsPasteur: c.IsPasteur(num, timestamp), + IsAmsterdam: (isMerge || c.IsInBSC()) && c.IsAmsterdam(num, timestamp), IsVerkle: c.IsVerkle(num, timestamp), IsEIP4762: isVerkle, } diff --git a/params/forks/forks.go b/params/forks/forks.go index cc35fd5d3a..bc7c8e9ecc 100644 --- a/params/forks/forks.go +++ b/params/forks/forks.go @@ -45,7 +45,7 @@ const ( Fermi Osaka Mendel - Pasteur // BOP1 will be skipped in BSC, so let Pasteur be the next to Mendel + Pasteur BPO1 BPO2 BPO3 @@ -88,11 +88,11 @@ var forkToString = map[Fork]string{ Fermi: "Fermi", Osaka: "Osaka", Mendel: "Mendel", + Pasteur: "Pasteur", BPO1: "BPO1", BPO2: "BPO2", BPO3: "BPO3", BPO4: "BPO4", BPO5: "BPO5", Amsterdam: "Amsterdam", - Pasteur: "Pasteur", } From cfed67f8a233d5dea0eb1b13a502dcef09e3e605 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:00:21 +0800 Subject: [PATCH 25/48] fix: nocgo sigToPub hash check + pathdb zero-base regression test (#3718) * crypto: add hash length check in nocgo sigToPub Upstream PR #33839 added the hash length guard to both VerifySignature and sigToPub. The prior backport only covered VerifySignature; mirror the same check in sigToPub so callers like Ecrecover reject malformed hash inputs with a clear error instead of relying on downstream library behavior. * triedb/pathdb: add regression test for zero-base-root fallback Cover the sentinel collision fixed in the prior commit: when the disk layer root is common.Hash{} (e.g. a fresh verkle/bintrie database whose empty trie hashes to zero), the legitimate fall-through to the disk layer must not be mistaken for the stale-state sentinel. Pins both the fall-through and the still-stale-on-unknown-state contract so a future refactor that always returns ok=true would fail here. --- crypto/signature_nocgo.go | 3 ++ triedb/pathdb/layertree_test.go | 61 +++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+) diff --git a/crypto/signature_nocgo.go b/crypto/signature_nocgo.go index 6ac1946829..de345c32e9 100644 --- a/crypto/signature_nocgo.go +++ b/crypto/signature_nocgo.go @@ -39,6 +39,9 @@ func Ecrecover(hash, sig []byte) ([]byte, error) { } func sigToPub(hash, sig []byte) (*secp256k1.PublicKey, error) { + if len(hash) != DigestLength { + return nil, fmt.Errorf("hash is required to be exactly %d bytes (%d)", DigestLength, len(hash)) + } if len(sig) != SignatureLength { return nil, errors.New("invalid signature") } diff --git a/triedb/pathdb/layertree_test.go b/triedb/pathdb/layertree_test.go index a74c6eb045..240ce03fce 100644 --- a/triedb/pathdb/layertree_test.go +++ b/triedb/pathdb/layertree_test.go @@ -882,3 +882,64 @@ func TestStorageLookup(t *testing.T) { } } } + +// TestLookupZeroBaseRootFallback regresses the sentinel collision in +// accountTip/storageTip when the disk layer root is itself common.Hash{} +// (a fresh verkle/bintrie database whose empty trie hashes to zero). +// Returning only common.Hash conflated the disk-layer fallback with the +// "stale" sentinel, so lookupAccount/Storage reported errSnapshotStale +// for a valid fall-through. +func TestLookupZeroBaseRootFallback(t *testing.T) { + db := New(rawdb.NewMemoryDatabase(), nil, false) + base := newDiskLayer(common.Hash{}, 0, db, nil, nil, newBuffer(0, nil, nil, 0), nil) + tr := newLayerTree(base) + + if err := tr.add(common.Hash{0x2}, common.Hash{}, 1, + NewNodeSetWithOrigin(nil, nil), + NewStateSetWithOrigin(randomAccountSet("0xa"), + randomStorageSet([]string{"0xa"}, [][]string{{"0x1"}}, nil), + nil, nil, false)); err != nil { + t.Fatalf("add first diff layer: %v", err) + } + if err := tr.add(common.Hash{0x3}, common.Hash{0x2}, 2, + NewNodeSetWithOrigin(nil, nil), + NewStateSetWithOrigin(randomAccountSet("0xb"), nil, nil, nil, false)); err != nil { + t.Fatalf("add second diff layer: %v", err) + } + + // Unknown account at HEAD: must fall through to the zero-rooted disk layer. + l, err := tr.lookupAccount(common.HexToHash("0xdead"), common.Hash{0x3}) + if err != nil { + t.Fatalf("lookupAccount fallback: unexpected error %v", err) + } + if l.rootHash() != (common.Hash{}) { + t.Errorf("lookupAccount fallback: want disk root 0, got %x", l.rootHash()) + } + + // Symmetric storage case. + l, err = tr.lookupStorage(common.HexToHash("0xdead"), common.HexToHash("0x99"), common.Hash{0x3}) + if err != nil { + t.Fatalf("lookupStorage fallback: unexpected error %v", err) + } + if l.rootHash() != (common.Hash{}) { + t.Errorf("lookupStorage fallback: want disk root 0, got %x", l.rootHash()) + } + + // Happy path still works: account 0xa was written in diff 0x2. + l, err = tr.lookupAccount(common.HexToHash("0xa"), common.Hash{0x3}) + if err != nil { + t.Fatalf("lookupAccount(known): %v", err) + } + if l.rootHash() != (common.Hash{0x2}) { + t.Errorf("lookupAccount(known): want %x, got %x", common.Hash{0x2}, l.rootHash()) + } + + // Truly stale state root must still surface errSnapshotStale, + // pinning the other half of the contract. + if _, err := tr.lookupAccount(common.HexToHash("0xa"), common.HexToHash("0xdeadbeef")); !errors.Is(err, errSnapshotStale) { + t.Errorf("lookupAccount(stale): want errSnapshotStale, got %v", err) + } + if _, err := tr.lookupStorage(common.HexToHash("0xa"), common.HexToHash("0x1"), common.HexToHash("0xdeadbeef")); !errors.Is(err, errSnapshotStale) { + t.Errorf("lookupStorage(stale): want errSnapshotStale, got %v", err) + } +} From 2d1a5906f3cf114fa085e652fe746a83219e9c9e Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:00:41 +0800 Subject: [PATCH 26/48] core/rawdb: fix incorrect fsync ordering for index file truncation (#34728) (#3712) Co-authored-by: Snehendu Roy <81818503+snehendu098@users.noreply.github.com> --- core/rawdb/freezer_utils.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/rawdb/freezer_utils.go b/core/rawdb/freezer_utils.go index 752e95ba6a..0c7d914ddb 100644 --- a/core/rawdb/freezer_utils.go +++ b/core/rawdb/freezer_utils.go @@ -69,6 +69,11 @@ func copyFrom(srcPath, destPath string, offset uint64, before func(f *os.File) e // we do the final move. src.Close() + // Permanently persist the content into disk + if err := f.Sync(); err != nil { + return err + } + if err := f.Close(); err != nil { return err } From 621eff7b9f907e31b645fe5038d248d41acc44f4 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:00:59 +0800 Subject: [PATCH 27/48] core/rawdb: fix file descriptor leak in freezer error paths (#34735) (#3711) In openFreezerFileForAppend, if Seek fails after the file is successfully opened, the file handle is not closed, leaking a descriptor. Similarly in newTable, if opening the meta file fails, the already-opened index file is not closed. And if newMetadata fails, both the index and meta files are leaked. Under repeated error conditions (e.g., corrupted filesystem), these leaks accumulate and may exhaust the OS file descriptor limit, causing cascading failures. Co-authored-by: rayoo --- core/rawdb/freezer_table.go | 4 ++++ core/rawdb/freezer_utils.go | 1 + 2 files changed, 5 insertions(+) diff --git a/core/rawdb/freezer_table.go b/core/rawdb/freezer_table.go index 6b2d4c2c27..d5d856d71c 100644 --- a/core/rawdb/freezer_table.go +++ b/core/rawdb/freezer_table.go @@ -167,6 +167,7 @@ func newTable(path string, name string, readMeter, writeMeter *metrics.Meter, si // the initialization. meta, err = openFreezerFileForAppend(filepath.Join(path, fmt.Sprintf("%s.meta", name))) if err != nil { + index.Close() return nil, err } } else { @@ -176,6 +177,7 @@ func newTable(path string, name string, readMeter, writeMeter *metrics.Meter, si } meta, err = openFreezerFileForAppend(filepath.Join(path, fmt.Sprintf("%s.meta", name))) if err != nil { + index.Close() return nil, err } } @@ -183,6 +185,8 @@ func newTable(path string, name string, readMeter, writeMeter *metrics.Meter, si // is detected. metadata, err := newMetadata(meta) if err != nil { + meta.Close() + index.Close() return nil, err } // Create the table and repair any past inconsistency diff --git a/core/rawdb/freezer_utils.go b/core/rawdb/freezer_utils.go index 0c7d914ddb..2088b39617 100644 --- a/core/rawdb/freezer_utils.go +++ b/core/rawdb/freezer_utils.go @@ -92,6 +92,7 @@ func openFreezerFileForAppend(filename string) (*os.File, error) { } // Seek to end for append if _, err = file.Seek(0, io.SeekEnd); err != nil { + file.Close() return nil, err } return file, nil From 5150bdbabb56d22f5c248047c80f92666af2b15c Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:01:34 +0800 Subject: [PATCH 28/48] eth/tracers: forward OnSystemCall hooks through mux (#34862) (#3707) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick of go-ethereum b9c5fe6d2 (PR #34862). The mux tracer fanned out every standard hook to its children but never forwarded OnSystemCall{Start,End}. Tracers that rely on these — like logger.jsonLogger, which uses the start hook to silence its opcode hook for the duration of a system call — never got the signal when wrapped behind a mux. Combining --trace with --opcode-count in evm t8n produces exactly that wrapping, and the first system call (e.g. ProcessBeaconBlockRoot) crashes t8n on nil env deref. Forwards OnSystemCallStartV2 (with V1 fallback per child) and OnSystemCallEnd through the mux. Same precedence as core/state_processor.go. Co-authored-by: Claude Opus 4.7 (1M context) --- eth/tracers/native/mux.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/eth/tracers/native/mux.go b/eth/tracers/native/mux.go index 4da3e2531d..c6c5ebbca3 100644 --- a/eth/tracers/native/mux.go +++ b/eth/tracers/native/mux.go @@ -71,6 +71,8 @@ func newMuxTracer(ctx *tracers.Context, cfg json.RawMessage, chainConfig *params OnStorageChange: t.OnStorageChange, OnLog: t.OnLog, OnSystemTxFixIntrinsicGas: t.OnSystemTxFixIntrinsicGas, + OnSystemCallStartV2: t.OnSystemCallStart, + OnSystemCallEnd: t.OnSystemCallEnd, }, GetResult: t.GetResult, Stop: t.Stop, @@ -181,6 +183,24 @@ func (t *muxTracer) OnSystemTxFixIntrinsicGas(intrinsicGas uint64) { } } +func (t *muxTracer) OnSystemCallStart(vm *tracing.VMContext) { + for _, t := range t.tracers { + if t.OnSystemCallStartV2 != nil { + t.OnSystemCallStartV2(vm) + } else if t.OnSystemCallStart != nil { + t.OnSystemCallStart() + } + } +} + +func (t *muxTracer) OnSystemCallEnd() { + for _, t := range t.tracers { + if t.OnSystemCallEnd != nil { + t.OnSystemCallEnd() + } + } +} + // GetResult returns an empty json object. func (t *muxTracer) GetResult() (json.RawMessage, error) { resObject := make(map[string]json.RawMessage) From e5f4f2c15a3dd2d154597b2928123216be38b705 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:01:54 +0800 Subject: [PATCH 29/48] eth/protocols/eth: stop serving on unavailable responses (#34787) (#3705) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cherry-pick of go-ethereum ea1cf7bf5 (PR #34787) — alternative to PR #34746 implementing the simpler approach: when serving GetBlockBodies / GetReceipts and a requested item is unavailable, stop serving instead of silently dropping it. Requests for unavailable items are typically a sign that the peer is following a different fork; replying with a sparse list is misleading because the dropped slots are silently elided. Halting at the first gap gives the requester a clearer signal and saves work. Adapted to BSC's two receipts handlers (68 and 69) which retain the empty-receipts-root branch — that branch continues to serve. Test adjusted to match the new "stop at gap" semantics. Co-authored-by: Claude Opus 4.7 (1M context) --- eth/protocols/eth/handler_test.go | 14 +++++++++----- eth/protocols/eth/handlers.go | 18 ++++++++++-------- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go index 12f4a4b016..b6dbc29872 100644 --- a/eth/protocols/eth/handler_test.go +++ b/eth/protocols/eth/handler_test.go @@ -429,16 +429,20 @@ func testGetBlockBodies(t *testing.T, protocol uint) { {0, []common.Hash{backend.chain.CurrentBlock().Hash()}, []bool{true}, 1}, // The chains head block should be retrievable {0, []common.Hash{{}}, []bool{false}, 0}, // A non existent block should not be returned - // Existing and non-existing blocks interleaved should not cause problems + // Existing blocks followed by a non-existing one should stop at the gap {0, []common.Hash{ - {}, backend.chain.GetBlockByNumber(1).Hash(), - {}, backend.chain.GetBlockByNumber(10).Hash(), - {}, backend.chain.GetBlockByNumber(100).Hash(), {}, - }, []bool{false, true, false, true, false, true, false}, 3}, + }, []bool{true, true, true, false}, 3}, + + // A non-existing block at the start should return nothing + {0, []common.Hash{ + {}, + backend.chain.GetBlockByNumber(1).Hash(), + backend.chain.GetBlockByNumber(10).Hash(), + }, []bool{false, true, true}, 0}, } // Run each of the tests and verify the results against the chain for i, tt := range tests { diff --git a/eth/protocols/eth/handlers.go b/eth/protocols/eth/handlers.go index c5e6afdd74..4ed19a788d 100644 --- a/eth/protocols/eth/handlers.go +++ b/eth/protocols/eth/handlers.go @@ -240,7 +240,7 @@ func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesRequ } body := chain.GetBody(hash) if body == nil { - continue + break // If we don't have this block's body, stop serving. } sidecars := chain.GetSidecarsByHash(hash) bodyWithSidecars := &struct { @@ -257,7 +257,7 @@ func ServiceGetBlockBodiesQuery(chain *core.BlockChain, query GetBlockBodiesRequ enc, err := rlp.EncodeToBytes(bodyWithSidecars) if err != nil { log.Error("block body encode err", "hash", hash, "err", err) - continue + break } bodies = append(bodies, enc) bytes += len(enc) @@ -301,19 +301,20 @@ func ServiceGetReceiptsQuery68(chain *core.BlockChain, query GetReceiptsRequest) // Retrieve the requested block's receipts results := chain.GetReceiptsRLP(hash) if results == nil { + // If we don't have this block (or it isn't an empty-receipts block), stop serving. if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { - continue + break } } else { body := chain.GetBodyRLP(hash) if body == nil { - continue + break // The block body is missing, stop serving. } var err error results, err = blockReceiptsToNetwork68(results, body) if err != nil { log.Error("Error in block receipts conversion", "hash", hash, "err", err) - continue + break } } receipts = append(receipts, results) @@ -338,19 +339,20 @@ func serviceGetReceiptsQuery69(chain *core.BlockChain, query GetReceiptsRequest) // Retrieve the requested block's receipts results := chain.GetReceiptsRLP(hash) if results == nil { + // If we don't have this block (or it isn't an empty-receipts block), stop serving. if header := chain.GetHeaderByHash(hash); header == nil || header.ReceiptHash != types.EmptyRootHash { - continue + break } } else { body := chain.GetBodyRLP(hash) if body == nil { - continue + break // The block body is missing, stop serving. } var err error results, err = blockReceiptsToNetwork69(results, body) if err != nil { log.Error("Error in block receipts conversion", "hash", hash, "err", err) - continue + break } } receipts = append(receipts, results) From a0dbef5e0b827c108f0bcbde5534042c048b364a Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:02:21 +0800 Subject: [PATCH 30/48] p2p/discover: copy buffer before sending read errors to unhandled (#34888) (#3701) Cherry-pick of go-ethereum e1e3eaa38 (PR #34888). The discv4 read loop allocates `buf` once and reuses it for every ReadFromUDPAddrPort call. When a packet fails handlePacket, the raw buffer `buf[:nbytes]` was sent by reference to the `unhandled` channel; by the time the consumer (discv5 in mixed-mode) processes it, the next ReadFromUDPAddrPort had overwritten the buffer contents. bytes.Clone the slice before sending so the consumer owns an independent copy. Co-authored-by: Claude Opus 4.7 (1M context) --- p2p/discover/v4_udp.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go index 67387b6294..e38fad63ce 100644 --- a/p2p/discover/v4_udp.go +++ b/p2p/discover/v4_udp.go @@ -570,8 +570,9 @@ func (t *UDPv4) readLoop(unhandled chan<- ReadPacket) { if err := t.handlePacket(from, buf[:nbytes]); err != nil && unhandled == nil { t.log.Debug("Bad discv4 packet", "addr", from, "err", err) } else if err != nil && unhandled != nil { + p := ReadPacket{bytes.Clone(buf[:nbytes]), from} select { - case unhandled <- ReadPacket{buf[:nbytes], from}: + case unhandled <- p: default: } } From 0608f7edca2e3ca42c61bf3c9b842d530b15d08b Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Wed, 10 Jun 2026 10:02:34 +0800 Subject: [PATCH 31/48] eth/filters: fix source leak when New Filters (#3692) --- eth/filters/api.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eth/filters/api.go b/eth/filters/api.go index 6b27cd2f5b..b974213dff 100644 --- a/eth/filters/api.go +++ b/eth/filters/api.go @@ -221,6 +221,7 @@ func (api *FilterAPI) NewVotesFilter() rpc.ID { api.filtersMu.Unlock() gopool.Submit(func() { + defer voteSub.Unsubscribe() for { select { case vote := <-votes: @@ -345,6 +346,7 @@ func (api *FilterAPI) NewFinalizedHeaderFilter() rpc.ID { api.filtersMu.Unlock() gopool.Submit(func() { + defer headerSub.Unsubscribe() for { select { case h := <-headers: From feba2f0b3f6b15a8d290e2cd7aa03e5ae1123960 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 10 Jun 2026 17:16:01 +0800 Subject: [PATCH 32/48] p2p/discover: fix timeout loop early exit when removing expired matchers (#34743) (#3702) * p2p/discover: fix timeout loop early exit when removing expired matchers (#34743) Cherry-pick of go-ethereum 51c97216c (PR #34743), adapted minimally to keep BSC's manual list iteration (BSC has not adopted the upstream iterList helper, so the upstream regression fixed by 60db25b07 never applied here). In both the gotreply and timeout-deadline loops, plist.Remove(el) invalidates el.Next(), so the next iteration's el.Next() returns nil and the loop exits after removing only the first expired/done matcher. Save el.Next() before calling plist.Remove(el) so iteration continues through every entry. Co-Authored-By: Claude Opus 4.7 (1M context) * p2p/discover: fix resetTimeout loop early exit on clock-warp removal The prior backport of upstream #34743 ported the gotreply and timeout loops but missed the resetTimeout loop. When the system clock jumps backward, expired matchers can still be removed inside resetTimeout via plist.Remove(el); after removal el.Next() returns nil, exiting the loop early and skipping subsequent stale matchers. Save the next element before removing the current one, matching the pattern used in the other two loops. --------- Co-authored-by: Claude Opus 4.7 (1M context) --- p2p/discover/v4_udp.go | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/p2p/discover/v4_udp.go b/p2p/discover/v4_udp.go index e38fad63ce..f080cc7ece 100644 --- a/p2p/discover/v4_udp.go +++ b/p2p/discover/v4_udp.go @@ -448,7 +448,8 @@ func (t *UDPv4) loop(isBootNode bool) { } // Start the timer so it fires when the next pending reply has expired. now := time.Now() - for el := plist.Front(); el != nil; el = el.Next() { + for el := plist.Front(); el != nil; { + next := el.Next() nextTimeout = el.Value.(*replyMatcher) if dist := nextTimeout.deadline.Sub(now); dist < 2*respTimeout { timeout.Reset(dist) @@ -459,6 +460,7 @@ func (t *UDPv4) loop(isBootNode bool) { // backwards after the deadline was assigned. nextTimeout.errc <- errClockWarp plist.Remove(el) + el = next } nextTimeout = nil timeout.Stop() @@ -486,7 +488,8 @@ func (t *UDPv4) loop(isBootNode bool) { case r := <-t.gotreply: var matched bool // whether any replyMatcher considered the reply acceptable. - for el := plist.Front(); el != nil; el = el.Next() { + for el := plist.Front(); el != nil; { + next := el.Next() p := el.Value.(*replyMatcher) if p.from == r.from && p.ptype == r.data.Kind() && p.ip == r.ip { ok, requestDone := p.callback(r.data) @@ -500,6 +503,7 @@ func (t *UDPv4) loop(isBootNode bool) { // Reset the continuous timeout counter (time drift detection) contTimeouts = 0 } + el = next } r.matched <- matched @@ -507,13 +511,15 @@ func (t *UDPv4) loop(isBootNode bool) { nextTimeout = nil // Notify and remove callbacks whose deadline is in the past. - for el := plist.Front(); el != nil; el = el.Next() { + for el := plist.Front(); el != nil; { + next := el.Next() p := el.Value.(*replyMatcher) if now.After(p.deadline) || now.Equal(p.deadline) { p.errc <- errTimeout plist.Remove(el) contTimeouts++ } + el = next } // If we've accumulated too many timeouts, do an NTP time sync check if contTimeouts > ntpFailureThreshold { From 745c1bb61f6fe0d0c16710736c00c94d9a3bf6c4 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Thu, 11 Jun 2026 10:50:59 +0800 Subject: [PATCH 33/48] core/rawdb: cheanup bep-592 bal key related (#3720) --- core/rawdb/database.go | 4 ---- core/rawdb/schema.go | 9 --------- 2 files changed, 13 deletions(-) diff --git a/core/rawdb/database.go b/core/rawdb/database.go index 3b8ac24ba9..8ba416d560 100644 --- a/core/rawdb/database.go +++ b/core/rawdb/database.go @@ -579,7 +579,6 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { tds stat numHashPairings stat blobSidecars stat - bals stat hashNumPairings stat legacyTries stat stateLookups stat @@ -719,8 +718,6 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { // bsc speicial case bytes.HasPrefix(key, BlockBlobSidecarsPrefix): blobSidecars.add(size) - case bytes.HasPrefix(key, BlockBALPrefix): - bals.add(size) case bytes.HasPrefix(key, ParliaSnapshotPrefix) && len(key) == 7+common.HashLength: parliaSnaps.add(size) @@ -807,7 +804,6 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error { {"Key-Value store", "Singleton metadata", metadata.sizeString(), metadata.countString()}, // bsc special {"Key-Value store", "BlobSidecars", blobSidecars.sizeString(), blobSidecars.countString()}, - {"Key-Value store", "Block access list", bals.sizeString(), bals.countString()}, {"Key-Value store", "Parlia snapshots", parliaSnaps.sizeString(), parliaSnaps.countString()}, } diff --git a/core/rawdb/schema.go b/core/rawdb/schema.go index 56cbe66b5b..6b5d83be46 100644 --- a/core/rawdb/schema.go +++ b/core/rawdb/schema.go @@ -149,8 +149,6 @@ var ( BlockBlobSidecarsPrefix = []byte("blobs") - BlockBALPrefix = []byte("bal") // blockBALPrefix + blockNumber (uint64 big endian) + blockHash -> block access list - // new log index filterMapsPrefix = "fm-" filterMapsRangeKey = []byte(filterMapsPrefix + "R") @@ -224,13 +222,6 @@ func blockBlobSidecarsKey(number uint64, hash common.Hash) []byte { return append(append(BlockBlobSidecarsPrefix, encodeBlockNumber(number)...), hash.Bytes()...) } -// blockBALKey = blockBALPrefix + blockNumber (uint64 big endian) + blockHash -// -//nolint:unused -func blockBALKey(number uint64, hash common.Hash) []byte { - return append(append(BlockBALPrefix, encodeBlockNumber(number)...), hash.Bytes()...) -} - // txLookupKey = txLookupPrefix + hash func txLookupKey(hash common.Hash) []byte { return append(txLookupPrefix, hash.Bytes()...) From 7408fed6ec658bf5bb179d72b496fa1212c33516 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Thu, 11 Jun 2026 15:17:20 +0800 Subject: [PATCH 34/48] eth/tracers/logger: fix exclude address list (#34887) (#3703) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * eth/tracers/logger: fix exclude address list (#34887) Cherry-pick of go-ethereum f7b7d4c7e (PR #34887). In NewAccessListTracer, when a prelude AccessList entry's address was in addressesToExclude, list.addAddress was correctly skipped — but the inner for-loop still called list.addSlot for every slot under that address, causing the excluded address to leak into the tracer's output with storage keys attached. Refactored to `continue` on the excluded address so both addAddress and the slot loop are skipped together. Co-Authored-By: Claude Opus 4.7 (1M context) * eth/tracers/logger: fix exclude address list (#34887) --------- Co-authored-by: Claude Opus 4.7 (1M context) --- eth/tracers/logger/access_list_tracer.go | 5 ++- eth/tracers/logger/access_list_tracer_test.go | 39 +++++++++++++++++++ 2 files changed, 42 insertions(+), 2 deletions(-) create mode 100644 eth/tracers/logger/access_list_tracer_test.go diff --git a/eth/tracers/logger/access_list_tracer.go b/eth/tracers/logger/access_list_tracer.go index 0d51f40522..e629eb3d31 100644 --- a/eth/tracers/logger/access_list_tracer.go +++ b/eth/tracers/logger/access_list_tracer.go @@ -106,9 +106,10 @@ type AccessListTracer struct { func NewAccessListTracer(acl types.AccessList, addressesToExclude map[common.Address]struct{}) *AccessListTracer { list := newAccessList() for _, al := range acl { - if _, ok := addressesToExclude[al.Address]; !ok { - list.addAddress(al.Address) + if _, ok := addressesToExclude[al.Address]; ok { + continue } + list.addAddress(al.Address) for _, slot := range al.StorageKeys { list.addSlot(al.Address, slot) } diff --git a/eth/tracers/logger/access_list_tracer_test.go b/eth/tracers/logger/access_list_tracer_test.go new file mode 100644 index 0000000000..04b2b4b31b --- /dev/null +++ b/eth/tracers/logger/access_list_tracer_test.go @@ -0,0 +1,39 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// The go-ethereum library is free software: you can redistribute it and/or modify +// it under the terms of the GNU Lesser General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// The go-ethereum library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with the go-ethereum library. If not, see . + +package logger + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +func TestNewAccessListTracerExcludedAddress(t *testing.T) { + excluded := common.HexToAddress("0x2222222222222222222222222222222222222222") + slot := common.HexToHash("0x01") + prelude := types.AccessList{{ + Address: excluded, + StorageKeys: []common.Hash{slot}, + }} + excl := map[common.Address]struct{}{excluded: {}} + tracer := NewAccessListTracer(prelude, excl) + got := tracer.AccessList() + if len(got) != 0 { + t.Fatalf("excluded prelude address must not contribute tuples, got %+v", got) + } +} From 1b8a634ed95a7f445cf3a3fe567aa0e5d8650c73 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Thu, 11 Jun 2026 15:17:36 +0800 Subject: [PATCH 35/48] cmd, core, eth, tests: prevent state flushing in RPC (#33931) (#3684) * cmd, core, eth, tests: prevent state flushing in RPC (#33931) Fixes https://github.com/ethereum/go-ethereum/issues/33572 * core/vm: clean vm.Config * eth: check block to avoid panic --------- Co-authored-by: rjl493456442 --- cmd/utils/flags.go | 5 +- core/blockchain.go | 124 +++++++++++++++++++++++++----------- core/vm/interpreter.go | 6 +- eth/api_debug.go | 37 ++++------- eth/backend.go | 5 +- internal/web3ext/web3ext.go | 11 ++-- tests/block_test_util.go | 4 +- 7 files changed, 114 insertions(+), 78 deletions(-) diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 60a02760f5..310ad44d22 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -2895,8 +2895,6 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh } vmcfg := vm.Config{ EnablePreimageRecording: ctx.Bool(VMEnableDebugFlag.Name), - EnableWitnessStats: ctx.Bool(VMWitnessStatsFlag.Name), - StatelessSelfValidation: ctx.Bool(VMStatelessSelfValidationFlag.Name) || ctx.Bool(VMWitnessStatsFlag.Name), EnableOpcodeOptimizations: ctx.Bool(VMOpcodeOptimizeFlag.Name), } @@ -2915,6 +2913,9 @@ func MakeChain(ctx *cli.Context, stack *node.Node, readonly bool) (*core.BlockCh } options.VmConfig = vmcfg + options.StatelessSelfValidation = ctx.Bool(VMStatelessSelfValidationFlag.Name) || ctx.Bool(VMWitnessStatsFlag.Name) + options.EnableWitnessStats = ctx.Bool(VMWitnessStatsFlag.Name) + chain, err := core.NewBlockChain(chainDb, gspec, engine, options) if err != nil { Fatalf("Can't create BlockChain: %v", err) diff --git a/core/blockchain.go b/core/blockchain.go index 0f92fd2204..aa21ae1834 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -18,6 +18,7 @@ package core import ( + "context" "errors" "fmt" "io" @@ -230,6 +231,18 @@ type BlockChainConfig struct { // StateSizeTracking indicates whether the state size tracking is enabled. StateSizeTracking bool + + // EnableBAL enables the block access list feature + EnableBAL bool + + // SlowBlockThreshold is the block execution time threshold beyond which + // detailed statistics will be logged. Negative value means disabled (default), + // zero logs all blocks, positive value filters blocks by execution time. + SlowBlockThreshold time.Duration + + // Execution configs + StatelessSelfValidation bool // Generate execution witnesses and self-check against them (testing purpose) + EnableWitnessStats bool // Whether trie access statistics collection is enabled } // DefaultConfig returns the default config. @@ -2393,7 +2406,15 @@ func (bc *BlockChain) insertChain(chain types.Blocks, setHead bool, makeWitness bc.updateHighestVerifiedHeader(block.Header()) // The traced section of block import. start := time.Now() - res, err := bc.ProcessBlock(parent.Root, block, setHead, makeWitness && len(chain) == 1) + config := ExecuteConfig{ + WriteState: true, + WriteHead: setHead, + EnableTracer: true, + MakeWitness: makeWitness && len(chain) == 1, + StatelessSelfValidation: bc.cfg.StatelessSelfValidation, + EnableWitnessStats: bc.cfg.EnableWitnessStats, + } + res, err := bc.ProcessBlock(context.Background(), parent.Root, block, config) if err != nil { return nil, it.index, err } @@ -2496,9 +2517,36 @@ func (bpr *blockProcessingResult) Witness() *stateless.Witness { return bpr.witness } +// ExecuteConfig defines optional behaviors during execution. +type ExecuteConfig struct { + // WriteState controls whether the computed state changes are persisted to + // the underlying storage. If false, execution is performed in-memory only. + WriteState bool + + // WriteHead indicates whether the execution result should update the canonical + // chain head. It's only relevant with WriteState == True. + WriteHead bool + + // EnableTracer enables execution tracing. This is typically used for debugging + // or analysis and may significantly impact performance. + EnableTracer bool + + // MakeWitness indicates whether to generate execution witness data during + // execution. Enabling this may introduce additional memory and CPU overhead. + MakeWitness bool + + // StatelessSelfValidation indicates whether the execution witnesses generation + // and self-validation (testing purpose) is enabled. + StatelessSelfValidation bool + + // EnableWitnessStats indicates whether to enable collection of witness trie + // access statistics + EnableWitnessStats bool +} + // ProcessBlock executes and validates the given block. If there was no error // it writes the block and associated state to database. -func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, setHead bool, makeWitness bool) (_ *blockProcessingResult, blockEndErr error) { +func (bc *BlockChain) ProcessBlock(ctx context.Context, parentRoot common.Hash, block *types.Block, config ExecuteConfig) (result *blockProcessingResult, blockEndErr error) { var ( err error startTime = time.Now() @@ -2570,12 +2618,12 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s // Generate witnesses either if we're self-testing, or if it's the // only block being inserted. A bit crude, but witnesses are huge, // so we refuse to make an entire chain of them. - if bc.cfg.VmConfig.StatelessSelfValidation || makeWitness { + if config.StatelessSelfValidation || config.MakeWitness { witness, err = stateless.NewWitness(block.Header(), bc) if err != nil { return nil, err } - if bc.cfg.VmConfig.EnableWitnessStats { + if config.EnableWitnessStats { witnessStats = stateless.NewWitnessStats() } } @@ -2583,19 +2631,22 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s defer statedb.StopPrefetcher() } - if bc.logger != nil && bc.logger.OnBlockStart != nil { - td := bc.GetTd(block.ParentHash(), block.NumberU64()-1) - bc.logger.OnBlockStart(tracing.BlockEvent{ - Block: block, - TD: td, - Finalized: bc.CurrentFinalBlock(), - Safe: bc.CurrentSafeBlock(), - }) - } - if bc.logger != nil && bc.logger.OnBlockEnd != nil { - defer func() { - bc.logger.OnBlockEnd(blockEndErr) - }() + // Instrument the blockchain tracing + if config.EnableTracer { + if bc.logger != nil && bc.logger.OnBlockStart != nil { + td := bc.GetTd(block.ParentHash(), block.NumberU64()-1) + bc.logger.OnBlockStart(tracing.BlockEvent{ + Block: block, + TD: td, + Finalized: bc.CurrentFinalBlock(), + Safe: bc.CurrentSafeBlock(), + }) + } + if bc.logger != nil && bc.logger.OnBlockEnd != nil { + defer func() { + bc.logger.OnBlockEnd(blockEndErr) + }() + } } // Process block using the parent state as reference point @@ -2623,7 +2674,7 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s // witness builder/runner, which would otherwise be impossible due to the // various invalid chain states/behaviors being contained in those tests. xvstart := time.Now() - if witness := statedb.Witness(); witness != nil && bc.cfg.VmConfig.StatelessSelfValidation { + if witness := statedb.Witness(); witness != nil && config.StatelessSelfValidation { log.Warn("Running stateless self-validation", "block", block.Number(), "hash", block.Hash()) // Remove critical computed fields from the block to force true recalculation @@ -2668,30 +2719,29 @@ func (bc *BlockChain) ProcessBlock(parentRoot common.Hash, block *types.Block, s blockCrossValidationTimer.Update(xvtime) // The time spent on stateless cross validation // Write the block to the chain and get the status. - var ( - wstart = time.Now() - status WriteStatus - ) - if !setHead { - // 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) - } - if err != nil { - return nil, err + var status WriteStatus + if config.WriteState { + wstart := time.Now() + if !config.WriteHead { + // 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) + } + if err != nil { + return nil, err + } + // Update the metrics touched during block commit + accountCommitTimer.Update(statedb.AccountCommits) + storageCommitTimer.Update(statedb.StorageCommits) + snapshotCommitTimer.Update(statedb.SnapshotCommits) + triedbCommitTimer.Update(statedb.TrieDBCommits) + blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits) } // Report the collected witness statistics if witnessStats != nil { witnessStats.ReportMetrics(block.NumberU64()) } - - // Update the metrics touched during block commit - accountCommitTimer.Update(statedb.AccountCommits) // Account commits are complete, we can mark them - storageCommitTimer.Update(statedb.StorageCommits) // Storage commits are complete, we can mark them - snapshotCommitTimer.Update(statedb.SnapshotCommits) // Snapshot commits are complete, we can mark them - triedbCommitTimer.Update(statedb.TrieDBCommits) // Trie database commits are complete, we can mark them - blockWriteTimer.Update(time.Since(wstart) - max(statedb.AccountCommits, statedb.StorageCommits) /* concurrent */ - statedb.SnapshotCommits - statedb.TrieDBCommits) elapsed := time.Since(startTime) + 1 // prevent zero division blockInsertTimer.Update(elapsed) blockInsertTxSizeGauge.Update(int64(len(block.Transactions()))) diff --git a/core/vm/interpreter.go b/core/vm/interpreter.go index 27cbb46c03..6762ecb087 100644 --- a/core/vm/interpreter.go +++ b/core/vm/interpreter.go @@ -29,14 +29,12 @@ import ( // Config are the configuration options for the Interpreter type Config struct { - Tracer *tracing.Hooks + Tracer *tracing.Hooks + NoBaseFee bool // Forces the EIP-1559 baseFee to 0 (needed for 0 price calls) EnablePreimageRecording bool // Enables recording of SHA3/keccak preimages ExtraEips []int // Additional EIPS that are to be enabled EnableOpcodeOptimizations bool // Enable opcode optimization - - StatelessSelfValidation bool // Generate execution witnesses and self-check against them (testing purpose) - EnableWitnessStats bool // Whether trie access statistics collection is enabled } // ScopeContext contains the things that are per-call, such as stack and memory, diff --git a/eth/api_debug.go b/eth/api_debug.go index 63cfa0ea23..ed4d4b63d4 100644 --- a/eth/api_debug.go +++ b/eth/api_debug.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/stateless" @@ -496,39 +497,23 @@ func (api *DebugAPI) StateSize(blockHashOrNumber *rpc.BlockNumberOrHash) (interf }, nil } -func (api *DebugAPI) ExecutionWitness(bn rpc.BlockNumber) (*stateless.ExtWitness, error) { +func (api *DebugAPI) ExecutionWitness(bn rpc.BlockNumberOrHash) (*stateless.ExtWitness, error) { bc := api.eth.blockchain - block, err := api.eth.APIBackend.BlockByNumber(context.Background(), bn) - if err != nil { - return &stateless.ExtWitness{}, fmt.Errorf("block number %v not found", bn) + block, err := api.eth.APIBackend.BlockByNumberOrHash(context.Background(), bn) + if block == nil || err != nil { + return &stateless.ExtWitness{}, fmt.Errorf("block %v not found", bn) } parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1) if parent == nil { - return &stateless.ExtWitness{}, fmt.Errorf("block number %v found, but parent missing", bn) - } - - result, err := bc.ProcessBlock(parent.Root, block, false, true) - if err != nil { - return nil, err - } - - return result.Witness().ToExtWitness(), nil -} - -func (api *DebugAPI) ExecutionWitnessByHash(hash common.Hash) (*stateless.ExtWitness, error) { - bc := api.eth.blockchain - block := bc.GetBlockByHash(hash) - if block == nil { - return &stateless.ExtWitness{}, fmt.Errorf("block hash %x not found", hash) + return &stateless.ExtWitness{}, fmt.Errorf("block %v found, but parent missing", bn) } - - parent := bc.GetHeader(block.ParentHash(), block.NumberU64()-1) - if parent == nil { - return &stateless.ExtWitness{}, fmt.Errorf("block number %x found, but parent missing", hash) + config := core.ExecuteConfig{ + WriteState: false, + EnableTracer: false, + MakeWitness: true, } - - result, err := bc.ProcessBlock(parent.Root, block, false, true) + result, err := bc.ProcessBlock(context.Background(), parent.Root, block, config) if err != nil { return nil, err } diff --git a/eth/backend.go b/eth/backend.go index 4bead869b5..9ef779e409 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -360,8 +360,6 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { TxLookupLimit: int64(min(config.TransactionHistory, math.MaxInt64)), VmConfig: vm.Config{ EnablePreimageRecording: config.EnablePreimageRecording, - EnableWitnessStats: config.EnableWitnessStats, - StatelessSelfValidation: config.StatelessSelfValidation, EnableOpcodeOptimizations: config.EnableOpcodeOptimizing, }, // Enables file journaling for the trie database. The journal files will be stored @@ -370,6 +368,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) { // - DATADIR/triedb/verkle.journal TrieJournalDirectory: stack.ResolvePath("triedb"), StateSizeTracking: config.EnableStateSizeTracking, + + StatelessSelfValidation: config.StatelessSelfValidation, + EnableWitnessStats: config.EnableWitnessStats, } ) if config.DisableTxIndexer { diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index 99b9214684..fb9c4e25b7 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -413,11 +413,6 @@ web3._extend({ params: 2, inputFormatter:[null, null], }), - new web3._extend.Method({ - name: 'freezeClient', - call: 'debug_freezeClient', - params: 1, - }), new web3._extend.Method({ name: 'getAccessibleState', call: 'debug_getAccessibleState', @@ -460,6 +455,12 @@ web3._extend({ params: 1, inputFormatter: [null], }), + new web3._extend.Method({ + name: 'executionWitness', + call: 'debug_executionWitness', + params: 1, + inputFormatter: [null], + }), ], properties: [] }); diff --git a/tests/block_test_util.go b/tests/block_test_util.go index bd9639474c..2bcaaca16a 100644 --- a/tests/block_test_util.go +++ b/tests/block_test_util.go @@ -158,9 +158,9 @@ func (t *BlockTest) Run(snapshotter bool, scheme string, witness bool, tracer *t Preimages: true, TxLookupLimit: -1, // disable tx indexing VmConfig: vm.Config{ - Tracer: tracer, - StatelessSelfValidation: witness, + Tracer: tracer, }, + StatelessSelfValidation: witness, } if snapshotter { options.SnapshotLimit = 1 From 31a34ac989c57b2b00522bfb6f0ebf8eb362b79a Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Mon, 15 Jun 2026 14:04:59 +0800 Subject: [PATCH 36/48] core/systemcontracts: introduce Pasteur hardfork system-contract upgrade (#3721) Wire the Pasteur hardfork to upgrade two system contracts whose bytecode changed on the genesis-contract side: - StakeHub (0x2002): propagate slash eviction to BSCValidatorSet after consensus-key rotation (bsc-genesis-contract #664) - BSCGovernor (0x2004): reject blacklisted voter on castVoteBySig (#667) Adds the `pasteur` bytecode package (StakeHub/Governor for Mainnet, Chapel, Rialto) and applies it in upgradeBuildInSystemContract when IsOnPasteur. Bytecode extracted from the regenerated genesis (bsc-genesis-contract commit 3f02a2e); CommitUrl points there for now and should be updated to the Pasteur release merge commit once available. PasteurTime scheduling in params/config.go is intentionally left unset. Co-authored-by: Claude Opus 4.8 (1M context) --- .../pasteur/chapel/GovernorContract | 1 + .../pasteur/chapel/StakeHubContract | 1 + .../pasteur/mainnet/GovernorContract | 1 + .../pasteur/mainnet/StakeHubContract | 1 + .../pasteur/rialto/GovernorContract | 1 + .../pasteur/rialto/StakeHubContract | 1 + core/systemcontracts/pasteur/types.go | 30 ++++++++++ core/systemcontracts/upgrade.go | 55 +++++++++++++++++++ 8 files changed, 91 insertions(+) create mode 100644 core/systemcontracts/pasteur/chapel/GovernorContract create mode 100644 core/systemcontracts/pasteur/chapel/StakeHubContract create mode 100644 core/systemcontracts/pasteur/mainnet/GovernorContract create mode 100644 core/systemcontracts/pasteur/mainnet/StakeHubContract create mode 100644 core/systemcontracts/pasteur/rialto/GovernorContract create mode 100644 core/systemcontracts/pasteur/rialto/StakeHubContract create mode 100644 core/systemcontracts/pasteur/types.go diff --git a/core/systemcontracts/pasteur/chapel/GovernorContract b/core/systemcontracts/pasteur/chapel/GovernorContract new file mode 100644 index 0000000000..861f33d447 --- /dev/null +++ b/core/systemcontracts/pasteur/chapel/GovernorContract @@ -0,0 +1 @@ +6080604052600436106103e85760003560e01c80637b3c71d311610208578063c28bc2fa11610118578063deaaa7cc116100ab578063ece40cc11161007a578063ece40cc114610e19578063f23a6e6114610e39578063f8ce560a14610e65578063fc0c546a14610e85578063fe0d94c114610ea657600080fd5b8063deaaa7cc14610cda578063e23a9a5214610d0e578063ea0217cf14610dd9578063eb9019d414610df957600080fd5b8063da95691a116100e7578063da95691a14610c2f578063dd42a1dd14610c4f578063dd4e2ba514610c74578063ddf0b00914610cba57600080fd5b8063c28bc2fa14610bbd578063c59057e414610bd0578063d07f91e914610bf0578063d33219b414610c1057600080fd5b8063a7713a701161019b578063b187bd261161016a578063b187bd2614610b23578063b58131b014610b41578063bc197c8114610b56578063c01f9e3714610b82578063c170ec0b14610ba257600080fd5b8063a7713a7014610aae578063a890c91014610ac3578063ab58fb8e14610ae3578063ac43175114610b0357600080fd5b806384b0196e116101d757806384b0196e14610a2657806391ddadf414610a4e57806397c3d33414610a7a5780639a802a6d14610a8e57600080fd5b80637b3c71d3146109bc5780637d5e81e2146109dc5780638129fc1c146109fc5780638456cb5914610a1157600080fd5b806332b8113e116103035780634838d1651161029657806354fd4d501161026557806354fd4d5014610912578063567813881461093c5780635f398a141461095c57806360c4247f1461097c57806370b0f6601461099c57600080fd5b80634838d1651461087c5780634a49ac4c146108ac5780634bf5d7e9146108cc578063533ddd14146108e157600080fd5b806340e58ee5116102d257806340e58ee5146107d1578063417c73a7146107f15780634385963214610811578063452115d61461085c57600080fd5b806332b8113e146107455780633932abb11461076e5780633bccf4fd146107845780633e4f49e6146107a457600080fd5b8063150b7a021161037b5780632656227d1161034a5780632656227d146106975780632d63f693146106aa5780632fe3e261146106e1578063328dd9821461071557600080fd5b8063150b7a02146105f0578063160cbed71461063457806317977c611461065457806324bc1a641461068257600080fd5b8063046f7da2116103b7578063046f7da21461054357806306f3f9e61461055857806306fdde0314610578578063143489d01461059a57600080fd5b8063013cf08b1461045857806301ffc9a7146104d357806302a251a314610503578063034201811461052357600080fd5b3661045357306103f6610eb9565b6001600160a01b0316146104515760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206d7573742073656e6420746f206578656375746f720060448201526064015b60405180910390fd5b005b600080fd5b34801561046457600080fd5b50610478610473366004615ca2565b610ed3565b604080519a8b526001600160a01b0390991660208b0152978901969096526060880194909452608087019290925260a086015260c085015260e084015215156101008301521515610120820152610140015b60405180910390f35b3480156104df57600080fd5b506104f36104ee366004615cbb565b610f8e565b60405190151581526020016104ca565b34801561050f57600080fd5b50610195545b6040519081526020016104ca565b34801561052f57600080fd5b5061051561053e366004615e01565b610f9f565b34801561054f57600080fd5b50610451611097565b34801561056457600080fd5b50610451610573366004615ca2565b611127565b34801561058457600080fd5b5061058d6111b2565b6040516104ca9190615ef7565b3480156105a657600080fd5b506105d86105b5366004615ca2565b60009081526101636020526040902054600160401b90046001600160a01b031690565b6040516001600160a01b0390911681526020016104ca565b3480156105fc57600080fd5b5061061b61060b366004615f1f565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016104ca565b34801561064057600080fd5b5061051561064f3660046160f6565b611245565b34801561066057600080fd5b5061051561066f366004616185565b6102c36020526000908152604090205481565b34801561068e57600080fd5b50610515611330565b6105156106a53660046160f6565b611356565b3480156106b657600080fd5b506105156106c5366004615ca2565b600090815261016360205260409020546001600160401b031690565b3480156106ed57600080fd5b506105157fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b34801561072157600080fd5b50610735610730366004615ca2565b611449565b6040516104ca949392919061626b565b34801561075157600080fd5b5061028f546040516001600160401b0390911681526020016104ca565b34801561077a57600080fd5b5061019454610515565b34801561079057600080fd5b5061051561079f3660046162b8565b6116db565b3480156107b057600080fd5b506107c46107bf366004615ca2565b611751565b6040516104ca919061631c565b3480156107dd57600080fd5b506104516107ec366004615ca2565b61175c565b3480156107fd57600080fd5b5061045161080c366004616185565b611787565b34801561081d57600080fd5b506104f361082c366004616344565b60008281526101c6602090815260408083206001600160a01b038516845260080190915290205460ff1692915050565b34801561086857600080fd5b506105156108773660046160f6565b611808565b34801561088857600080fd5b506104f3610897366004616185565b60016020526000908152604090205460ff1681565b3480156108b857600080fd5b506104516108c7366004616185565b611816565b3480156108d857600080fd5b5061058d611891565b3480156108ed57600080fd5b506104f36108fc366004616185565b6102c16020526000908152604090205460ff1681565b34801561091e57600080fd5b506040805180820190915260018152603160f81b602082015261058d565b34801561094857600080fd5b50610515610957366004616374565b61193e565b34801561096857600080fd5b506105156109773660046163a0565b611967565b34801561098857600080fd5b50610515610997366004615ca2565b6119b1565b3480156109a857600080fd5b506104516109b7366004615ca2565b611a66565b3480156109c857600080fd5b506105156109d7366004616423565b611aee565b3480156109e857600080fd5b506105156109f736600461647c565b611b40565b348015610a0857600080fd5b50610451611c5b565b348015610a1d57600080fd5b50610451611e8c565b348015610a3257600080fd5b50610a3b611f22565b6040516104ca979695949392919061651c565b348015610a5a57600080fd5b50610a63611fc0565b60405165ffffffffffff90911681526020016104ca565b348015610a8657600080fd5b506064610515565b348015610a9a57600080fd5b50610515610aa936600461657e565b612034565b348015610aba57600080fd5b5061051561204b565b348015610acf57600080fd5b50610451610ade366004616185565b612078565b348015610aef57600080fd5b50610515610afe366004615ca2565b612100565b348015610b0f57600080fd5b50610451610b1e3660046165d6565b61219c565b348015610b2f57600080fd5b5060005462010000900460ff166104f3565b348015610b4d57600080fd5b506105156128e1565b348015610b6257600080fd5b5061061b610b71366004616635565b63bc197c8160e01b95945050505050565b348015610b8e57600080fd5b50610515610b9d366004615ca2565b6128ed565b348015610bae57600080fd5b506102c2546104f39060ff1681565b610451610bcb3660046166c8565b6128f8565b348015610bdc57600080fd5b50610515610beb3660046160f6565b612a08565b348015610bfc57600080fd5b50610451610c0b36600461670b565b612a42565b348015610c1c57600080fd5b5061022b546001600160a01b03166105d8565b348015610c3b57600080fd5b50610515610c4a366004616734565b612aca565b348015610c5b57600080fd5b50600054630100000090046001600160a01b03166105d8565b348015610c8057600080fd5b5060408051808201909152601a81527f737570706f72743d627261766f2671756f72756d3d627261766f000000000000602082015261058d565b348015610cc657600080fd5b50610451610cd5366004615ca2565b612b51565b348015610ce657600080fd5b506105157f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610d1a57600080fd5b50610da9610d29366004616344565b60408051606081018252600080825260208201819052918101919091525060009182526101c6602090815260408084206001600160a01b0393909316845260089092018152918190208151606081018352905460ff8082161515835261010082041693820193909352620100009092046001600160601b03169082015290565b6040805182511515815260208084015160ff1690820152918101516001600160601b0316908201526060016104ca565b348015610de557600080fd5b50610451610df4366004615ca2565b612b74565b348015610e0557600080fd5b50610515610e143660046167d5565b612bfc565b348015610e2557600080fd5b50610451610e34366004615ca2565b612c1d565b348015610e4557600080fd5b5061061b610e54366004616801565b63f23a6e6160e01b95945050505050565b348015610e7157600080fd5b50610515610e80366004615ca2565b612ca5565b348015610e9157600080fd5b506101f8546105d8906001600160a01b031681565b610451610eb4366004615ca2565b612d34565b6000610ece61022b546001600160a01b031690565b905090565b8060008080808080808080610ee78a612100565b60008c815261016360205260409020549098506001600160401b03169650610f0e8b6128ed565b60008c81526101c66020526040812080546005820154600683015460078401546001600160a01b039093169e50949a509850929650919450610f4f8d611751565b90506002816007811115610f6557610f65616306565b1493506007816007811115610f7c57610f7c616306565b14925050509193959799509193959799565b6000610f9982612d57565b92915050565b60008061104361103b7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c604051610fdb929190616869565b60405180910390208b80519060200120604051602001611020959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b60405160208183030381529060405280519060200120612d7c565b868686612da9565b90506110898a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d9250612dc7915050565b9a9950505050505050505050565b600054630100000090046001600160a01b031633146110c9576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff166110f257604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b61112f610eb9565b6001600160a01b0316336001600160a01b03161461115f5760405162461bcd60e51b815260040161044890616879565b30611168610eb9565b6001600160a01b0316146111a65760008036604051611188929190616869565b604051809103902090505b8061119f610164612e6a565b0361119357505b6111af81612ee9565b50565b606061016280546111c2906168b0565b80601f01602080910402602001604051908101604052809291908181526020018280546111ee906168b0565b801561123b5780601f106112105761010080835404028352916020019161123b565b820191906000526020600020905b81548152906001019060200180831161121e57829003601f168201915b5050505050905090565b6000805462010000900460ff161561127057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156112a15760405163b1d02c3d60e01b815260040160405180910390fd5b60005b855181101561131a576102c160008783815181106112c4576112c46168ea565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1661130857604051630b094f2760e31b815260040160405180910390fd5b8061131281616916565b9150506112a4565b506113278585858561305a565b95945050505050565b6000610ece600161133f611fc0565b611349919061692f565b65ffffffffffff16612ca5565b60008061136586868686612a08565b9050600061137282611751565b9050600481600781111561138857611388616306565b14806113a5575060058160078111156113a3576113a3616306565b145b6113c15760405162461bcd60e51b815260040161044890616955565b6000828152610163602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f906114109084815260200190565b60405180910390a1611425828888888861325f565b6114328288888888613300565b61143f82888888886133e2565b5095945050505050565b60608060608060006101c66000878152602001908152602001600020905080600101816002018260030183600401838054806020026020016040519081016040528092919081815260200182805480156114cc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114ae575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561151e57602002820191906000526020600020905b81548152602001906001019080831161150a575b5050505050925081805480602002602001604051908101604052809291908181526020016000905b828210156115f2578382906000526020600020018054611565906168b0565b80601f0160208091040260200160405190810160405280929190818152602001828054611591906168b0565b80156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505081526020019060010190611546565b50505050915080805480602002602001604051908101604052809291908181526020016000905b828210156116c5578382906000526020600020018054611638906168b0565b80601f0160208091040260200160405190810160405280929190818152602001828054611664906168b0565b80156116b15780601f10611686576101008083540402835291602001916116b1565b820191906000526020600020905b81548152906001019060200180831161169457829003601f168201915b505050505081526020019060010190611619565b5050505090509450945094509450509193509193565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff8516606082015260009081906117299061103b90608001611020565b90506117468782886040518060200160405280600081525061341d565b979650505050505050565b6000610f9982613440565b60008060008061176b8561358d565b935093509350935061177f84848484611808565b505050505050565b600054630100000090046001600160a01b031633146117b9576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60006113278585858561381e565b600054630100000090046001600160a01b03163314611848576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b6101f85460408051634bf5d7e960e01b815290516060926001600160a01b031691634bf5d7e99160048083019260009291908290030181865afa9250505080156118fd57506040513d6000823e601f3d908101601f191682016040526118fa9190810190616996565b60015b611939575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b60008033905061195f8482856040518060200160405280600081525061341d565b949350505050565b60008033905061174687828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250612dc7915050565b61025e546000908082036119ca57505061025d54919050565b600061025e6119da600184616a03565b815481106119ea576119ea6168ea565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b03169282019290925291508410611a4057602001516001600160e01b03169392505050565b611a55611a4c856138e9565b61025e90613952565b6001600160e01b0316949350505050565b611a6e610eb9565b6001600160a01b0316336001600160a01b031614611a9e5760405162461bcd60e51b815260040161044890616879565b30611aa7610eb9565b6001600160a01b031614611ae55760008036604051611ac7929190616869565b604051809103902090505b80611ade610164612e6a565b03611ad257505b6111af81613a05565b600080339050611b3686828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061341d92505050565b9695505050505050565b6000805462010000900460ff1615611b6b57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615611b9c5760405163b1d02c3d60e01b815260040160405180910390fd5b611ba4613a48565b3360009081526102c360205260409020548015611c19576000611bc682611751565b90506001816007811115611bdc57611bdc616306565b1480611bf957506000816007811115611bf757611bf7616306565b145b15611c175760405163867f3ee560e01b815260040160405180910390fd5b505b825160208401206000611c2e88888885612a08565b3360009081526102c3602052604090208190559050611c4f88888888613af3565b98975050505050505050565b600054610100900460ff1615808015611c7b5750600054600160ff909116105b80611c955750303b158015611c95575060005460ff166001145b611cf85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610448565b6000805460ff191660011790558015611d1b576000805461ff0019166101001790555b334114611d3b5760405163022d8c9560e31b815260040160405180910390fd5b3a15611d5a576040516383f1b1d360e01b815260040160405180910390fd5b611d866040518060400160405280600b81526020016a2129a1a3b7bb32b93737b960a91b815250613b5b565b611db2611d9560036000616a2c565b611da3600362015180616a2c565b68056bc75e2d63100000613bb2565b611dba613be9565b611dc5612005613c10565b611dd0612006613c40565b611dda600a613c70565b611def611dea6003610e10616a2c565b613ca0565b6110076000526102c16020527f2f832952f0ef896b8c8edd6d16a2e4f2591a90375e33021e3b9ff197f3793fc0805460ff19166001179055611e447330151da466ec8ab345bef3d6983023e050fb0673613cd0565b80156111af576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b600054630100000090046001600160a01b03163314611ebe576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1615611ee857604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b6000606080600080600060606098546000801b148015611f425750609954155b611f865760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606401610448565b611f8e613d23565b611f96613d32565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6101f854604080516324776b7d60e21b815290516000926001600160a01b0316916391ddadf49160048083019260209291908290030181865afa925050508015612027575060408051601f3d908101601f1916820190925261202491810190616a4e565b60015b61193957610ece43613d41565b6000612041848484613da8565b90505b9392505050565b61025e54600090156120705761206261025e613e1f565b6001600160e01b0316905090565b5061025d5490565b612080610eb9565b6001600160a01b0316336001600160a01b0316146120b05760405162461bcd60e51b815260040161044890616879565b306120b9610eb9565b6001600160a01b0316146120f757600080366040516120d9929190616869565b604051809103902090505b806120f0610164612e6a565b036120e457505b6111af81613e4f565b61022b54600082815261022c602052604080822054905163d45c443560e01b81526004810191909152909182916001600160a01b039091169063d45c443590602401602060405180830381865afa15801561215f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121839190616a76565b9050806001146121935780612044565b60009392505050565b33611007146121c257604051630f22c43960e41b81526110076004820152602401610448565b6122286040518060400160405280600b81526020016a766f74696e6744656c617960a81b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eba9050565b156122dd57602081146122565783838383604051630a5a604160e01b81526004016104489493929190616ab8565b604080516020601f8401819004810282018101909252828152600091612297918585808385018382808284376000920191909152509293925050613f139050565b90508015806122a857506201518081115b156122ce5784848484604051630a5a604160e01b81526004016104489493929190616ab8565b6122d781613a05565b5061289e565b6123446040518060400160405280600c81526020016b1d9bdd1a5b99d4195c9a5bd960a21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eba9050565b156123f357602081146123725783838383604051630a5a604160e01b81526004016104489493929190616ab8565b604080516020601f84018190048102820181019092528281526000916123b3918585808385018382808284376000920191909152509293925050613f139050565b90508015806123c4575062278d0081115b156123ea5784848484604051630a5a604160e01b81526004016104489493929190616ab8565b6122d781613f18565b61245f604051806040016040528060118152602001701c1c9bdc1bdcd85b151a1c995cda1bdb19607a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eba9050565b15612515576020811461248d5783838383604051630a5a604160e01b81526004016104489493929190616ab8565b604080516020601f84018190048102820181019092528281526000916124ce918585808385018382808284376000920191909152509293925050613f139050565b90508015806124e6575069021e19e0c9bab240000081115b1561250c5784848484604051630a5a604160e01b81526004016104489493929190616ab8565b6122d781613fbb565b61257f6040518060400160405280600f81526020016e38bab7b93ab6a73ab6b2b930ba37b960891b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eba9050565b1561262e57602081146125ad5783838383604051630a5a604160e01b81526004016104489493929190616ab8565b604080516020601f84018190048102820181019092528281526000916125ee918585808385018382808284376000920191909152509293925050613f139050565b905060058110806125ff5750601481115b156126255784848484604051630a5a604160e01b81526004016104489493929190616ab8565b6122d781612ee9565b61269d604051806040016040528060148152602001736d696e506572696f64416674657251756f72756d60601b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eba9050565b1561276357600881146126cb5783838383604051630a5a604160e01b81526004016104489493929190616ab8565b6000612711600884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613f139050565b90506001600160401b038116158061273457506202a300816001600160401b0316115b1561275a5784848484604051630a5a604160e01b81526004016104489493929190616ab8565b6122d781613ffe565b6127cf6040518060400160405280601181526020017033b7bb32b93737b9283937ba32b1ba37b960791b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eba9050565b1561287d57601481146127fd5783838383604051630a5a604160e01b81526004016104489493929190616ab8565b6000612843601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613f139050565b90506001600160a01b0381166128745784848484604051630a5a604160e01b81526004016104489493929190616ab8565b6122d78161406a565b838383836040516325ee20d560e21b81526004016104489493929190616ab8565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516128d39493929190616ab8565b60405180910390a150505050565b6000610ece6101965490565b6000610f99826140d6565b612900610eb9565b6001600160a01b0316336001600160a01b0316146129305760405162461bcd60e51b815260040161044890616879565b30612939610eb9565b6001600160a01b0316146129775760008036604051612959929190616869565b604051809103902090505b80612970610164612e6a565b0361296457505b600080856001600160a01b0316858585604051612995929190616869565b60006040518083038185875af1925050503d80600081146129d2576040519150601f19603f3d011682016040523d82523d6000602084013e6129d7565b606091505b50915091506129ff8282604051806060016040528060288152602001616f1560289139614114565b50505050505050565b600084848484604051602001612a219493929190616adf565b60408051601f19818403018152919052805160209091012095945050505050565b612a4a610eb9565b6001600160a01b0316336001600160a01b031614612a7a5760405162461bcd60e51b815260040161044890616879565b30612a83610eb9565b6001600160a01b031614612ac15760008036604051612aa3929190616869565b604051809103902090505b80612aba610164612e6a565b03612aae57505b6111af81613ffe565b60008251845114612b2e5760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72427261766f3a20696e76616c6964207369676e61747572656044820152670e640d8cadccee8d60c31b6064820152608401610448565b612b3c33878787878761412d565b611b368686612b4b87876141eb565b85611b40565b600080600080612b608561358d565b935093509350935061177f84848484611245565b612b7c610eb9565b6001600160a01b0316336001600160a01b031614612bac5760405162461bcd60e51b815260040161044890616879565b30612bb5610eb9565b6001600160a01b031614612bf35760008036604051612bd5929190616869565b604051809103902090505b80612bec610164612e6a565b03612be057505b6111af81613f18565b60006120448383612c1860408051602081019091526000815290565b613da8565b612c25610eb9565b6001600160a01b0316336001600160a01b031614612c555760405162461bcd60e51b815260040161044890616879565b30612c5e610eb9565b6001600160a01b031614612c9c5760008036604051612c7e929190616869565b604051809103902090505b80612c95610164612e6a565b03612c8957505b6111af81613fbb565b60006064612cb2836119b1565b6101f854604051632394e7a360e21b8152600481018690526001600160a01b0390911690638e539e8c90602401602060405180830381865afa158015612cfc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d209190616a76565b612d2a9190616b2a565b610f999190616a2c565b600080600080612d438561358d565b935093509350935061177f84848484611356565b60006001600160e01b03198216636e665ced60e01b1480610f995750610f998261431d565b6000610f99612d896143b9565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000612dba878787876143c3565b9150915061143f81614487565b6000805462010000900460ff1615612df257604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615612e235760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b03851660009081526001602052604090205460ff1615612e5d5760405163b1d02c3d60e01b815260040160405180910390fd5b611b3686868686866145d1565b6000612e858254600f81810b600160801b909204900b131590565b15612ea357604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b6064811115612f6c5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610448565b6000612f7661204b565b90508015801590612f88575061025e54155b15612fed57604080518082019091526000815261025e9060208101612fac846146d4565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b61301b613008612ffb611fc0565b65ffffffffffff166138e9565b613011846146d4565b61025e919061473d565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60008061306986868686612a08565b9050600461307682611751565b600781111561308757613087616306565b146130a45760405162461bcd60e51b815260040161044890616955565b61022b546040805163793d064960e11b815290516000926001600160a01b03169163f27a0c929160048083019260209291908290030181865afa1580156130ef573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131139190616a76565b61022b5460405163b1c5f42760e01b81529192506001600160a01b03169063b1c5f4279061314e908a908a908a906000908b90600401616b41565b602060405180830381865afa15801561316b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061318f9190616a76565b600083815261022c60205260408082209290925561022b5491516308f2a0bb60e41b81526001600160a01b0390921691638f2a0bb0916131dc918b918b918b91908b908990600401616b8f565b600060405180830381600087803b1580156131f657600080fd5b505af115801561320a573d6000803e3d6000fd5b505050507f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda289282824261323c9190616be7565b604080519283526020830191909152015b60405180910390a15095945050505050565b30613268610eb9565b6001600160a01b0316146132f95760005b845181101561177f57306001600160a01b031685828151811061329e5761329e6168ea565b60200260200101516001600160a01b0316036132e9576132e98382815181106132c9576132c96168ea565b60200260200101518051906020012061016461475890919063ffffffff16565b6132f281616916565b9050613279565b5050505050565b60005462010000900460ff161561332a57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161561335b5760405163b1d02c3d60e01b815260040160405180910390fd5b60005b84518110156133d4576102c1600086838151811061337e5761337e6168ea565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff166133c257604051630b094f2760e31b815260040160405180910390fd5b806133cc81616916565b91505061335e565b506132f98585858585614794565b306133eb610eb9565b6001600160a01b0316146132f95761016454600f81810b600160801b909204900b13156132f9576000610164556132f9565b60006113278585858561343b60408051602081019091526000815290565b612dc7565b60008061344c83614809565b9050600481600781111561346257613462616306565b1461346d5792915050565b600083815261022c602052604090205480613489575092915050565b61022b54604051632ab0f52960e01b8152600481018390526001600160a01b0390911690632ab0f52990602401602060405180830381865afa1580156134d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f79190616bfa565b15613506575060079392505050565b61022b54604051632c258a9f60e11b8152600481018390526001600160a01b039091169063584b153e90602401602060405180830381865afa158015613550573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135749190616bfa565b15613583575060059392505050565b5060029392505050565b60608060606000806101c660008781526020019081526020016000209050806001018160020161375f83600301805480602002602001604051908101604052809291908181526020016000905b828210156136865783829060005260206000200180546135f9906168b0565b80601f0160208091040260200160405190810160405280929190818152602001828054613625906168b0565b80156136725780601f1061364757610100808354040283529160200191613672565b820191906000526020600020905b81548152906001019060200180831161365557829003601f168201915b5050505050815260200190600101906135da565b50505060048601805460408051602080840282018101909252828152935060009084015b828210156137565783829060005260206000200180546136c9906168b0565b80601f01602080910402602001604051908101604052809291908181526020018280546136f5906168b0565b80156137425780601f1061371757610100808354040283529160200191613742565b820191906000526020600020905b81548152906001019060200180831161372557829003601f168201915b5050505050815260200190600101906136aa565b505050506141eb565b60098401548354604080516020808402820181019092528281529186918301828280156137b557602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613797575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561380757602002820191906000526020600020905b8154815260200190600101908083116137f3575b505050505092509450945094509450509193509193565b60008061382d86868686612a08565b60008181526101c660205260409020549091506001600160a01b031633811480613881575061385a6128e1565b61387f826001613868611fc0565b613872919061692f565b65ffffffffffff16612bfc565b105b6138dd5760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72427261766f3a2070726f706f7365722061626f76652074686044820152661c995cda1bdb1960ca1b6064820152608401610448565b61174687878787614941565b600063ffffffff82111561394e5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610448565b5090565b8154600090818160058111156139af57600061396d8461494f565b6139779085616a03565b60008881526020902090915081015463ffffffff908116908716101561399f578091506139ad565b6139aa816001616be7565b92505b505b60006139bd87878585614a37565b905080156139f8576139e2876139d4600184616a03565b600091825260209091200190565b54600160201b90046001600160e01b0316611746565b6000979650505050505050565b6101945460408051918252602082018390527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a93910160405180910390a161019455565b6102c25460ff16613af1576a084595161401484a0000006120056001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a9f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ac39190616a76565b1015613ae2576040516311b6707f60e01b815260040160405180910390fd5b6102c2805460ff191660011790555b565b6000613b4f33868686516001600160401b03811115613b1457613b14615d3e565b604051908082528060200260200182016040528015613b4757816020015b6060815260200190600190039081613b325790505b50878761412d565b61132785858585614a8d565b600054610100900460ff16613b825760405162461bcd60e51b815260040161044890616c1c565b613ba981613ba46040805180820190915260018152603160f81b602082015290565b614e6c565b6111af81614ebb565b600054610100900460ff16613bd95760405162461bcd60e51b815260040161044890616c1c565b613be4838383614ef3565b505050565b600054610100900460ff16613af15760405162461bcd60e51b815260040161044890616c1c565b600054610100900460ff16613c375760405162461bcd60e51b815260040161044890616c1c565b6111af81614f35565b600054610100900460ff16613c675760405162461bcd60e51b815260040161044890616c1c565b6111af81614f7f565b600054610100900460ff16613c975760405162461bcd60e51b815260040161044890616c1c565b6111af81614fa6565b600054610100900460ff16613cc75760405162461bcd60e51b815260040161044890616c1c565b6111af81614fcd565b600054610100900460ff16613cf75760405162461bcd60e51b815260040161044890616c1c565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b6060609a80546111c2906168b0565b6060609b80546111c2906168b0565b600065ffffffffffff82111561394e5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610448565b6101f854604051630748d63560e31b81526001600160a01b038581166004830152602482018590526000921690633a46b1a890604401602060405180830381865afa158015613dfb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120419190616a76565b8054600090801561219357613e39836139d4600184616a03565b54600160201b90046001600160e01b0316612044565b61022b54604080516001600160a01b03928316815291831660208301527f08f74ea46ef7894f65eabfb5e6e695de773a000b47c529ab559178069b226401910160405180910390a161022b80546001600160a01b0319166001600160a01b0392909216919091179055565b600081604051602001613ecd9190616c67565b6040516020818303038152906040528051906020012083604051602001613ef49190616c67565b6040516020818303038152906040528051906020012014905092915050565b015190565b60008111613f785760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253657474696e67733a20766f74696e6720706572696f6420604482015266746f6f206c6f7760c81b6064820152608401610448565b6101955460408051918252602082018390527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828910160405180910390a161019555565b6101965460408051918252602082018390527fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc05461910160405180910390a161019655565b61028f54604080516001600160401b03928316815291831660208301527f7ca4ac117ed3cdce75c1161d8207c440389b1a15d69d096831664657c07dafc2910160405180910390a161028f805467ffffffffffffffff19166001600160401b0392909216919091179055565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008181526101636020526040812060010154610f99906001600160401b0316600084815261029060205260409020546001600160401b0316614ff4565b60608315614123575081612044565b612044838361500a565b80516020820120600061414b878761414588886141eb565b85612a08565b60008181526101c6602052604090206009810154919250906141e05780546001600160a01b0319166001600160a01b038a16178155875161419590600183019060208b0190615ad9565b5086516141ab90600283019060208a0190615b3a565b5085516141c19060038301906020890190615b75565b5084516141d79060048301906020880190615bc7565b50600981018390555b505050505050505050565b6060600082516001600160401b0381111561420857614208615d3e565b60405190808252806020026020018201604052801561423b57816020015b60608152602001906001900390816142265790505b50905060005b81518110156143155784818151811061425c5761425c6168ea565b6020026020010151516000146142cc5784818151811061427e5761427e6168ea565b60200260200101518051906020012084828151811061429f5761429f6168ea565b60200260200101516040516020016142b8929190616c83565b6040516020818303038152906040526142e7565b8381815181106142de576142de6168ea565b60200260200101515b8282815181106142f9576142f96168ea565b60200260200101819052508061430e90616916565b9050614241565b509392505050565b600063288ace0360e11b6318df743f60e31b63bf26d89760e01b6379dd796f60e01b6001600160e01b0319861682148061436357506001600160e01b0319868116908216145b8061437a57506001600160e01b0319868116908516145b8061439557506001600160e01b03198616630271189760e51b145b80611b3657506301ffc9a760e01b6001600160e01b03198716149695505050505050565b6000610ece615034565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143fa575060009050600361447e565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561444e573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166144775760006001925092505061447e565b9150600090505b94509492505050565b600081600481111561449b5761449b616306565b036144a35750565b60018160048111156144b7576144b7616306565b036145045760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610448565b600281600481111561451857614518616306565b036145655760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610448565b600381600481111561457957614579616306565b036111af5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610448565b6000806145e187878787876150a8565b600088815261029060205260409020549091506001600160401b031615801561460e575061460e876151fe565b15611b3657600061462861028f546001600160401b031690565b614630611fc0565b65ffffffffffff166146429190616cb4565b905061464d886128ed565b816001600160401b0316111561469c576040516001600160401b038216815288907f541f725fb9f7c98a30cc9c0ff32fbb14358cd7159c847a3aa20a2bdc442ba5119060200160405180910390a25b600088815261029060205260409020805467ffffffffffffffff19166001600160401b03929092169190911790559695505050505050565b60006001600160e01b0382111561394e5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610448565b60008061474b85858561523e565b915091505b935093915050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b61022b5460405163e38335e560e01b81526001600160a01b039091169063e38335e59034906147d0908890889088906000908990600401616b41565b6000604051808303818588803b1580156147e957600080fd5b505af11580156147fd573d6000803e3d6000fd5b50505050505050505050565b600081815261016360205260408120600281015460ff161561482e5750600792915050565b6002810154610100900460ff16156148495750600292915050565b600083815261016360205260408120546001600160401b0316908190036148b25760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610448565b60006148bc611fc0565b65ffffffffffff1690508082106148d857506000949350505050565b60006148e3866128ed565b90508181106148f85750600195945050505050565b614901866151fe565b8015614924575060008681526101c6602052604090206006810154600590910154115b156149355750600495945050505050565b50600395945050505050565b6000611327858585856153dd565b60008160000361496157506000919050565b6000600161496e84615493565b901c6001901b9050600181848161498757614987616a16565b048201901c9050600181848161499f5761499f616a16565b048201901c905060018184816149b7576149b7616a16565b048201901c905060018184816149cf576149cf616a16565b048201901c905060018184816149e7576149e7616a16565b048201901c905060018184816149ff576149ff616a16565b048201901c90506001818481614a1757614a17616a16565b048201901c905061204481828581614a3157614a31616a16565b04615527565b60005b81831015614315576000614a4e8484615536565b60008781526020902090915063ffffffff86169082015463ffffffff161115614a7957809250614a87565b614a84816001616be7565b93505b50614a3a565b600033614a9a8184615551565b614ae65760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73657220726573747269637465640000006044820152606401610448565b6000614af0611fc0565b65ffffffffffff169050614b026128e1565b614b1183610e14600185616a03565b1015614b795760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610448565b6000614b8e8888888880519060200120612a08565b90508651885114614bb15760405162461bcd60e51b815260040161044890616cd4565b8551885114614bd25760405162461bcd60e51b815260040161044890616cd4565b6000885111614c235760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610448565b600081815261016360205260409020546001600160401b031615614c935760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610448565b6000614c9f6101945490565b614ca99084616be7565b90506000614cb76101955490565b614cc19083616be7565b90506040518060e00160405280614cd784615642565b6001600160401b031681526001600160a01b038716602082015260006040820152606001614d0483615642565b6001600160401b03908116825260006020808401829052604080850183905260609485018390528883526101638252918290208551815492870151878501519186166001600160e01b031990941693909317600160401b6001600160a01b039094168402176001600160e01b0316600160e01b60e09290921c91909102178155938501516080860151908416921c0217600183015560a08301516002909201805460c09094015161ffff1990941692151561ff00191692909217610100931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e91811115614e0957614e09615d3e565b604051908082528060200260200182016040528015614e3c57816020015b6060815260200190600190039081614e275790505b508d88888f604051614e5699989796959493929190616d15565b60405180910390a1509098975050505050505050565b600054610100900460ff16614e935760405162461bcd60e51b815260040161044890616c1c565b609a614e9f8382616df3565b50609b614eac8282616df3565b50506000609881905560995550565b600054610100900460ff16614ee25760405162461bcd60e51b815260040161044890616c1c565b610162614eef8282616df3565b5050565b600054610100900460ff16614f1a5760405162461bcd60e51b815260040161044890616c1c565b614f2383613a05565b614f2c82613f18565b613be481613fbb565b600054610100900460ff16614f5c5760405162461bcd60e51b815260040161044890616c1c565b6101f880546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166120f75760405162461bcd60e51b815260040161044890616c1c565b600054610100900460ff166111a65760405162461bcd60e51b815260040161044890616c1c565b600054610100900460ff16612ac15760405162461bcd60e51b815260040161044890616c1c565b60008183116150035781612044565b5090919050565b81511561501a5781518083602001fd5b8060405162461bcd60e51b81526004016104489190615ef7565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61505f6156aa565b615067615703565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60008581526101636020526040812060016150c288611751565b60078111156150d3576150d3616306565b1461512c5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610448565b80546000906151469088906001600160401b031686613da8565b90506151558888888488615734565b83516000036151aa57866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48988848960405161519d9493929190616eb2565b60405180910390a2611746565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb871289888489896040516151eb959493929190616eda565b60405180910390a2979650505050505050565b60008181526101c6602052604081206005810154615235610e8085600090815261016360205260409020546001600160401b031690565b11159392505050565b82546000908190801561538457600061525c876139d4600185616a03565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090871610156152dd5760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610448565b805163ffffffff80881691160361532557846152fe886139d4600186616a03565b80546001600160e01b0392909216600160201b0263ffffffff909216919091179055615374565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b6020015192508391506147509050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b029190931617920191909155905081614750565b6000806153ec868686866158d2565b600081815261022c6020526040902054909150156113275761022b54600082815261022c60205260409081902054905163c4d252f560e01b81526001600160a01b039092169163c4d252f5916154489160040190815260200190565b600060405180830381600087803b15801561546257600080fd5b505af1158015615476573d6000803e3d6000fd5b505050600082815261022c60205260408120555095945050505050565b600080608083901c156154a857608092831c92015b604083901c156154ba57604092831c92015b602083901c156154cc57602092831c92015b601083901c156154de57601092831c92015b600883901c156154f057600892831c92015b600483901c1561550257600492831c92015b600283901c1561551457600292831c92015b600183901c15610f995760010192915050565b60008183106150035781612044565b60006155456002848418616a2c565b61204490848416616be7565b80516000906034811015615569576001915050610f99565b82810160131901516001600160a01b031981166b046e0e4dee0dee6cae47a60f60a31b1461559c57600192505050610f99565b6000806155aa602885616a03565b90505b83811015615621576000806155e18884815181106155cd576155cd6168ea565b01602001516001600160f81b0319166159df565b91509150816155f95760019650505050505050610f99565b8060ff166004856001600160a01b0316901b17935050508061561a90616916565b90506155ad565b50856001600160a01b0316816001600160a01b031614935050505092915050565b60006001600160401b0382111561394e5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610448565b6000806156b5613d23565b8051909150156156cc578051602090910120919050565b60985480156156db5792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b60008061570e613d32565b805190915015615725578051602090910120919050565b60995480156156db5792915050565b60008581526101c6602090815260408083206001600160a01b038816845260088101909252909120805460ff16156157c45760405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20766f746560448201526c08185b1c9958591e4818d85cdd609a1b6064820152608401610448565b805460ff86166101000261ffff199091161760011781556157e484615a71565b81546001600160601b039190911662010000026dffffffffffffffffffffffff00001990911617815560ff851661583457838260060160008282546158299190616be7565b909155506129ff9050565b60001960ff86160161585457838260050160008282546158299190616be7565b60011960ff86160161587457838260070160008282546158299190616be7565b60405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20696e766160448201526c6c696420766f7465207479706560981b6064820152608401610448565b6000806158e186868686612a08565b905060006158ee82611751565b9050600281600781111561590457615904616306565b141580156159245750600681600781111561592157615921616306565b14155b80156159425750600781600781111561593f5761593f616306565b14155b61598e5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610448565b6000828152610163602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c9061324d9084815260200190565b60008060f883901c602f811180156159fa5750603a8160ff16105b15615a0f57600194602f199091019350915050565b8060ff166040108015615a25575060478160ff16105b15615a3a576001946036199091019350915050565b8060ff166060108015615a50575060678160ff16105b15615a65576001946056199091019350915050565b50600093849350915050565b60006001600160601b0382111561394e5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610448565b828054828255906000526020600020908101928215615b2e579160200282015b82811115615b2e57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615af9565b5061394e929150615c19565b828054828255906000526020600020908101928215615b2e579160200282015b82811115615b2e578251825591602001919060010190615b5a565b828054828255906000526020600020908101928215615bbb579160200282015b82811115615bbb5782518290615bab9082616df3565b5091602001919060010190615b95565b5061394e929150615c2e565b828054828255906000526020600020908101928215615c0d579160200282015b82811115615c0d5782518290615bfd9082616df3565b5091602001919060010190615be7565b5061394e929150615c4b565b5b8082111561394e5760008155600101615c1a565b8082111561394e576000615c428282615c68565b50600101615c2e565b8082111561394e576000615c5f8282615c68565b50600101615c4b565b508054615c74906168b0565b6000825580601f10615c84575050565b601f0160209004906000526020600020908101906111af9190615c19565b600060208284031215615cb457600080fd5b5035919050565b600060208284031215615ccd57600080fd5b81356001600160e01b03198116811461204457600080fd5b803560ff8116811461193957600080fd5b60008083601f840112615d0857600080fd5b5081356001600160401b03811115615d1f57600080fd5b602083019150836020828501011115615d3757600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715615d7c57615d7c615d3e565b604052919050565b60006001600160401b03821115615d9d57615d9d615d3e565b50601f01601f191660200190565b600082601f830112615dbc57600080fd5b8135615dcf615dca82615d84565b615d54565b818152846020838601011115615de457600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060e0898b031215615e1d57600080fd5b88359750615e2d60208a01615ce5565b965060408901356001600160401b0380821115615e4957600080fd5b615e558c838d01615cf6565b909850965060608b0135915080821115615e6e57600080fd5b50615e7b8b828c01615dab565b945050615e8a60808a01615ce5565b925060a0890135915060c089013590509295985092959890939650565b60005b83811015615ec2578181015183820152602001615eaa565b50506000910152565b60008151808452615ee3816020860160208601615ea7565b601f01601f19169290920160200192915050565b6020815260006120446020830184615ecb565b6001600160a01b03811681146111af57600080fd5b60008060008060808587031215615f3557600080fd5b8435615f4081615f0a565b93506020850135615f5081615f0a565b92506040850135915060608501356001600160401b03811115615f7257600080fd5b615f7e87828801615dab565b91505092959194509250565b60006001600160401b03821115615fa357615fa3615d3e565b5060051b60200190565b600082601f830112615fbe57600080fd5b81356020615fce615dca83615f8a565b82815260059290921b84018101918181019086841115615fed57600080fd5b8286015b8481101561601157803561600481615f0a565b8352918301918301615ff1565b509695505050505050565b600082601f83011261602d57600080fd5b8135602061603d615dca83615f8a565b82815260059290921b8401810191818101908684111561605c57600080fd5b8286015b848110156160115780358352918301918301616060565b600082601f83011261608857600080fd5b81356020616098615dca83615f8a565b82815260059290921b840181019181810190868411156160b757600080fd5b8286015b848110156160115780356001600160401b038111156160da5760008081fd5b6160e88986838b0101615dab565b8452509183019183016160bb565b6000806000806080858703121561610c57600080fd5b84356001600160401b038082111561612357600080fd5b61612f88838901615fad565b9550602087013591508082111561614557600080fd5b6161518883890161601c565b9450604087013591508082111561616757600080fd5b5061617487828801616077565b949793965093946060013593505050565b60006020828403121561619757600080fd5b813561204481615f0a565b600081518084526020808501945080840160005b838110156161db5781516001600160a01b0316875295820195908201906001016161b6565b509495945050505050565b600081518084526020808501945080840160005b838110156161db578151875295820195908201906001016161fa565b600081518084526020808501808196508360051b8101915082860160005b8581101561625e57828403895261624c848351615ecb565b98850198935090840190600101616234565b5091979650505050505050565b60808152600061627e60808301876161a2565b828103602084015261629081876161e6565b905082810360408401526162a48186616216565b905082810360608401526117468185616216565b600080600080600060a086880312156162d057600080fd5b853594506162e060208701615ce5565b93506162ee60408701615ce5565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b602081016008831061633e57634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561635757600080fd5b82359150602083013561636981615f0a565b809150509250929050565b6000806040838503121561638757600080fd5b8235915061639760208401615ce5565b90509250929050565b6000806000806000608086880312156163b857600080fd5b853594506163c860208701615ce5565b935060408601356001600160401b03808211156163e457600080fd5b6163f089838a01615cf6565b9095509350606088013591508082111561640957600080fd5b5061641688828901615dab565b9150509295509295909350565b6000806000806060858703121561643957600080fd5b8435935061644960208601615ce5565b925060408501356001600160401b0381111561646457600080fd5b61647087828801615cf6565b95989497509550505050565b6000806000806080858703121561649257600080fd5b84356001600160401b03808211156164a957600080fd5b6164b588838901615fad565b955060208701359150808211156164cb57600080fd5b6164d78883890161601c565b945060408701359150808211156164ed57600080fd5b6164f988838901616077565b9350606087013591508082111561650f57600080fd5b50615f7e87828801615dab565b60ff60f81b8816815260e06020820152600061653b60e0830189615ecb565b828103604084015261654d8189615ecb565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152905061108981856161e6565b60008060006060848603121561659357600080fd5b833561659e81615f0a565b92506020840135915060408401356001600160401b038111156165c057600080fd5b6165cc86828701615dab565b9150509250925092565b600080600080604085870312156165ec57600080fd5b84356001600160401b038082111561660357600080fd5b61660f88838901615cf6565b9096509450602087013591508082111561662857600080fd5b5061647087828801615cf6565b600080600080600060a0868803121561664d57600080fd5b853561665881615f0a565b9450602086013561666881615f0a565b935060408601356001600160401b038082111561668457600080fd5b61669089838a0161601c565b945060608801359150808211156166a657600080fd5b6166b289838a0161601c565b9350608088013591508082111561640957600080fd5b600080600080606085870312156166de57600080fd5b84356166e981615f0a565b93506020850135925060408501356001600160401b0381111561646457600080fd5b60006020828403121561671d57600080fd5b81356001600160401b038116811461204457600080fd5b600080600080600060a0868803121561674c57600080fd5b85356001600160401b038082111561676357600080fd5b61676f89838a01615fad565b9650602088013591508082111561678557600080fd5b61679189838a0161601c565b955060408801359150808211156167a757600080fd5b6167b389838a01616077565b945060608801359150808211156167c957600080fd5b6166b289838a01616077565b600080604083850312156167e857600080fd5b82356167f381615f0a565b946020939093013593505050565b600080600080600060a0868803121561681957600080fd5b853561682481615f0a565b9450602086013561683481615f0a565b9350604086013592506060860135915060808601356001600160401b0381111561685d57600080fd5b61641688828901615dab565b8183823760009101908152919050565b60208082526018908201527f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000604082015260600190565b600181811c908216806168c457607f821691505b6020821081036168e457634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161692857616928616900565b5060010190565b65ffffffffffff82811682821603908082111561694e5761694e616900565b5092915050565b60208082526021908201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756040820152601b60fa1b606082015260800190565b6000602082840312156169a857600080fd5b81516001600160401b038111156169be57600080fd5b8201601f810184136169cf57600080fd5b80516169dd615dca82615d84565b8181528560208385010111156169f257600080fd5b611327826020830160208601615ea7565b81810381811115610f9957610f99616900565b634e487b7160e01b600052601260045260246000fd5b600082616a4957634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215616a6057600080fd5b815165ffffffffffff8116811461204457600080fd5b600060208284031215616a8857600080fd5b5051919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000616acc604083018688616a8f565b8281036020840152611746818587616a8f565b608081526000616af260808301876161a2565b8281036020840152616b0481876161e6565b90508281036040840152616b188186616216565b91505082606083015295945050505050565b8082028115828204841417610f9957610f99616900565b60a081526000616b5460a08301886161a2565b8281036020840152616b6681886161e6565b90508281036040840152616b7a8187616216565b60608401959095525050608001529392505050565b60c081526000616ba260c08301896161a2565b8281036020840152616bb481896161e6565b90508281036040840152616bc88188616216565b60608401969096525050608081019290925260a0909101529392505050565b80820180821115610f9957610f99616900565b600060208284031215616c0c57600080fd5b8151801515811461204457600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251616c79818460208701615ea7565b9190910192915050565b6001600160e01b0319831681528151600090616ca6816004850160208701615ea7565b919091016004019392505050565b6001600160401b0381811683821601908082111561694e5761694e616900565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b8981526001600160a01b038916602082015261012060408201819052600090616d408382018b6161a2565b90508281036060840152616d54818a6161e6565b90508281036080840152616d688189616216565b905082810360a0840152616d7c8188616216565b90508560c08401528460e0840152828103610100840152616d9d8185615ecb565b9c9b505050505050505050505050565b601f821115613be457600081815260208120601f850160051c81016020861015616dd45750805b601f850160051c820191505b8181101561177f57828155600101616de0565b81516001600160401b03811115616e0c57616e0c615d3e565b616e2081616e1a84546168b0565b84616dad565b602080601f831160018114616e555760008415616e3d5750858301515b600019600386901b1c1916600185901b17855561177f565b600085815260208120601f198616915b82811015616e8457888601518255948401946001909101908401616e65565b5085821015616ea25787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b84815260ff84166020820152826040820152608060608201526000611b366080830184615ecb565b85815260ff8516602082015283604082015260a060608201526000616f0260a0830185615ecb565b8281036080840152611c4f8185615ecb56fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/pasteur/chapel/StakeHubContract b/core/systemcontracts/pasteur/chapel/StakeHubContract new file mode 100644 index 0000000000..67153989c0 --- /dev/null +++ b/core/systemcontracts/pasteur/chapel/StakeHubContract @@ -0,0 +1 @@ +6080604052600436106200043b5760003560e01c806386d545061162000233578063ca47908f116200012f578063dd42a1dd11620000b9578063f1f74d841162000084578063f1f74d841462000d75578063f80a34021462000d8d578063fb50b31f1462000db2578063fc0c5ff11462000dd7578063ff69ab611462000def57600080fd5b8063dd42a1dd1462000ce2578063e8f67c3b1462000d09578063e992aaf51462000d21578063efdbf0e11462000d3957600080fd5b8063d7c2dfc811620000fa578063d7c2dfc81462000c68578063d8ca511f1462000c8d578063daacdb661462000ca5578063dbda7fb31462000cbd57600080fd5b8063ca47908f1462000bd1578063cbb04d9d1462000be9578063d115a2061462000c2a578063d6ca429d1462000c4357600080fd5b8063b187bd2611620001bd578063bfff04751162000188578063bfff04751462000b58578063c166f58a1462000b7d578063c38fbec81462000b94578063c473318f1462000bb9578063c8509d81146200095157600080fd5b8063b187bd261462000ac5578063baa7199e1462000ae5578063bdceadf31462000b0a578063bff02e201462000b2257600080fd5b8063a1832e6411620001fe578063a1832e641462000a22578063a43569b31462000a47578063aad3ec961462000a7b578063ac4317511462000aa057600080fd5b806386d54506146200098e5780638a4d3fa814620009c85780638cd22b2214620009e6578063982ef0a71462000a0b57600080fd5b80634838d165116200034357806364028fbd11620002cd57806375cc7d89116200029857806375cc7d8914620008fc57806376e7d6d614620009215780638129fc1c1462000939578063831d65d114620009515780638456cb59146200097657600080fd5b806364028fbd1462000837578063663706d3146200084e5780636ec01b27146200087f5780636f8e2fa414620008d757600080fd5b80634e6fd6c4116200030e5780634e6fd6c4146200079e5780635949187114620007b65780635e7cc1c914620007db57806363a036b5146200080057600080fd5b80634838d16514620006ea57806349f41a42146200072f5780634a49ac4c14620007545780634d99dd16146200077957600080fd5b80631fab701511620003c5578063384099881162000390578063384099881462000663578063417c73a7146200067b578063449ecfe614620006a057806345211bfd14620006c557600080fd5b80631fab701514620005aa5780632b727c8614620005cf5780632e8e8c7114620005f4578063367dad49146200062e57600080fd5b80630e9fbf5111620004065780630e9fbf5114620004f35780631182b875146200051857806317b4f353146200054c5780631fa8882b146200059157600080fd5b8063046f7da2146200045b578063059ddd2214620004735780630661806e14620004b5578063092193ab14620004dc57600080fd5b36620004565760345460ff166001146200045457600080fd5b005b600080fd5b3480156200046857600080fd5b506200045462000e07565b3480156200048057600080fd5b506200049862000492366004620097cc565b62000e99565b6040516001600160a01b0390911681526020015b60405180910390f35b348015620004c257600080fd5b50620004cd60365481565b604051908152602001620004ac565b62000454620004ed366004620097cc565b620012c1565b3480156200050057600080fd5b5062000454620005123660046200982e565b62001912565b3480156200052557600080fd5b506200053d6200053736600462009873565b62001c9e565b604051620004ac919062009926565b3480156200055957600080fd5b50620004986200056b366004620099f8565b80516020818301810180516045825292820191909301209152546001600160a01b031681565b3480156200059e57600080fd5b50620004cd6201518081565b348015620005b757600080fd5b5062000454620005c936600462009a94565b62001d36565b348015620005dc57600080fd5b5062000498620005ee366004620097cc565b6200208d565b3480156200060157600080fd5b506200049862000613366004620097cc565b604d602052600090815260409020546001600160a01b031681565b3480156200063b57600080fd5b50620006536200064d36600462009a94565b620020e2565b604051620004ac92919062009b13565b3480156200067057600080fd5b50620004cd60375481565b3480156200068857600080fd5b50620004546200069a366004620097cc565b620026b1565b348015620006ad57600080fd5b5062000454620006bf366004620097cc565b62002733565b348015620006d257600080fd5b5062000454620006e4366004620097cc565b62002918565b348015620006f757600080fd5b506200071e62000709366004620097cc565b60016020526000908152604090205460ff1681565b6040519015158152602001620004ac565b3480156200073c57600080fd5b50620004546200074e366004620097cc565b62002af1565b3480156200076157600080fd5b506200045462000773366004620097cc565b62002d0d565b3480156200078657600080fd5b50620004546200079836600462009bb2565b62002d89565b348015620007ab57600080fd5b506200049861dead81565b348015620007c357600080fd5b5062000454620007d536600462009bf0565b620033b9565b348015620007e857600080fd5b5062000454620007fa36600462009c5a565b620041b2565b3480156200080d57600080fd5b50620008256200081f36600462009c81565b620043dc565b604051620004ac949392919062009ca4565b620004546200084836600462009d60565b62004a81565b3480156200085b57600080fd5b50620004cd6200086d366004620097cc565b60446020526000908152604090205481565b3480156200088c57600080fd5b50620008a46200089e366004620097cc565b620050d0565b6040805182516001600160401b0390811682526020808501518216908301529282015190921690820152606001620004ac565b348015620008e457600080fd5b506200053d620008f6366004620097cc565b62005175565b3480156200090957600080fd5b50620004546200091b366004620097cc565b620055a1565b3480156200092e57600080fd5b50620004cd603d5481565b3480156200094657600080fd5b506200045462005773565b3480156200095e57600080fd5b50620004546200097036600462009873565b6200593e565b3480156200098357600080fd5b50620004546200599c565b3480156200099b57600080fd5b5062000498620009ad366004620097cc565b6043602052600090815260409020546001600160a01b031681565b348015620009d557600080fd5b50620004cd670de0b6b3a764000081565b348015620009f357600080fd5b50620004cd62000a0536600462009bb2565b62005a34565b6200045462000a1c36600462009e36565b62005aed565b34801562000a2f57600080fd5b506200045462000a4136600462009a94565b6200619b565b34801562000a5457600080fd5b5062000a6c62000a66366004620097cc565b620064a1565b604051620004ac919062009e6e565b34801562000a8857600080fd5b506200045462000a9a36600462009bb2565b6200678e565b34801562000aad57600080fd5b506200045462000abf36600462009eeb565b620067fb565b34801562000ad257600080fd5b5060005462010000900460ff166200071e565b34801562000af257600080fd5b506200045462000b0436600462009f5d565b620077ad565b34801562000b1757600080fd5b50620004cd603c5481565b34801562000b2f57600080fd5b5062000b4762000b4136600462009c81565b6200797a565b604051620004ac9392919062009fb6565b34801562000b6557600080fd5b50620004cd62000b77366004620097cc565b62007b56565b34801562000b8a57600080fd5b50620004cd600581565b34801562000ba157600080fd5b506200045462000bb3366004620097cc565b62007ba4565b34801562000bc657600080fd5b50620004cd60385481565b34801562000bde57600080fd5b50620004cd604e5481565b34801562000bf657600080fd5b5062000c0e62000c08366004620097cc565b62007ec6565b60408051938452911515602084015290820152606001620004ac565b34801562000c3757600080fd5b50620004cd620186a081565b34801562000c5057600080fd5b506200045462000c623660046200a013565b62008309565b34801562000c7557600080fd5b506200045462000c873660046200a0fc565b6200852f565b34801562000c9a57600080fd5b50620004cd603b5481565b34801562000cb257600080fd5b50620004cd60495481565b34801562000cca57600080fd5b506200049862000cdc366004620097cc565b62008625565b34801562000cef57600080fd5b50600054630100000090046001600160a01b031662000498565b34801562000d1657600080fd5b50620004cd60355481565b34801562000d2e57600080fd5b50620004cd603a5481565b34801562000d4657600080fd5b50620004cd62000d58366004620099f8565b805160208183018101805160468252928201919093012091525481565b34801562000d8257600080fd5b50620004cd603e5481565b34801562000d9a57600080fd5b50620004cd62000dac36600462009bb2565b62008a4f565b34801562000dbf57600080fd5b506200045462000dd136600462009eeb565b62008ac0565b34801562000de457600080fd5b50620004cd60395481565b34801562000dfc57600080fd5b50620004cd604a5481565b600054630100000090046001600160a01b0316331462000e3a576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1662000e6457604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162000f04906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462000f32906200a162565b801562000f835780601f1062000f575761010080835404028352916020019162000f83565b820191906000526020600020905b81548152906001019060200180831162000f6557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462000fae906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462000fdc906200a162565b80156200102d5780601f1062001001576101008083540402835291602001916200102d565b820191906000526020600020905b8154815290600101906020018083116200100f57829003601f168201915b5050505050815260200160018201805462001048906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462001076906200a162565b8015620010c75780601f106200109b57610100808354040283529160200191620010c7565b820191906000526020600020905b815481529060010190602001808311620010a957829003601f168201915b50505050508152602001600282018054620010e2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462001110906200a162565b8015620011615780601f10620011355761010080835404028352916020019162001161565b820191906000526020600020905b8154815290600101906020018083116200114357829003601f168201915b505050505081526020016003820180546200117c906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620011aa906200a162565b8015620011fb5780601f10620011cf57610100808354040283529160200191620011fb565b820191906000526020600020905b815481529060010190602001808311620011dd57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200129a575050509190925250509051949350505050565b3361100014620012ed57604051630f22c43960e41b815261100060048201526024015b60405180910390fd5b6001600160a01b0380821660009081526043602090815260408083205484168084526041835281842082516101808101845281548716815260018201548716948101949094526002810154909516918301919091526003840154606083015260048401805491949160808401919062001366906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462001394906200a162565b8015620013e55780601f10620013b957610100808354040283529160200191620013e5565b820191906000526020600020905b815481529060010190602001808311620013c757829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462001410906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200143e906200a162565b80156200148f5780601f1062001463576101008083540402835291602001916200148f565b820191906000526020600020905b8154815290600101906020018083116200147157829003601f168201915b50505050508152602001600182018054620014aa906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620014d8906200a162565b8015620015295780601f10620014fd5761010080835404028352916020019162001529565b820191906000526020600020905b8154815290600101906020018083116200150b57829003601f168201915b5050505050815260200160028201805462001544906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462001572906200a162565b8015620015c35780601f106200159757610100808354040283529160200191620015c3565b820191906000526020600020905b815481529060010190602001808311620015a557829003601f168201915b50505050508152602001600382018054620015de906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200160c906200a162565b80156200165d5780601f1062001631576101008083540402835291602001916200165d565b820191906000526020600020905b8154815290600101906020018083116200163f57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620016fc575050509190925250505060408101519091506001600160a01b031615806200173957508060e001515b15620017f657604051611002903490600081818185875af1925050503d806000811462001783576040519150601f19603f3d011682016040523d82523d6000602084013e62001788565b606091505b505050816001600160a01b03167ffc8bff675087dd2da069cc3fb517b9ed001e19750c0865241a5542dba1ba170d604051620017e99060208082526011908201527024a72b20a624a22fab20a624a220aa27a960791b604082015260600190565b60405180910390a2505050565b60408181015160c0830151519151632f303ebb60e11b81526001600160401b0390921660048301526001600160a01b031690635e607d769034906024016000604051808303818588803b1580156200184d57600080fd5b505af115801562001862573d6000803e3d6000fd5b5050505050816001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea634604051620018a391815260200190565b60405180910390a26040808201519051633041949b60e01b815261200591633041949b91620018d8919086906004016200a198565b600060405180830381600087803b158015620018f357600080fd5b505af115801562001908573d6000803e3d6000fd5b5050505050505b50565b33611001146200193a57604051630f22c43960e41b81526110016004820152602401620012e4565b60005462010000900460ff16156200196557604051631785c68160e01b815260040160405180910390fd5b6000604583836040516200197b9291906200a1b2565b908152604051908190036020019020546001600160a01b03169050620019a3603f8262008cf9565b620019c15760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038116600090815260416020526040812090620019e962015180426200a1d8565b604a546000828152604b60205260409020549192501162001a1d5760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062001a3e9084906200a1fb565b909155505060405160469062001a5890879087906200a1b2565b90815260200160405180910390205460001415801562001aa9575042620151806046878760405162001a8c9291906200a1b2565b90815260200160405180910390205462001aa791906200a1fb565b105b1562001ac857604051631898eb6b60e01b815260040160405180910390fd5b60008062001ad885600262008d1c565b915091508162001afb57604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562001b4e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001b7491906200a211565b905062001b82858362008da4565b84546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562001bc957600080fd5b505af115801562001bde573d6000803e3d6000fd5b50505050856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600260405162001c22939291906200a22b565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162001c60916001600160a01b0316908a906004016200a198565b600060405180830381600087803b15801562001c7b57600080fd5b505af115801562001c90573d6000803e3d6000fd5b505050505050505050505050565b6060336120001462001cc857604051630f22c43960e41b81526120006004820152602401620012e4565b60005462010000900460ff161562001cf357604051631785c68160e01b815260040160405180910390fd5b6034805460ff1916600117905560405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e4565b60005462010000900460ff161562001d6157604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562001d935760405163b1d02c3d60e01b815260040160405180910390fd5b62001d9d62008e98565b62001daa603f8262008cf9565b62001dc85760405163056e881160e01b815260040160405180910390fd5b62001dd262008eff565b600082900362001df557604051636490ffd360e01b815260040160405180910390fd5b600062001e0162008e98565b6001600160a01b0381166000908152604f602052604090208054604e54929350909162001e2f86836200a1fb565b111562001e4f5760405163091af98560e21b815260040160405180910390fd5b60005b8581101562001f3557600087878381811062001e725762001e726200a266565b905060200201350362001e9857604051636490ffd360e01b815260040160405180910390fd5b600062001ea78260016200a1fb565b90505b8681101562001f1f5787878281811062001ec85762001ec86200a266565b9050602002013588888481811062001ee45762001ee46200a266565b905060200201350362001f0a57604051632205e3c760e11b815260040160405180910390fd5b8062001f16816200a27c565b91505062001eaa565b508062001f2c816200a27c565b91505062001e52565b5060005b8581101562001fd45760005b8281101562001fbe5783818154811062001f635762001f636200a266565b906000526020600020015488888481811062001f835762001f836200a266565b905060200201350362001fa957604051632205e3c760e11b815260040160405180910390fd5b8062001fb5816200a27c565b91505062001f45565b508062001fcb816200a27c565b91505062001f39565b5060005b8581101562001908578287878381811062001ff75762001ff76200a266565b835460018101855560009485526020948590209190940292909201359190920155506001600160a01b0384167f7c4ff4c9a343a2daef608f3b5a91016e994a15fc0ef8611109e4f45823249f298888848181106200205957620020596200a266565b905060200201356040516200207091815260200190565b60405180910390a28062002084816200a27c565b91505062001fd8565b6000816200209d603f8262008cf9565b620020bb5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160205260409020600d01541691505b50919050565b60608082806001600160401b038111156200210157620021016200993b565b6040519080825280602002602001820160405280156200212b578160200160208202803683370190505b509250806001600160401b038111156200214957620021496200993b565b6040519080825280602002602001820160405280156200217e57816020015b6060815260200190600190039081620021685790505b50915060005b81811015620026a7576000868683818110620021a457620021a46200a266565b9050602002016020810190620021bb9190620097cc565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549495509193909291608084019162002228906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002256906200a162565b8015620022a75780601f106200227b57610100808354040283529160200191620022a7565b820191906000526020600020905b8154815290600101906020018083116200228957829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620022d2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002300906200a162565b8015620023515780601f10620023255761010080835404028352916020019162002351565b820191906000526020600020905b8154815290600101906020018083116200233357829003601f168201915b505050505081526020016001820180546200236c906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200239a906200a162565b8015620023eb5780601f10620023bf57610100808354040283529160200191620023eb565b820191906000526020600020905b815481529060010190602001808311620023cd57829003601f168201915b5050505050815260200160028201805462002406906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002434906200a162565b8015620024855780601f10620024595761010080835404028352916020019162002485565b820191906000526020600020905b8154815290600101906020018083116200246757829003601f168201915b50505050508152602001600382018054620024a0906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620024ce906200a162565b80156200251f5780601f10620024f3576101008083540402835291602001916200251f565b820191906000526020600020905b8154815290600101906020018083116200250157829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620025be5750505050508152505090508060000151868481518110620025f757620025f76200a266565b6001600160a01b039283166020918202929092018101919091529083166000908152604f8252604090819020805482518185028101850190935280835291929091908301828280156200266a57602002820191906000526020600020905b81548152602001906001019080831162002655575b50505050508584815181106200268457620026846200a266565b6020026020010181905250505080806200269e906200a27c565b91505062002184565b50505b9250929050565b600054630100000090046001600160a01b03163314620026e4576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60005462010000900460ff16156200275e57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620027905760405163b1d02c3d60e01b815260040160405180910390fd5b806200279e603f8262008cf9565b620027bc5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166000908152604160205260409020600a81015460ff16620027fa57604051634b6b857d60e01b815260040160405180910390fd5b6036546002820154604051630913db4760e01b81526001600160a01b03868116600483015290911690630913db4790602401602060405180830381865afa1580156200284a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200287091906200a211565b101562002890576040516317b204bf60e11b815260040160405180910390fd5b4281600b01541115620028b65760405163170cb76760e21b815260040160405180910390fd5b600a8101805460ff191690556049805460019190600090620028da9084906200a298565b90915550506040516001600160a01b038416907f9390b453426557da5ebdc31f19a37753ca04addf656d32f35232211bb2af3f1990600090a2505050565b60005462010000900460ff16156200294357604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620029755760405163b1d02c3d60e01b815260040160405180910390fd5b6200297f62008f12565b6200298c603f8262008cf9565b620029aa5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038216620029d257604051636520611b60e11b815260040160405180910390fd5b6001600160a01b03828116600090815260436020526040902054161562002a0c57604051631e6f587560e11b815260040160405180910390fd5b600062002a1862008f12565b6001600160a01b0381166000908152604160205260409020600c81015491925090429062002a4b9062015180906200a1fb565b111562002a6b57604051631f92cdbd60e11b815260040160405180910390fd5b80546001600160a01b039081166000908152604460209081526040808320429081905585548986166001600160a01b031991821681178855600c88019290925581855260439093528184208054958816959093168517909255519092917f6e4e747ca35203f16401c69805c7dd52fff67ef60b0ebc5c7fe16890530f223591a350505050565b3362002aff603f8262008cf9565b62002b1d5760405163056e881160e01b815260040160405180910390fd5b60005462010000900460ff161562002b4857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002b7a5760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b038281166000908152604d6020526040902054161562002bb45760405163bebdc75760e01b815260040160405180910390fd5b62002bc1603f8362008cf9565b1562002be05760405163bebdc75760e01b815260040160405180910390fd5b336000818152604160205260409020600d01546001600160a01b03908116908416810362002c215760405163bebdc75760e01b815260040160405180910390fd5b6001600160a01b0381161562002c58576001600160a01b0381166000908152604d6020526040902080546001600160a01b03191690555b6001600160a01b038281166000908152604160205260409020600d0180546001600160a01b03191691861691821790551562002cbd576001600160a01b038481166000908152604d6020526040902080546001600160a01b0319169184169190911790555b836001600160a01b0316816001600160a01b0316836001600160a01b03167fcbb728765de145e99c00e8ae32a325231e850359b7b8a6da3b84d672ab3f1d0a60405160405180910390a450505050565b600054630100000090046001600160a01b0316331462002d40576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60005462010000900460ff161562002db457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002de65760405163b1d02c3d60e01b815260040160405180910390fd5b8162002df4603f8262008cf9565b62002e125760405163056e881160e01b815260040160405180910390fd5b8160000362002e3457604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162002e9c906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002eca906200a162565b801562002f1b5780601f1062002eef5761010080835404028352916020019162002f1b565b820191906000526020600020905b81548152906001019060200180831162002efd57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002f46906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002f74906200a162565b801562002fc55780601f1062002f995761010080835404028352916020019162002fc5565b820191906000526020600020905b81548152906001019060200180831162002fa757829003601f168201915b5050505050815260200160018201805462002fe0906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200300e906200a162565b80156200305f5780601f1062003033576101008083540402835291602001916200305f565b820191906000526020600020905b8154815290600101906020018083116200304157829003601f168201915b505050505081526020016002820180546200307a906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620030a8906200a162565b8015620030f95780601f10620030cd57610100808354040283529160200191620030f9565b820191906000526020600020905b815481529060010190602001808311620030db57829003601f168201915b5050505050815260200160038201805462003114906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003142906200a162565b8015620031935780601f10620031675761010080835404028352916020019162003193565b820191906000526020600020905b8154815290600101906020018083116200317557829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162003232575050509190925250505060408082015190516326ccee8b60e11b81526001600160a01b0385811660048301526024820188905292935060009290911690634d99dd16906044016020604051808303816000875af1158015620032ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620032d291906200a211565b9050826001600160a01b0316866001600160a01b03167f3aace7340547de7b9156593a7652dc07ee900cea3fd8f82cb6c9d38b40829802878460405162003323929190918252602082015260400190565b60405180910390a3856001600160a01b0316836001600160a01b0316036200335057620033508662008f53565b6040808301519051633041949b60e01b815261200591633041949b916200337d919087906004016200a198565b600060405180830381600087803b1580156200339857600080fd5b505af1158015620033ad573d6000803e3d6000fd5b50505050505050505050565b60005462010000900460ff1615620033e457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620034165760405163b1d02c3d60e01b815260040160405180910390fd5b8362003424603f8262008cf9565b620034425760405163056e881160e01b815260040160405180910390fd5b8362003450603f8262008cf9565b6200346e5760405163056e881160e01b815260040160405180910390fd5b6034805460ff1916600117905560008490036200349e57604051639811e0c760e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031603620034d15760405163f0e3e62960e01b815260040160405180910390fd5b6001600160a01b038087166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162003539906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003567906200a162565b8015620035b85780601f106200358c57610100808354040283529160200191620035b8565b820191906000526020600020905b8154815290600101906020018083116200359a57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620035e3906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003611906200a162565b8015620036625780601f10620036365761010080835404028352916020019162003662565b820191906000526020600020905b8154815290600101906020018083116200364457829003601f168201915b505050505081526020016001820180546200367d906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620036ab906200a162565b8015620036fc5780601f10620036d057610100808354040283529160200191620036fc565b820191906000526020600020905b815481529060010190602001808311620036de57829003601f168201915b5050505050815260200160028201805462003717906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003745906200a162565b8015620037965780601f106200376a5761010080835404028352916020019162003796565b820191906000526020600020905b8154815290600101906020018083116200377857829003601f168201915b50505050508152602001600382018054620037b1906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620037df906200a162565b8015620038305780601f10620038045761010080835404028352916020019162003830565b820191906000526020600020905b8154815290600101906020018083116200381257829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620038cf57505050919092525050506001600160a01b038089166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054949550919390929160808401916200395a906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003988906200a162565b8015620039d95780601f10620039ad57610100808354040283529160200191620039d9565b820191906000526020600020905b815481529060010190602001808311620039bb57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462003a04906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003a32906200a162565b801562003a835780601f1062003a575761010080835404028352916020019162003a83565b820191906000526020600020905b81548152906001019060200180831162003a6557829003601f168201915b5050505050815260200160018201805462003a9e906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003acc906200a162565b801562003b1d5780601f1062003af15761010080835404028352916020019162003b1d565b820191906000526020600020905b81548152906001019060200180831162003aff57829003601f168201915b5050505050815260200160028201805462003b38906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003b66906200a162565b801562003bb75780601f1062003b8b5761010080835404028352916020019162003bb7565b820191906000526020600020905b81548152906001019060200180831162003b9957829003601f168201915b5050505050815260200160038201805462003bd2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003c00906200a162565b801562003c515780601f1062003c255761010080835404028352916020019162003c51565b820191906000526020600020905b81548152906001019060200180831162003c3357829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162003cf05750505050508152505090508060e00151801562003d335750876001600160a01b0316836001600160a01b031614155b1562003d5257604051636468920360e01b815260040160405180910390fd5b60408083015190516352e82ce560e11b81526001600160a01b038581166004830152602482018a9052600092169063a5d059ca906044016020604051808303816000875af115801562003da9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003dcf91906200a211565b905060375481101562003df55760405163dc6f0bdd60e01b815260040160405180910390fd5b896001600160a01b0316846001600160a01b031614801562003e8a57506036546040808501519051630913db4760e01b81526001600160a01b038d8116600483015290911690630913db4790602401602060405180830381865afa15801562003e62573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e8891906200a211565b105b1562003ea9576040516317b204bf60e11b815260040160405180910390fd5b6000620186a0603a548362003ebf91906200a2ae565b62003ecb91906200a1d8565b9050600083604001516001600160a01b03168260405160006040518083038185875af1925050503d806000811462003f20576040519150601f19603f3d011682016040523d82523d6000602084013e62003f25565b606091505b505090508062003f48576040516312171d8360e31b815260040160405180910390fd5b62003f5482846200a298565b60408086015190516317066a5760e21b81526001600160a01b03898116600483015292955060009290911690635c19a95c90869060240160206040518083038185885af115801562003faa573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062003fd191906200a211565b9050866001600160a01b03168c6001600160a01b03168e6001600160a01b03167ffdac6e81913996d95abcc289e90f2d8bd235487ce6fe6f821e7d21002a1915b48e858960405162004036939291909283526020830191909152604082015260600190565b60405180910390a46040805160028082526060820183526000926020830190803683370190505090508660400151816000815181106200407a576200407a6200a266565b60200260200101906001600160a01b031690816001600160a01b031681525050856040015181600181518110620040b557620040b56200a266565b6001600160a01b0390921660209283029190910190910152604051634484077560e01b815261200590634484077590620040f69084908c906004016200a2c8565b600060405180830381600087803b1580156200411157600080fd5b505af115801562004126573d6000803e3d6000fd5b505050508a1562004198576120056001600160a01b031663e5ed5b1e898f6040518363ffffffff1660e01b8152600401620041639291906200a198565b600060405180830381600087803b1580156200417e57600080fd5b505af115801562004193573d6000803e3d6000fd5b505050505b50506034805460ff19169055505050505050505050505050565b60005462010000900460ff1615620041dd57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200420f5760405163b1d02c3d60e01b815260040160405180910390fd5b6200421962008f12565b62004226603f8262008cf9565b620042445760405163056e881160e01b815260040160405180910390fd5b60006200425062008f12565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620042839062015180906200a1fb565b1115620042a357604051631f92cdbd60e11b815260040160405180910390fd5b60098101546001600160401b03600160401b90910481169085161115620042dd5760405163dc81db8560e01b815260040160405180910390fd5b60098101546000906001600160401b0390811690861610156200431b576009820154620043159086906001600160401b03166200a2f4565b62004335565b600982015462004335906001600160401b0316866200a2f4565b60098301546001600160401b039182169250600160801b900416811115620043705760405163dc81db8560e01b815260040160405180910390fd5b60098201805467ffffffffffffffff19166001600160401b03871690811790915542600c8401556040519081526001600160a01b038416907f78cdd96edf59e09cfd4d26ef6ef6c92d166effe6a40970c54821206d541932cb9060200160405180910390a25050505050565b60608060606000620043ef603f62009071565b90508086101562004a785784156200440857846200440a565b805b94506000856200441b88846200a298565b1162004433576200442d87836200a298565b62004435565b855b9050806001600160401b038111156200445257620044526200993b565b6040519080825280602002602001820160405280156200447c578160200160208202803683370190505b509450806001600160401b038111156200449a576200449a6200993b565b604051908082528060200260200182016040528015620044c4578160200160208202803683370190505b509350806001600160401b03811115620044e257620044e26200993b565b6040519080825280602002602001820160405280156200451757816020015b6060815260200190600190039081620045015790505b50925060005b8181101562004a755760006200454162004538838b6200a1fb565b603f906200907c565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620045ae906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620045dc906200a162565b80156200462d5780601f1062004601576101008083540402835291602001916200462d565b820191906000526020600020905b8154815290600101906020018083116200460f57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462004658906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462004686906200a162565b8015620046d75780601f10620046ab57610100808354040283529160200191620046d7565b820191906000526020600020905b815481529060010190602001808311620046b957829003601f168201915b50505050508152602001600182018054620046f2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462004720906200a162565b8015620047715780601f10620047455761010080835404028352916020019162004771565b820191906000526020600020905b8154815290600101906020018083116200475357829003601f168201915b505050505081526020016002820180546200478c906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620047ba906200a162565b80156200480b5780601f10620047df576101008083540402835291602001916200480b565b820191906000526020600020905b815481529060010190602001808311620047ed57829003601f168201915b5050505050815260200160038201805462004826906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462004854906200a162565b8015620048a55780601f106200487957610100808354040283529160200191620048a5565b820191906000526020600020905b8154815290600101906020018083116200488757829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200494457505050505081525050905080600001518884815181106200497d576200497d6200a266565b60200260200101906001600160a01b031690816001600160a01b0316815250508060e0015162004a165780604001516001600160a01b03166315d1f8986040518163ffffffff1660e01b8152600401602060405180830381865afa158015620049ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062004a1091906200a211565b62004a19565b60005b87848151811062004a2e5762004a2e6200a266565b602002602001018181525050806080015186848151811062004a545762004a546200a266565b602002602001018190525050508062004a6d906200a27c565b90506200451d565b50505b92959194509250565b60005462010000900460ff161562004aac57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562004ade5760405163b1d02c3d60e01b815260040160405180910390fd5b3362004aec603f8262008cf9565b1562004b0b57604051635f28f62b60e01b815260040160405180910390fd5b6001600160a01b038181166000908152604d6020526040902054161562004b4557604051631a0a9b9f60e21b815260040160405180910390fd5b6001600160a01b03888116600090815260436020526040902054161562004b7f57604051631e6f587560e11b815260040160405180910390fd5b60006001600160a01b03166045888860405162004b9e9291906200a1b2565b908152604051908190036020019020546001600160a01b03161462004bd6576040516311fdb94760e01b815260040160405180910390fd5b600062004be483806200a31e565b60405160200162004bf79291906200a1b2565b60408051601f1981840301815291815281516020928301206000818152604290935291205490915060ff161562004c415760405163c0bf414360e01b815260040160405180910390fd5b600062004c57670de0b6b3a7640000346200a298565b905060365481101562004c7d576040516317b204bf60e11b815260040160405180910390fd5b6001600160a01b038a1662004ca557604051636520611b60e11b815260040160405180910390fd5b61138862004cba604087016020880162009c5a565b6001600160401b0316118062004d00575062004cdd604086016020870162009c5a565b6001600160401b031662004cf5602087018762009c5a565b6001600160401b0316115b8062004d3f575062004d19604086016020870162009c5a565b6001600160401b031662004d34606087016040880162009c5a565b6001600160401b0316115b1562004d5e5760405163dc81db8560e01b815260040160405180910390fd5b62004da962004d6e85806200a31e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200908a92505050565b62004dc757604051635dba5ad760e01b815260040160405180910390fd5b62004dd6838a8a8a8a6200922c565b62004df457604051631647e3cb60e11b815260040160405180910390fd5b600062004e428462004e0787806200a31e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200935c92505050565b905062004e51603f856200945d565b506000838152604260209081526040808320805460ff191660019081179091556001600160a01b0380891680865260419094529190932080548f83166001600160a01b03199182161782559381018054851690931790925560028201805491851691909316179091554260038201556004810162004ed18b8d836200a3c6565b50856005820162004ee382826200a48e565b508790506009820162004ef782826200a5c7565b505042600c8201556001600160a01b038c81166000908152604360205260409081902080546001600160a01b0319169288169290921790915551859060459062004f45908e908e906200a1b2565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316856001600160a01b03168d6001600160a01b03167faecd9fb95e79c75a3a1de93362c6be5fe6ab65770d8614be583884161cd8228d8e8e60405162004fc89291906200a697565b60405180910390a460408051848152602081018590526001600160a01b0387169182917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a360408051670de0b6b3a7640000808252602082015261dead916001600160a01b038816917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a3604051633041949b60e01b815261200590633041949b906200508e90859089906004016200a198565b600060405180830381600087803b158015620050a957600080fd5b505af1158015620050be573d6000803e3d6000fd5b50505050505050505050505050505050565b604080516060810182526000808252602082018190529181019190915281620050fb603f8262008cf9565b620051195760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b031660009081526041602090815260409182902082516060810184526009909101546001600160401b038082168352600160401b8204811693830193909352600160801b90049091169181019190915290565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082810191909152600484018054919491608084019190620051e2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005210906200a162565b8015620052615780601f10620052355761010080835404028352916020019162005261565b820191906000526020600020905b8154815290600101906020018083116200524357829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200528c906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620052ba906200a162565b80156200530b5780601f10620052df576101008083540402835291602001916200530b565b820191906000526020600020905b815481529060010190602001808311620052ed57829003601f168201915b5050505050815260200160018201805462005326906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005354906200a162565b8015620053a55780601f106200537957610100808354040283529160200191620053a5565b820191906000526020600020905b8154815290600101906020018083116200538757829003601f168201915b50505050508152602001600282018054620053c0906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620053ee906200a162565b80156200543f5780601f1062005413576101008083540402835291602001916200543f565b820191906000526020600020905b8154815290600101906020018083116200542157829003601f168201915b505050505081526020016003820180546200545a906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005488906200a162565b8015620054d95780601f10620054ad57610100808354040283529160200191620054d9565b820191906000526020600020905b815481529060010190602001808311620054bb57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620055785750505091909252505050608001519392505050565b3361100114620055c957604051630f22c43960e41b81526110016004820152602401620012e4565b6001600160a01b0380821660009081526043602052604090205416620055f1603f8262008cf9565b6200560f5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038181166000908152604160205260408082206002810154603b54925163045bc4d160e41b81526004810193909352909316906345bc4d10906024016020604051808303816000875af115801562005672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200569891906200a211565b90506000603d5442620056ac91906200a1fb565b9050620056ba838262008da4565b836001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb282846001604051620056fa939291906200a22b565b60405180910390a26002830154604051633041949b60e01b815261200591633041949b9162005738916001600160a01b03169088906004016200a198565b600060405180830381600087803b1580156200575357600080fd5b505af115801562005768573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff1615808015620057945750600054600160ff909116105b80620057b05750303b158015620057b0575060005460ff166001145b620058155760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620012e4565b6000805460ff19166001179055801562005839576000805461ff0019166101001790555b3341146200585a5760405163022d8c9560e31b815260040160405180910390fd5b3a156200587a576040516383f1b1d360e01b815260040160405180910390fd5b611388603555686c6b935b8bbd400000603655670de0b6b3a7640000603755600960385562093a806039556002603a819055678ac7230489e80000603b55680ad78ebc5ac6200000603c556202a300603d5562069780603e55604a55620058f57330151da466ec8ab345bef3d6983023e050fb067362009474565b80156200190f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b33612000146200596657604051630f22c43960e41b81526120006004820152602401620012e4565b60405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e4565b600054630100000090046001600160a01b03163314620059cf576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1615620059fa57604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b600062005a43603f8462008cf9565b62005a615760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383811660009081526041602052604090819020600201549051636bbf224960e01b815260048101859052911690636bbf2249906024015b602060405180830381865afa15801562005abe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062005ae491906200a211565b90505b92915050565b60005462010000900460ff161562005b1857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562005b4a5760405163b1d02c3d60e01b815260040160405180910390fd5b8162005b58603f8262008cf9565b62005b765760405163056e881160e01b815260040160405180910390fd5b603754349081101562005b9c5760405163dc6f0bdd60e01b815260040160405180910390fd5b6001600160a01b038085166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162005c04906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005c32906200a162565b801562005c835780601f1062005c575761010080835404028352916020019162005c83565b820191906000526020600020905b81548152906001019060200180831162005c6557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462005cae906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005cdc906200a162565b801562005d2d5780601f1062005d015761010080835404028352916020019162005d2d565b820191906000526020600020905b81548152906001019060200180831162005d0f57829003601f168201915b5050505050815260200160018201805462005d48906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005d76906200a162565b801562005dc75780601f1062005d9b5761010080835404028352916020019162005dc7565b820191906000526020600020905b81548152906001019060200180831162005da957829003601f168201915b5050505050815260200160028201805462005de2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005e10906200a162565b801562005e615780601f1062005e355761010080835404028352916020019162005e61565b820191906000526020600020905b81548152906001019060200180831162005e4357829003601f168201915b5050505050815260200160038201805462005e7c906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005eaa906200a162565b801562005efb5780601f1062005ecf5761010080835404028352916020019162005efb565b820191906000526020600020905b81548152906001019060200180831162005edd57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162005f9a5750505050508152505090508060e00151801562005fdd5750856001600160a01b0316826001600160a01b031614155b1562005ffc57604051636468920360e01b815260040160405180910390fd5b60408082015190516317066a5760e21b81526001600160a01b0384811660048301526000921690635c19a95c90869060240160206040518083038185885af11580156200604d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200607491906200a211565b9050826001600160a01b0316876001600160a01b03167f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e048387604051620060c5929190918252602082015260400190565b60405180910390a36040808301519051633041949b60e01b815261200591633041949b91620060fa919087906004016200a198565b600060405180830381600087803b1580156200611557600080fd5b505af11580156200612a573d6000803e3d6000fd5b50505050851562001908576040516372f6ad8f60e11b81526120059063e5ed5b1e906200615e9086908b906004016200a198565b600060405180830381600087803b1580156200617957600080fd5b505af11580156200618e573d6000803e3d6000fd5b5050505050505050505050565b60005462010000900460ff1615620061c657604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620061f85760405163b1d02c3d60e01b815260040160405180910390fd5b6200620262008e98565b6200620f603f8262008cf9565b6200622d5760405163056e881160e01b815260040160405180910390fd5b60006200623962008e98565b6001600160a01b0381166000908152604f6020526040812080549293509190859003620063105760005b81811015620062e457836001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a848381548110620062ac57620062ac6200a266565b9060005260206000200154604051620062c791815260200190565b60405180910390a280620062db816200a27c565b91505062006263565b506001600160a01b0383166000908152604f60205260408120620063089162009766565b505050505050565b60005b858110156200646e5760008787838181106200633357620063336200a266565b90506020020135905060005b838110156200645657818582815481106200635e576200635e6200a266565b9060005260206000200154036200644157846200637d6001866200a298565b815481106200639057620063906200a266565b9060005260206000200154858281548110620063b057620063b06200a266565b906000526020600020018190555084805480620063d157620063d16200a6ad565b600190038181906000526020600020016000905590558380620063f4906200a6c3565b945050856001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a836040516200643391815260200190565b60405180910390a262006456565b806200644d816200a27c565b9150506200633f565b5050808062006465906200a27c565b91505062006313565b50815460000362006308576001600160a01b0383166000908152604f60205260408120620063089162009766565b505050565b620064cd6040518060800160405280606081526020016060815260200160608152602001606081525090565b81620064db603f8262008cf9565b620064f95760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383166000908152604160205260409081902081516080810190925260050180548290829062006530906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200655e906200a162565b8015620065af5780601f106200658357610100808354040283529160200191620065af565b820191906000526020600020905b8154815290600101906020018083116200659157829003601f168201915b50505050508152602001600182018054620065ca906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620065f8906200a162565b8015620066495780601f106200661d5761010080835404028352916020019162006649565b820191906000526020600020905b8154815290600101906020018083116200662b57829003601f168201915b5050505050815260200160028201805462006664906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462006692906200a162565b8015620066e35780601f10620066b757610100808354040283529160200191620066e3565b820191906000526020600020905b815481529060010190602001808311620066c557829003601f168201915b50505050508152602001600382018054620066fe906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200672c906200a162565b80156200677d5780601f1062006751576101008083540402835291602001916200677d565b820191906000526020600020905b8154815290600101906020018083116200675f57829003601f168201915b505050505081525050915050919050565b60005462010000900460ff1615620067b957604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620067eb5760405163b1d02c3d60e01b815260040160405180910390fd5b620067f782826200950d565b5050565b33611007146200682357604051630f22c43960e41b81526110076004820152602401620012e4565b620068906040518060400160405280601081526020016f1d1c985b9cd9995c91d85cd31a5b5a5d60821b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b156200694b5760208114620068c25783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006905918585808385018382808284376000920191909152509293925050620096769050565b90506108fc81108062006919575061271081115b15620069425784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60355562007768565b620069bc6040518060400160405280601481526020017336b4b729b2b6332232b632b3b0ba34b7b721272160611b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006a865760208114620069ee5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006a31918585808385018382808284376000920191909152509293925050620096769050565b9050683635c9adc5dea0000081108062006a54575069152d02c7e14af680000081115b1562006a7d5784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60365562007768565b62006af9604051806040016040528060168152602001756d696e44656c65676174696f6e424e424368616e676560501b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006bc0576020811462006b2b5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006b6e918585808385018382808284376000920191909152509293925050620096769050565b905067016345785d8a000081108062006b8e5750678ac7230489e8000081115b1562006bb75784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60375562007768565b62006c31604051806040016040528060148152602001736d6178456c656374656456616c696461746f727360601b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006ce9576020811462006c635783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006ca6918585808385018382808284376000920191909152509293925050620096769050565b905080158062006cb757506101f481115b1562006ce05784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60385562007768565b62006d526040518060400160405280600c81526020016b1d5b989bdb9914195c9a5bd960a21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006e0f576020811462006d845783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006dc7918585808385018382808284376000920191909152509293925050620096769050565b90506203f48081108062006ddd575062278d0081115b1562006e065784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60395562007768565b62006e7d60405180604001604052806011815260200170726564656c65676174654665655261746560781b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006f2a576020811462006eaf5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006ef2918585808385018382808284376000920191909152509293925050620096769050565b9050606481111562006f215784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603a5562007768565b62006f9a60405180604001604052806013815260200172191bdddb9d1a5b5954db185cda105b5bdd5b9d606a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b156200705c576020811462006fcc5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f84018190048102820181019092528281526000916200700f918585808385018382808284376000920191909152509293925050620096769050565b9050670de0b6b3a76400008110806200702a5750603c548110155b15620070535784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603b5562007768565b620070ca6040518060400160405280601181526020017019995b1bdb9e54db185cda105b5bdd5b9d607a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b156200718c5760208114620070fc5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f84018190048102820181019092528281526000916200713f918585808385018382808284376000920191909152509293925050620096769050565b9050678ac7230489e800008110806200715a5750603b548111155b15620071835784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603c5562007768565b620071f96040518060400160405280601081526020016f646f776e74696d654a61696c54696d6560801b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b15620072b657602081146200722b5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f84018190048102820181019092528281526000916200726e918585808385018382808284376000920191909152509293925050620096769050565b905062015180811080620072845750603e548110155b15620072ad5784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603d5562007768565b620073216040518060400160405280600e81526020016d66656c6f6e794a61696c54696d6560901b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b15620073de5760208114620073535783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162007396918585808385018382808284376000920191909152509293925050620096769050565b90506203f480811080620073ac5750603d548111155b15620073d55784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603e5562007768565b620074586040518060400160405280601c81526020017f6d617846656c6f6e794265747765656e42726561746865426c6f636b0000000081525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b156200750457602081146200748a5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f8401819004810282018101909252828152600091620074cd918585808385018382808284376000920191909152509293925050620096769050565b905080600003620074fb5784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604a5562007768565b620075726040518060400160405280601181526020017039ba30b5b2a43ab1283937ba32b1ba37b960791b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b15620076325760148114620075a45783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b6000620075ec601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096769050565b90506001600160a01b038116620076205784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b6200762b816200967b565b5062007768565b620076996040518060400160405280600a8152602001696d61784e6f646549447360b01b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b15620077455760208114620076cb5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f84018190048102820181019092528281526000916200770e918585808385018382808284376000920191909152509293925050620096769050565b9050806000036200773c5784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604e5562007768565b838383836040516325ee20d560e21b8152600401620012e494939291906200a6dd565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516200779f94939291906200a6dd565b60405180910390a150505050565b60005462010000900460ff1615620077d857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200780a5760405163b1d02c3d60e01b815260040160405180910390fd5b816000816001600160401b038111156200782857620078286200993b565b60405190808252806020026020018201604052801562007852578160200160208202803683370190505b5090506000805b8381101562007950576200789b8787838181106200787b576200787b6200a266565b9050602002016020810190620078929190620097cc565b603f9062008cf9565b620078b95760405163056e881160e01b815260040160405180910390fd5b60416000888884818110620078d257620078d26200a266565b9050602002016020810190620078e99190620097cc565b6001600160a01b03908116825260208201929092526040016000206002015484519116925082908490839081106200792557620079256200a266565b6001600160a01b039092166020928302919091019091015262007948816200a27c565b905062007859565b50604051634484077560e01b8152612005906344840775906200337d90859088906004016200a2c8565b60608060006200798b603f62009071565b90508085101562007b4f578315620079a45783620079a6565b805b9350600084620079b787846200a298565b11620079cf57620079c986836200a298565b620079d1565b845b9050806001600160401b03811115620079ee57620079ee6200993b565b60405190808252806020026020018201604052801562007a18578160200160208202803683370190505b509350806001600160401b0381111562007a365762007a366200993b565b60405190808252806020026020018201604052801562007a60578160200160208202803683370190505b50925060005b8181101562007b4c5762007a7f6200453882896200a1fb565b85828151811062007a945762007a946200a266565b60200260200101906001600160a01b031690816001600160a01b0316815250506041600086838151811062007acd5762007acd6200a266565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060020160009054906101000a90046001600160a01b031684828151811062007b215762007b216200a266565b6001600160a01b039092166020928302919091019091015262007b44816200a27c565b905062007a66565b50505b9250925092565b60008162007b66603f8262008cf9565b62007b845760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b03166000908152604160205260409020600c015490565b336110011462007bcc57604051630f22c43960e41b81526110016004820152602401620012e4565b60005462010000900460ff161562007bf757604051631785c68160e01b815260040160405180910390fd5b6001600160a01b038082166000908152604360205260409020541662007c1f603f8262008cf9565b62007c3d5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062007c6562015180426200a1d8565b604a546000828152604b60205260409020549192501162007c995760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062007cba9084906200a1fb565b90915550506001600160a01b0384166000908152604460205260409020541580159062007d0f57506001600160a01b038416600090815260446020526040902054429062007d0d9062015180906200a1fb565b105b1562007d2e576040516330abb81d60e21b815260040160405180910390fd5b60008062007d3e85600062008d1c565b915091508162007d6157604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562007db4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062007dda91906200a211565b905062007de8858362008da4565b84546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562007e2f57600080fd5b505af115801562007e44573d6000803e3d6000fd5b50505050856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600060405162007e88939291906200a22b565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b916200615e916001600160a01b0316908a906004016200a198565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384938493849390929160808401919062007f37906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462007f65906200a162565b801562007fb65780601f1062007f8a5761010080835404028352916020019162007fb6565b820191906000526020600020905b81548152906001019060200180831162007f9857829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462007fe1906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200800f906200a162565b8015620080605780601f10620080345761010080835404028352916020019162008060565b820191906000526020600020905b8154815290600101906020018083116200804257829003601f168201915b505050505081526020016001820180546200807b906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620080a9906200a162565b8015620080fa5780601f10620080ce57610100808354040283529160200191620080fa565b820191906000526020600020905b815481529060010190602001808311620080dc57829003601f168201915b5050505050815260200160028201805462008115906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008143906200a162565b8015620081945780601f10620081685761010080835404028352916020019162008194565b820191906000526020600020905b8154815290600101906020018083116200817657829003601f168201915b50505050508152602001600382018054620081af906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620081dd906200a162565b80156200822e5780601f1062008202576101008083540402835291602001916200822e565b820191906000526020600020905b8154815290600101906020018083116200821057829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620082cd5750505091909252505050606081015160e0820151610100909201519097919650945092505050565b60005462010000900460ff16156200833457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620083665760405163b1d02c3d60e01b815260040160405180910390fd5b6200837062008f12565b6200837d603f8262008cf9565b6200839b5760405163056e881160e01b815260040160405180910390fd5b6000620083a762008f12565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620083da9062015180906200a1fb565b1115620083fa57604051631f92cdbd60e11b815260040160405180910390fd5b6005810180546200840b906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008439906200a162565b80156200848a5780601f106200845e576101008083540402835291602001916200848a565b820191906000526020600020905b8154815290600101906020018083116200846c57829003601f168201915b5050508287525085916005840191508190620084a790826200a713565b5060208201516001820190620084be90826200a713565b5060408201516002820190620084d590826200a713565b5060608201516003820190620084ec90826200a713565b505042600c830155506040516001600160a01b038316907f85d6366b336ade7f106987ec7a8eac1e8799e508aeab045a39d2f63e0dc969d990600090a250505050565b60005462010000900460ff16156200855a57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200858c5760405163b1d02c3d60e01b815260040160405180910390fd5b828114620085ad576040516341abc80160e01b815260040160405180910390fd5b60005b838110156200861e576200860b858583818110620085d257620085d26200a266565b9050602002016020810190620085e99190620097cc565b848484818110620085fe57620085fe6200a266565b905060200201356200950d565b62008616816200a27c565b9050620085b0565b5050505050565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162008690906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620086be906200a162565b80156200870f5780601f10620086e3576101008083540402835291602001916200870f565b820191906000526020600020905b815481529060010190602001808311620086f157829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200873a906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008768906200a162565b8015620087b95780601f106200878d57610100808354040283529160200191620087b9565b820191906000526020600020905b8154815290600101906020018083116200879b57829003601f168201915b50505050508152602001600182018054620087d4906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008802906200a162565b8015620088535780601f10620088275761010080835404028352916020019162008853565b820191906000526020600020905b8154815290600101906020018083116200883557829003601f168201915b505050505081526020016002820180546200886e906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200889c906200a162565b8015620088ed5780601f10620088c157610100808354040283529160200191620088ed565b820191906000526020600020905b815481529060010190602001808311620088cf57829003601f168201915b5050505050815260200160038201805462008908906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008936906200a162565b8015620089875780601f106200895b5761010080835404028352916020019162008987565b820191906000526020600020905b8154815290600101906020018083116200896957829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162008a265750505091909252505050604001519392505050565b600062008a5e603f8462008cf9565b62008a7c5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038381166000908152604160205260409081902060020154905163aa1966cd60e01b81526004810185905291169063aa1966cd9060240162005aa0565b60005462010000900460ff161562008aeb57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562008b1d5760405163b1d02c3d60e01b815260040160405180910390fd5b62008b2762008f12565b62008b34603f8262008cf9565b62008b525760405163056e881160e01b815260040160405180910390fd5b600062008b5e62008f12565b905062008b6f81878787876200922c565b62008b8d57604051631647e3cb60e11b815260040160405180910390fd5b60006001600160a01b03166045878760405162008bac9291906200a1b2565b908152604051908190036020019020546001600160a01b03161462008be4576040516311fdb94760e01b815260040160405180910390fd5b6001600160a01b0381166000908152604160205260409020600c810154429062008c139062015180906200a1fb565b111562008c3357604051631f92cdbd60e11b815260040160405180910390fd5b4260468260040160405162008c4991906200a7db565b908152604051908190036020019020556004810162008c6a8789836200a3c6565b5042600c820155604051829060459062008c88908a908a906200a1b2565b90815260405190819003602001812080546001600160a01b039384166001600160a01b0319909116179055908316907f783156582145bd0ff7924fae6953ba054cf1233eb60739a200ddb10de068ff0d9062008ce8908a908a906200a697565b60405180910390a250505050505050565b6001600160a01b0381166000908152600183016020526040812054151562005ae4565b6000806000848460405160200162008d369291906200a859565b60408051601f1981840301815291815281516020928301206000818152604c9093529120549091504281111562008d7657600080935093505050620026aa565b603e5462008d8590426200a1fb565b6000928352604c60205260409092208290555060019590945092505050565b6000600162008db4603f62009071565b62008dc091906200a298565b604954108015915062008e0c5760018301546040516001600160a01b03909116907f2afdc18061ac21cff7d9f11527ab9c8dec6fabd4edf6f894ed634bebd6a20d4590600090a2505050565b82600b015482111562008e2157600b83018290555b600a83015460ff166200649c57600a8301805460ff191660019081179091556049805460009062008e549084906200a1fb565b909155505060018301546040516001600160a01b03909116907f4905ac32602da3fb8b4b7b00c285e5fc4c6c2308cc908b4a1e4e9625a29c90a390600090a2505050565b336000908152604360205260408120546001600160a01b03161580159062008ecd575033600090815260446020526040902054155b1562008ef05750336000908152604360205260409020546001600160a01b031690565b62008efa62008f12565b905090565b604e5460000362008f10576005604e555b565b336000908152604d60205260408120546001600160a01b03161562008f4e5750336000908152604d60205260409020546001600160a01b031690565b503390565b6001600160a01b0381166000908152604160205260409020600a81015460ff161562008f7d575050565b6036546002820154604051630913db4760e01b81526001600160a01b03858116600483015290911690630913db4790602401602060405180830381865afa15801562008fcd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008ff391906200a211565b1015620067f7576200901581603d54426200900f91906200a1fb565b62008da4565b80546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b1580156200905c57600080fd5b505af115801562006308573d6000803e3d6000fd5b600062005ae7825490565b600062005ae48383620096e7565b600080829050600381511080620090a2575060098151115b15620090b15750600092915050565b604181600081518110620090c957620090c96200a266565b016020015160f81c1080620090fb5750605a81600081518110620090f157620090f16200a266565b016020015160f81c115b156200910a5750600092915050565b60015b8151811015620092225760308282815181106200912e576200912e6200a266565b016020015160f81c10806200915f575060398282815181106200915557620091556200a266565b016020015160f81c115b8015620091af575060418282815181106200917e576200917e6200a266565b016020015160f81c1080620091af5750605a828281518110620091a557620091a56200a266565b016020015160f81c115b8015620091ff57506061828281518110620091ce57620091ce6200a266565b016020015160f81c1080620091ff5750607a828281518110620091f557620091f56200a266565b016020015160f81c115b156200920f575060009392505050565b6200921a816200a27c565b90506200910d565b5060019392505050565b600060308414158062009240575060608214155b156200924f5750600062009353565b6000868686466040516020016200926a94939291906200a8a3565b60408051808303601f1901815282825280516020918201208184528383019092529092506000919060208201818036833701905050905081602082015260008186868a8a604051602001620092c49594939291906200a8d0565b60408051808303601f190181526001808452838301909252925060009190602082018180368337019050509050815160016020830182602086016066600019fa6200930e57600080fd5b506000816000815181106200932757620093276200a266565b016020015160f81c905060018114620093495760009550505050505062009353565b6001955050505050505b95945050505050565b60008061200361dead604051620093739062009786565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f080158015620093b6573d6000803e3d6000fd5b509050806001600160a01b031663f399e22e3486866040518463ffffffff1660e01b8152600401620093ea9291906200a908565b6000604051808303818588803b1580156200940457600080fd5b505af115801562009419573d6000803e3d6000fd5b50506040516001600160a01b038086169450881692507fd481492e4e93bb36b4c12a5af93f03be3bf04b454dfbc35dd2663fa26f44d5b09150600090a39392505050565b600062005ae4836001600160a01b03841662009714565b600054610100900460ff16620094e15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620012e4565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b816200951b603f8262008cf9565b620095395760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03838116600090815260416020526040808220600201549051635569f64b60e11b8152336004820152602481018690529192169063aad3ec96906044016020604051808303816000875af11580156200959d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620095c391906200a211565b9050336001600160a01b0316846001600160a01b03167ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd3992683836040516200960b91815260200190565b60405180910390a350505050565b6000816040516020016200962e91906200a92e565b60405160208183030381529060405280519060200120836040516020016200965791906200a92e565b6040516020818303038152906040528051906020012014905092915050565b015190565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008260000182815481106200970157620097016200a266565b9060005260206000200154905092915050565b60008181526001830160205260408120546200975d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562005ae7565b50600062005ae7565b50805460008255906000526020600020908101906200190f919062009794565b610e96806200a94d83390190565b5b80821115620097ab576000815560010162009795565b5090565b80356001600160a01b0381168114620097c757600080fd5b919050565b600060208284031215620097df57600080fd5b62005ae482620097af565b60008083601f840112620097fd57600080fd5b5081356001600160401b038111156200981557600080fd5b602083019150836020828501011115620026aa57600080fd5b600080602083850312156200984257600080fd5b82356001600160401b038111156200985957600080fd5b6200986785828601620097ea565b90969095509350505050565b6000806000604084860312156200988957600080fd5b833560ff811681146200989b57600080fd5b925060208401356001600160401b03811115620098b757600080fd5b620098c586828701620097ea565b9497909650939450505050565b60005b83811015620098ef578181015183820152602001620098d5565b50506000910152565b6000815180845262009912816020860160208601620098d2565b601f01601f19169290920160200192915050565b60208152600062005ae46020830184620098f8565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200997657620099766200993b565b60405290565b60006001600160401b03808411156200999957620099996200993b565b604051601f8501601f19908116603f01168101908282118183101715620099c457620099c46200993b565b81604052809350858152868686011115620099de57600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121562009a0b57600080fd5b81356001600160401b0381111562009a2257600080fd5b8201601f8101841362009a3457600080fd5b62009a45848235602084016200997c565b949350505050565b60008083601f84011262009a6057600080fd5b5081356001600160401b0381111562009a7857600080fd5b6020830191508360208260051b8501011115620026aa57600080fd5b6000806020838503121562009aa857600080fd5b82356001600160401b0381111562009abf57600080fd5b620098678582860162009a4d565b600081518084526020808501945080840160005b8381101562009b085781516001600160a01b03168752958201959082019060010162009ae1565b509495945050505050565b60408152600062009b28604083018562009acd565b6020838203818501528185518084528284019150828160051b8501018388016000805b8481101562009ba257878403601f19018652825180518086529088019088860190845b8181101562009b8c5783518352928a0192918a019160010162009b6e565b5050968801969450509186019160010162009b4b565b50919a9950505050505050505050565b6000806040838503121562009bc657600080fd5b62009bd183620097af565b946020939093013593505050565b80358015158114620097c757600080fd5b6000806000806080858703121562009c0757600080fd5b62009c1285620097af565b935062009c2260208601620097af565b92506040850135915062009c396060860162009bdf565b905092959194509250565b6001600160401b03811681146200190f57600080fd5b60006020828403121562009c6d57600080fd5b813562009c7a8162009c44565b9392505050565b6000806040838503121562009c9557600080fd5b50508035926020909101359150565b60808152600062009cb9608083018762009acd565b82810360208481019190915286518083528782019282019060005b8181101562009cf25784518352938301939183019160010162009cd4565b5050848103604086015286518082528282019350600581901b8201830183890160005b8381101562009d4757601f1985840301875262009d34838351620098f8565b9686019692509085019060010162009d15565b5050809550505050505082606083015295945050505050565b600080600080600080600087890360e081121562009d7d57600080fd5b62009d8889620097af565b975060208901356001600160401b038082111562009da557600080fd5b62009db38c838d01620097ea565b909950975060408b013591508082111562009dcd57600080fd5b62009ddb8c838d01620097ea565b90975095508591506060605f198401121562009df657600080fd5b60608b01945060c08b013592508083111562009e1157600080fd5b505088016080818b03121562009e2657600080fd5b8091505092959891949750929550565b6000806040838503121562009e4a57600080fd5b62009e5583620097af565b915062009e656020840162009bdf565b90509250929050565b60208152600082516080602084015262009e8c60a0840182620098f8565b90506020840151601f198085840301604086015262009eac8383620098f8565b9250604086015191508085840301606086015262009ecb8383620098f8565b9250606086015191508085840301608086015250620093538282620098f8565b6000806000806040858703121562009f0257600080fd5b84356001600160401b038082111562009f1a57600080fd5b62009f2888838901620097ea565b9096509450602087013591508082111562009f4257600080fd5b5062009f5187828801620097ea565b95989497509550505050565b60008060006040848603121562009f7357600080fd5b83356001600160401b0381111562009f8a57600080fd5b62009f988682870162009a4d565b909450925062009fad905060208501620097af565b90509250925092565b60608152600062009fcb606083018662009acd565b828103602084015262009fdf818662009acd565b915050826040830152949350505050565b600082601f8301126200a00257600080fd5b62005ae4838335602085016200997c565b6000602082840312156200a02657600080fd5b81356001600160401b03808211156200a03e57600080fd5b90830190608082860312156200a05357600080fd5b6200a05d62009951565b8235828111156200a06d57600080fd5b6200a07b8782860162009ff0565b8252506020830135828111156200a09157600080fd5b6200a09f8782860162009ff0565b6020830152506040830135828111156200a0b857600080fd5b6200a0c68782860162009ff0565b6040830152506060830135828111156200a0df57600080fd5b6200a0ed8782860162009ff0565b60608301525095945050505050565b600080600080604085870312156200a11357600080fd5b84356001600160401b03808211156200a12b57600080fd5b6200a1398883890162009a4d565b909650945060208701359150808211156200a15357600080fd5b5062009f518782880162009a4d565b600181811c908216806200a17757607f821691505b602082108103620020dc57634e487b7160e01b600052602260045260246000fd5b6001600160a01b0392831681529116602082015260400190565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b6000826200a1f657634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562005ae75762005ae76200a1c2565b6000602082840312156200a22457600080fd5b5051919050565b8381526020810183905260608101600383106200a25857634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200a291576200a2916200a1c2565b5060010190565b8181038181111562005ae75762005ae76200a1c2565b808202811582820484141762005ae75762005ae76200a1c2565b6040815260006200a2dd604083018562009acd565b905060018060a01b03831660208301529392505050565b6001600160401b038281168282160390808211156200a317576200a3176200a1c2565b5092915050565b6000808335601e198436030181126200a33657600080fd5b8301803591506001600160401b038211156200a35157600080fd5b602001915036819003821315620026aa57600080fd5b601f8211156200649c57600081815260208120601f850160051c810160208610156200a3905750805b601f850160051c820191505b8181101562006308578281556001016200a39c565b600019600383901b1c191660019190911b1790565b6001600160401b038311156200a3e0576200a3e06200993b565b6200a3f8836200a3f183546200a162565b836200a367565b6000601f8411600181146200a42b57600085156200a4165750838201355b6200a42286826200a3b1565b8455506200861e565b600083815260209020601f19861690835b828110156200a45e57868501358255602094850194600190920191016200a43c565b50868210156200a47c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6200a49a82836200a31e565b6001600160401b038111156200a4b4576200a4b46200993b565b6200a4cc816200a4c585546200a162565b856200a367565b6000601f8211600181146200a4ff57600083156200a4ea5750838201355b6200a4f684826200a3b1565b8655506200a55c565b600085815260209020601f19841690835b828110156200a53257868501358255602094850194600190920191016200a510565b50848210156200a5505760001960f88660031b161c19848701351681555b505060018360011b0185555b505050506200a56f60208301836200a31e565b6200a57f8183600186016200a3c6565b50506200a59060408301836200a31e565b6200a5a08183600286016200a3c6565b50506200a5b160608301836200a31e565b6200a5c18183600386016200a3c6565b50505050565b81356200a5d48162009c44565b6001600160401b03811690508154816001600160401b0319821617835560208401356200a6018162009c44565b6fffffffffffffffff0000000000000000604091821b166fffffffffffffffffffffffffffffffff198316841781178555908501356200a6418162009c44565b6001600160c01b0319929092169092179190911760809190911b67ffffffffffffffff60801b1617905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600062009a456020830184866200a66e565b634e487b7160e01b600052603160045260246000fd5b6000816200a6d5576200a6d56200a1c2565b506000190190565b6040815260006200a6f36040830186886200a66e565b82810360208401526200a7088185876200a66e565b979650505050505050565b81516001600160401b038111156200a72f576200a72f6200993b565b6200a747816200a74084546200a162565b846200a367565b602080601f8311600181146200a77b57600084156200a7665750858301515b6200a77285826200a3b1565b86555062006308565b600085815260208120601f198616915b828110156200a7ac578886015182559484019460019091019084016200a78b565b50858210156200a7cb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200a7eb816200a162565b600182811680156200a80657600181146200a81c576200a84d565b60ff19841687528215158302870194506200a84d565b8760005260208060002060005b858110156200a8445781548a8201529084019082016200a829565b50505082870194505b50929695505050505050565b6bffffffffffffffffffffffff198360601b1681526000600383106200a88f57634e487b7160e01b600052602160045260246000fd5b5060f89190911b6014820152601501919050565b6bffffffffffffffffffffffff198560601b16815282846014830137601492019182015260340192915050565b600086516200a8e4818460208b01620098d2565b82018587823760009086019081528385823760009301928352509095945050505050565b6001600160a01b038316815260406020820181905260009062009a4590830184620098f8565b600082516200a942818460208701620098d2565b919091019291505056fe608060405260405162000e9638038062000e96833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e6f60279139620002f8565b9392505050565b60006200018060008051602062000e4f83398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e4f83398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61087580620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/pasteur/mainnet/GovernorContract b/core/systemcontracts/pasteur/mainnet/GovernorContract new file mode 100644 index 0000000000..4065cc7973 --- /dev/null +++ b/core/systemcontracts/pasteur/mainnet/GovernorContract @@ -0,0 +1 @@ +6080604052600436106103e85760003560e01c80637b3c71d311610208578063c28bc2fa11610118578063deaaa7cc116100ab578063ece40cc11161007a578063ece40cc114610e19578063f23a6e6114610e39578063f8ce560a14610e65578063fc0c546a14610e85578063fe0d94c114610ea657600080fd5b8063deaaa7cc14610cda578063e23a9a5214610d0e578063ea0217cf14610dd9578063eb9019d414610df957600080fd5b8063da95691a116100e7578063da95691a14610c2f578063dd42a1dd14610c4f578063dd4e2ba514610c74578063ddf0b00914610cba57600080fd5b8063c28bc2fa14610bbd578063c59057e414610bd0578063d07f91e914610bf0578063d33219b414610c1057600080fd5b8063a7713a701161019b578063b187bd261161016a578063b187bd2614610b23578063b58131b014610b41578063bc197c8114610b56578063c01f9e3714610b82578063c170ec0b14610ba257600080fd5b8063a7713a7014610aae578063a890c91014610ac3578063ab58fb8e14610ae3578063ac43175114610b0357600080fd5b806384b0196e116101d757806384b0196e14610a2657806391ddadf414610a4e57806397c3d33414610a7a5780639a802a6d14610a8e57600080fd5b80637b3c71d3146109bc5780637d5e81e2146109dc5780638129fc1c146109fc5780638456cb5914610a1157600080fd5b806332b8113e116103035780634838d1651161029657806354fd4d501161026557806354fd4d5014610912578063567813881461093c5780635f398a141461095c57806360c4247f1461097c57806370b0f6601461099c57600080fd5b80634838d1651461087c5780634a49ac4c146108ac5780634bf5d7e9146108cc578063533ddd14146108e157600080fd5b806340e58ee5116102d257806340e58ee5146107d1578063417c73a7146107f15780634385963214610811578063452115d61461085c57600080fd5b806332b8113e146107455780633932abb11461076e5780633bccf4fd146107845780633e4f49e6146107a457600080fd5b8063150b7a021161037b5780632656227d1161034a5780632656227d146106975780632d63f693146106aa5780632fe3e261146106e1578063328dd9821461071557600080fd5b8063150b7a02146105f0578063160cbed71461063457806317977c611461065457806324bc1a641461068257600080fd5b8063046f7da2116103b7578063046f7da21461054357806306f3f9e61461055857806306fdde0314610578578063143489d01461059a57600080fd5b8063013cf08b1461045857806301ffc9a7146104d357806302a251a314610503578063034201811461052357600080fd5b3661045357306103f6610eb9565b6001600160a01b0316146104515760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206d7573742073656e6420746f206578656375746f720060448201526064015b60405180910390fd5b005b600080fd5b34801561046457600080fd5b50610478610473366004615ca3565b610ed3565b604080519a8b526001600160a01b0390991660208b0152978901969096526060880194909452608087019290925260a086015260c085015260e084015215156101008301521515610120820152610140015b60405180910390f35b3480156104df57600080fd5b506104f36104ee366004615cbc565b610f8e565b60405190151581526020016104ca565b34801561050f57600080fd5b50610195545b6040519081526020016104ca565b34801561052f57600080fd5b5061051561053e366004615e02565b610f9f565b34801561054f57600080fd5b50610451611097565b34801561056457600080fd5b50610451610573366004615ca3565b611127565b34801561058457600080fd5b5061058d6111b2565b6040516104ca9190615ef8565b3480156105a657600080fd5b506105d86105b5366004615ca3565b60009081526101636020526040902054600160401b90046001600160a01b031690565b6040516001600160a01b0390911681526020016104ca565b3480156105fc57600080fd5b5061061b61060b366004615f20565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016104ca565b34801561064057600080fd5b5061051561064f3660046160f7565b611245565b34801561066057600080fd5b5061051561066f366004616186565b6102c36020526000908152604090205481565b34801561068e57600080fd5b50610515611330565b6105156106a53660046160f7565b611356565b3480156106b657600080fd5b506105156106c5366004615ca3565b600090815261016360205260409020546001600160401b031690565b3480156106ed57600080fd5b506105157fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b34801561072157600080fd5b50610735610730366004615ca3565b611449565b6040516104ca949392919061626c565b34801561075157600080fd5b5061028f546040516001600160401b0390911681526020016104ca565b34801561077a57600080fd5b5061019454610515565b34801561079057600080fd5b5061051561079f3660046162b9565b6116db565b3480156107b057600080fd5b506107c46107bf366004615ca3565b611751565b6040516104ca919061631d565b3480156107dd57600080fd5b506104516107ec366004615ca3565b61175c565b3480156107fd57600080fd5b5061045161080c366004616186565b611787565b34801561081d57600080fd5b506104f361082c366004616345565b60008281526101c6602090815260408083206001600160a01b038516845260080190915290205460ff1692915050565b34801561086857600080fd5b506105156108773660046160f7565b611808565b34801561088857600080fd5b506104f3610897366004616186565b60016020526000908152604090205460ff1681565b3480156108b857600080fd5b506104516108c7366004616186565b611816565b3480156108d857600080fd5b5061058d611891565b3480156108ed57600080fd5b506104f36108fc366004616186565b6102c16020526000908152604090205460ff1681565b34801561091e57600080fd5b506040805180820190915260018152603160f81b602082015261058d565b34801561094857600080fd5b50610515610957366004616375565b61193e565b34801561096857600080fd5b506105156109773660046163a1565b611967565b34801561098857600080fd5b50610515610997366004615ca3565b6119b1565b3480156109a857600080fd5b506104516109b7366004615ca3565b611a66565b3480156109c857600080fd5b506105156109d7366004616424565b611aee565b3480156109e857600080fd5b506105156109f736600461647d565b611b40565b348015610a0857600080fd5b50610451611c5b565b348015610a1d57600080fd5b50610451611e8d565b348015610a3257600080fd5b50610a3b611f23565b6040516104ca979695949392919061651d565b348015610a5a57600080fd5b50610a63611fc1565b60405165ffffffffffff90911681526020016104ca565b348015610a8657600080fd5b506064610515565b348015610a9a57600080fd5b50610515610aa936600461657f565b612035565b348015610aba57600080fd5b5061051561204c565b348015610acf57600080fd5b50610451610ade366004616186565b612079565b348015610aef57600080fd5b50610515610afe366004615ca3565b612101565b348015610b0f57600080fd5b50610451610b1e3660046165d7565b61219d565b348015610b2f57600080fd5b5060005462010000900460ff166104f3565b348015610b4d57600080fd5b506105156128e2565b348015610b6257600080fd5b5061061b610b71366004616636565b63bc197c8160e01b95945050505050565b348015610b8e57600080fd5b50610515610b9d366004615ca3565b6128ee565b348015610bae57600080fd5b506102c2546104f39060ff1681565b610451610bcb3660046166c9565b6128f9565b348015610bdc57600080fd5b50610515610beb3660046160f7565b612a09565b348015610bfc57600080fd5b50610451610c0b36600461670c565b612a43565b348015610c1c57600080fd5b5061022b546001600160a01b03166105d8565b348015610c3b57600080fd5b50610515610c4a366004616735565b612acb565b348015610c5b57600080fd5b50600054630100000090046001600160a01b03166105d8565b348015610c8057600080fd5b5060408051808201909152601a81527f737570706f72743d627261766f2671756f72756d3d627261766f000000000000602082015261058d565b348015610cc657600080fd5b50610451610cd5366004615ca3565b612b52565b348015610ce657600080fd5b506105157f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610d1a57600080fd5b50610da9610d29366004616345565b60408051606081018252600080825260208201819052918101919091525060009182526101c6602090815260408084206001600160a01b0393909316845260089092018152918190208151606081018352905460ff8082161515835261010082041693820193909352620100009092046001600160601b03169082015290565b6040805182511515815260208084015160ff1690820152918101516001600160601b0316908201526060016104ca565b348015610de557600080fd5b50610451610df4366004615ca3565b612b75565b348015610e0557600080fd5b50610515610e143660046167d6565b612bfd565b348015610e2557600080fd5b50610451610e34366004615ca3565b612c1e565b348015610e4557600080fd5b5061061b610e54366004616802565b63f23a6e6160e01b95945050505050565b348015610e7157600080fd5b50610515610e80366004615ca3565b612ca6565b348015610e9157600080fd5b506101f8546105d8906001600160a01b031681565b610451610eb4366004615ca3565b612d35565b6000610ece61022b546001600160a01b031690565b905090565b8060008080808080808080610ee78a612101565b60008c815261016360205260409020549098506001600160401b03169650610f0e8b6128ee565b60008c81526101c66020526040812080546005820154600683015460078401546001600160a01b039093169e50949a509850929650919450610f4f8d611751565b90506002816007811115610f6557610f65616307565b1493506007816007811115610f7c57610f7c616307565b14925050509193959799509193959799565b6000610f9982612d58565b92915050565b60008061104361103b7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c604051610fdb92919061686a565b60405180910390208b80519060200120604051602001611020959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b60405160208183030381529060405280519060200120612d7d565b868686612daa565b90506110898a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d9250612dc8915050565b9a9950505050505050505050565b600054630100000090046001600160a01b031633146110c9576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff166110f257604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b61112f610eb9565b6001600160a01b0316336001600160a01b03161461115f5760405162461bcd60e51b81526004016104489061687a565b30611168610eb9565b6001600160a01b0316146111a6576000803660405161118892919061686a565b604051809103902090505b8061119f610164612e6b565b0361119357505b6111af81612eea565b50565b606061016280546111c2906168b1565b80601f01602080910402602001604051908101604052809291908181526020018280546111ee906168b1565b801561123b5780601f106112105761010080835404028352916020019161123b565b820191906000526020600020905b81548152906001019060200180831161121e57829003601f168201915b5050505050905090565b6000805462010000900460ff161561127057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156112a15760405163b1d02c3d60e01b815260040160405180910390fd5b60005b855181101561131a576102c160008783815181106112c4576112c46168eb565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1661130857604051630b094f2760e31b815260040160405180910390fd5b8061131281616917565b9150506112a4565b506113278585858561305b565b95945050505050565b6000610ece600161133f611fc1565b6113499190616930565b65ffffffffffff16612ca6565b60008061136586868686612a09565b9050600061137282611751565b9050600481600781111561138857611388616307565b14806113a5575060058160078111156113a3576113a3616307565b145b6113c15760405162461bcd60e51b815260040161044890616956565b6000828152610163602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f906114109084815260200190565b60405180910390a16114258288888888613260565b6114328288888888613301565b61143f82888888886133e3565b5095945050505050565b60608060608060006101c66000878152602001908152602001600020905080600101816002018260030183600401838054806020026020016040519081016040528092919081815260200182805480156114cc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114ae575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561151e57602002820191906000526020600020905b81548152602001906001019080831161150a575b5050505050925081805480602002602001604051908101604052809291908181526020016000905b828210156115f2578382906000526020600020018054611565906168b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611591906168b1565b80156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505081526020019060010190611546565b50505050915080805480602002602001604051908101604052809291908181526020016000905b828210156116c5578382906000526020600020018054611638906168b1565b80601f0160208091040260200160405190810160405280929190818152602001828054611664906168b1565b80156116b15780601f10611686576101008083540402835291602001916116b1565b820191906000526020600020905b81548152906001019060200180831161169457829003601f168201915b505050505081526020019060010190611619565b5050505090509450945094509450509193509193565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff8516606082015260009081906117299061103b90608001611020565b90506117468782886040518060200160405280600081525061341e565b979650505050505050565b6000610f9982613441565b60008060008061176b8561358e565b935093509350935061177f84848484611808565b505050505050565b600054630100000090046001600160a01b031633146117b9576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60006113278585858561381f565b600054630100000090046001600160a01b03163314611848576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b6101f85460408051634bf5d7e960e01b815290516060926001600160a01b031691634bf5d7e99160048083019260009291908290030181865afa9250505080156118fd57506040513d6000823e601f3d908101601f191682016040526118fa9190810190616997565b60015b611939575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b60008033905061195f8482856040518060200160405280600081525061341e565b949350505050565b60008033905061174687828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250612dc8915050565b61025e546000908082036119ca57505061025d54919050565b600061025e6119da600184616a04565b815481106119ea576119ea6168eb565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b03169282019290925291508410611a4057602001516001600160e01b03169392505050565b611a55611a4c856138ea565b61025e90613953565b6001600160e01b0316949350505050565b611a6e610eb9565b6001600160a01b0316336001600160a01b031614611a9e5760405162461bcd60e51b81526004016104489061687a565b30611aa7610eb9565b6001600160a01b031614611ae55760008036604051611ac792919061686a565b604051809103902090505b80611ade610164612e6b565b03611ad257505b6111af81613a06565b600080339050611b3686828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061341e92505050565b9695505050505050565b6000805462010000900460ff1615611b6b57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615611b9c5760405163b1d02c3d60e01b815260040160405180910390fd5b611ba4613a49565b3360009081526102c360205260409020548015611c19576000611bc682611751565b90506001816007811115611bdc57611bdc616307565b1480611bf957506000816007811115611bf757611bf7616307565b145b15611c175760405163867f3ee560e01b815260040160405180910390fd5b505b825160208401206000611c2e88888885612a09565b3360009081526102c3602052604090208190559050611c4f88888888613af4565b98975050505050505050565b600054610100900460ff1615808015611c7b5750600054600160ff909116105b80611c955750303b158015611c95575060005460ff166001145b611cf85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610448565b6000805460ff191660011790558015611d1b576000805461ff0019166101001790555b334114611d3b5760405163022d8c9560e31b815260040160405180910390fd5b3a15611d5a576040516383f1b1d360e01b815260040160405180910390fd5b611d866040518060400160405280600b81526020016a2129a1a3b7bb32b93737b960a91b815250613b5c565b611db2611d9560036000616a2d565b611da3600362093a80616a2d565b680ad78ebc5ac6200000613bb3565b611dba613bea565b611dc5612005613c11565b611dd0612006613c41565b611dda600a613c71565b611df0611deb600362015180616a2d565b613ca1565b6110076000526102c16020527f2f832952f0ef896b8c8edd6d16a2e4f2591a90375e33021e3b9ff197f3793fc0805460ff19166001179055611e457308e68ec70fa3b629784fdb28887e206ce8561e08613cd1565b80156111af576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b600054630100000090046001600160a01b03163314611ebf576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1615611ee957604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b6000606080600080600060606098546000801b148015611f435750609954155b611f875760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606401610448565b611f8f613d24565b611f97613d33565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6101f854604080516324776b7d60e21b815290516000926001600160a01b0316916391ddadf49160048083019260209291908290030181865afa925050508015612028575060408051601f3d908101601f1916820190925261202591810190616a4f565b60015b61193957610ece43613d42565b6000612042848484613da9565b90505b9392505050565b61025e54600090156120715761206361025e613e20565b6001600160e01b0316905090565b5061025d5490565b612081610eb9565b6001600160a01b0316336001600160a01b0316146120b15760405162461bcd60e51b81526004016104489061687a565b306120ba610eb9565b6001600160a01b0316146120f857600080366040516120da92919061686a565b604051809103902090505b806120f1610164612e6b565b036120e557505b6111af81613e50565b61022b54600082815261022c602052604080822054905163d45c443560e01b81526004810191909152909182916001600160a01b039091169063d45c443590602401602060405180830381865afa158015612160573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121849190616a77565b9050806001146121945780612045565b60009392505050565b33611007146121c357604051630f22c43960e41b81526110076004820152602401610448565b6122296040518060400160405280600b81526020016a766f74696e6744656c617960a81b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ebb9050565b156122de57602081146122575783838383604051630a5a604160e01b81526004016104489493929190616ab9565b604080516020601f8401819004810282018101909252828152600091612298918585808385018382808284376000920191909152509293925050613f149050565b90508015806122a957506201518081115b156122cf5784848484604051630a5a604160e01b81526004016104489493929190616ab9565b6122d881613a06565b5061289f565b6123456040518060400160405280600c81526020016b1d9bdd1a5b99d4195c9a5bd960a21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ebb9050565b156123f457602081146123735783838383604051630a5a604160e01b81526004016104489493929190616ab9565b604080516020601f84018190048102820181019092528281526000916123b4918585808385018382808284376000920191909152509293925050613f149050565b90508015806123c5575062278d0081115b156123eb5784848484604051630a5a604160e01b81526004016104489493929190616ab9565b6122d881613f19565b612460604051806040016040528060118152602001701c1c9bdc1bdcd85b151a1c995cda1bdb19607a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ebb9050565b15612516576020811461248e5783838383604051630a5a604160e01b81526004016104489493929190616ab9565b604080516020601f84018190048102820181019092528281526000916124cf918585808385018382808284376000920191909152509293925050613f149050565b90508015806124e7575069021e19e0c9bab240000081115b1561250d5784848484604051630a5a604160e01b81526004016104489493929190616ab9565b6122d881613fbc565b6125806040518060400160405280600f81526020016e38bab7b93ab6a73ab6b2b930ba37b960891b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ebb9050565b1561262f57602081146125ae5783838383604051630a5a604160e01b81526004016104489493929190616ab9565b604080516020601f84018190048102820181019092528281526000916125ef918585808385018382808284376000920191909152509293925050613f149050565b905060058110806126005750601481115b156126265784848484604051630a5a604160e01b81526004016104489493929190616ab9565b6122d881612eea565b61269e604051806040016040528060148152602001736d696e506572696f64416674657251756f72756d60601b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ebb9050565b1561276457600881146126cc5783838383604051630a5a604160e01b81526004016104489493929190616ab9565b6000612712600884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613f149050565b90506001600160401b038116158061273557506202a300816001600160401b0316115b1561275b5784848484604051630a5a604160e01b81526004016104489493929190616ab9565b6122d881613fff565b6127d06040518060400160405280601181526020017033b7bb32b93737b9283937ba32b1ba37b960791b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613ebb9050565b1561287e57601481146127fe5783838383604051630a5a604160e01b81526004016104489493929190616ab9565b6000612844601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613f149050565b90506001600160a01b0381166128755784848484604051630a5a604160e01b81526004016104489493929190616ab9565b6122d88161406b565b838383836040516325ee20d560e21b81526004016104489493929190616ab9565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516128d49493929190616ab9565b60405180910390a150505050565b6000610ece6101965490565b6000610f99826140d7565b612901610eb9565b6001600160a01b0316336001600160a01b0316146129315760405162461bcd60e51b81526004016104489061687a565b3061293a610eb9565b6001600160a01b031614612978576000803660405161295a92919061686a565b604051809103902090505b80612971610164612e6b565b0361296557505b600080856001600160a01b031685858560405161299692919061686a565b60006040518083038185875af1925050503d80600081146129d3576040519150601f19603f3d011682016040523d82523d6000602084013e6129d8565b606091505b5091509150612a008282604051806060016040528060288152602001616f1660289139614115565b50505050505050565b600084848484604051602001612a229493929190616ae0565b60408051601f19818403018152919052805160209091012095945050505050565b612a4b610eb9565b6001600160a01b0316336001600160a01b031614612a7b5760405162461bcd60e51b81526004016104489061687a565b30612a84610eb9565b6001600160a01b031614612ac25760008036604051612aa492919061686a565b604051809103902090505b80612abb610164612e6b565b03612aaf57505b6111af81613fff565b60008251845114612b2f5760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72427261766f3a20696e76616c6964207369676e61747572656044820152670e640d8cadccee8d60c31b6064820152608401610448565b612b3d33878787878761412e565b611b368686612b4c87876141ec565b85611b40565b600080600080612b618561358e565b935093509350935061177f84848484611245565b612b7d610eb9565b6001600160a01b0316336001600160a01b031614612bad5760405162461bcd60e51b81526004016104489061687a565b30612bb6610eb9565b6001600160a01b031614612bf45760008036604051612bd692919061686a565b604051809103902090505b80612bed610164612e6b565b03612be157505b6111af81613f19565b60006120458383612c1960408051602081019091526000815290565b613da9565b612c26610eb9565b6001600160a01b0316336001600160a01b031614612c565760405162461bcd60e51b81526004016104489061687a565b30612c5f610eb9565b6001600160a01b031614612c9d5760008036604051612c7f92919061686a565b604051809103902090505b80612c96610164612e6b565b03612c8a57505b6111af81613fbc565b60006064612cb3836119b1565b6101f854604051632394e7a360e21b8152600481018690526001600160a01b0390911690638e539e8c90602401602060405180830381865afa158015612cfd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d219190616a77565b612d2b9190616b2b565b610f999190616a2d565b600080600080612d448561358e565b935093509350935061177f84848484611356565b60006001600160e01b03198216636e665ced60e01b1480610f995750610f998261431e565b6000610f99612d8a6143ba565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000612dbb878787876143c4565b9150915061143f81614488565b6000805462010000900460ff1615612df357604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615612e245760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b03851660009081526001602052604090205460ff1615612e5e5760405163b1d02c3d60e01b815260040160405180910390fd5b611b3686868686866145d2565b6000612e868254600f81810b600160801b909204900b131590565b15612ea457604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b6064811115612f6d5760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610448565b6000612f7761204c565b90508015801590612f89575061025e54155b15612fee57604080518082019091526000815261025e9060208101612fad846146d5565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b61301c613009612ffc611fc1565b65ffffffffffff166138ea565b613012846146d5565b61025e919061473e565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60008061306a86868686612a09565b9050600461307782611751565b600781111561308857613088616307565b146130a55760405162461bcd60e51b815260040161044890616956565b61022b546040805163793d064960e11b815290516000926001600160a01b03169163f27a0c929160048083019260209291908290030181865afa1580156130f0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131149190616a77565b61022b5460405163b1c5f42760e01b81529192506001600160a01b03169063b1c5f4279061314f908a908a908a906000908b90600401616b42565b602060405180830381865afa15801561316c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131909190616a77565b600083815261022c60205260408082209290925561022b5491516308f2a0bb60e41b81526001600160a01b0390921691638f2a0bb0916131dd918b918b918b91908b908990600401616b90565b600060405180830381600087803b1580156131f757600080fd5b505af115801561320b573d6000803e3d6000fd5b505050507f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda289282824261323d9190616be8565b604080519283526020830191909152015b60405180910390a15095945050505050565b30613269610eb9565b6001600160a01b0316146132fa5760005b845181101561177f57306001600160a01b031685828151811061329f5761329f6168eb565b60200260200101516001600160a01b0316036132ea576132ea8382815181106132ca576132ca6168eb565b60200260200101518051906020012061016461475990919063ffffffff16565b6132f381616917565b905061327a565b5050505050565b60005462010000900460ff161561332b57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161561335c5760405163b1d02c3d60e01b815260040160405180910390fd5b60005b84518110156133d5576102c1600086838151811061337f5761337f6168eb565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff166133c357604051630b094f2760e31b815260040160405180910390fd5b806133cd81616917565b91505061335f565b506132fa8585858585614795565b306133ec610eb9565b6001600160a01b0316146132fa5761016454600f81810b600160801b909204900b13156132fa576000610164556132fa565b60006113278585858561343c60408051602081019091526000815290565b612dc8565b60008061344d8361480a565b9050600481600781111561346357613463616307565b1461346e5792915050565b600083815261022c60205260409020548061348a575092915050565b61022b54604051632ab0f52960e01b8152600481018390526001600160a01b0390911690632ab0f52990602401602060405180830381865afa1580156134d4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f89190616bfb565b15613507575060079392505050565b61022b54604051632c258a9f60e11b8152600481018390526001600160a01b039091169063584b153e90602401602060405180830381865afa158015613551573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135759190616bfb565b15613584575060059392505050565b5060029392505050565b60608060606000806101c660008781526020019081526020016000209050806001018160020161376083600301805480602002602001604051908101604052809291908181526020016000905b828210156136875783829060005260206000200180546135fa906168b1565b80601f0160208091040260200160405190810160405280929190818152602001828054613626906168b1565b80156136735780601f1061364857610100808354040283529160200191613673565b820191906000526020600020905b81548152906001019060200180831161365657829003601f168201915b5050505050815260200190600101906135db565b50505060048601805460408051602080840282018101909252828152935060009084015b828210156137575783829060005260206000200180546136ca906168b1565b80601f01602080910402602001604051908101604052809291908181526020018280546136f6906168b1565b80156137435780601f1061371857610100808354040283529160200191613743565b820191906000526020600020905b81548152906001019060200180831161372657829003601f168201915b5050505050815260200190600101906136ab565b505050506141ec565b60098401548354604080516020808402820181019092528281529186918301828280156137b657602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613798575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561380857602002820191906000526020600020905b8154815260200190600101908083116137f4575b505050505092509450945094509450509193509193565b60008061382e86868686612a09565b60008181526101c660205260409020549091506001600160a01b031633811480613882575061385b6128e2565b613880826001613869611fc1565b6138739190616930565b65ffffffffffff16612bfd565b105b6138de5760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72427261766f3a2070726f706f7365722061626f76652074686044820152661c995cda1bdb1960ca1b6064820152608401610448565b61174687878787614942565b600063ffffffff82111561394f5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610448565b5090565b8154600090818160058111156139b057600061396e84614950565b6139789085616a04565b60008881526020902090915081015463ffffffff90811690871610156139a0578091506139ae565b6139ab816001616be8565b92505b505b60006139be87878585614a38565b905080156139f9576139e3876139d5600184616a04565b600091825260209091200190565b54600160201b90046001600160e01b0316611746565b6000979650505050505050565b6101945460408051918252602082018390527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a93910160405180910390a161019455565b6102c25460ff16613af2576a084595161401484a0000006120056001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613aa0573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ac49190616a77565b1015613ae3576040516311b6707f60e01b815260040160405180910390fd5b6102c2805460ff191660011790555b565b6000613b5033868686516001600160401b03811115613b1557613b15615d3f565b604051908082528060200260200182016040528015613b4857816020015b6060815260200190600190039081613b335790505b50878761412e565b61132785858585614a8e565b600054610100900460ff16613b835760405162461bcd60e51b815260040161044890616c1d565b613baa81613ba56040805180820190915260018152603160f81b602082015290565b614e6d565b6111af81614ebc565b600054610100900460ff16613bda5760405162461bcd60e51b815260040161044890616c1d565b613be5838383614ef4565b505050565b600054610100900460ff16613af25760405162461bcd60e51b815260040161044890616c1d565b600054610100900460ff16613c385760405162461bcd60e51b815260040161044890616c1d565b6111af81614f36565b600054610100900460ff16613c685760405162461bcd60e51b815260040161044890616c1d565b6111af81614f80565b600054610100900460ff16613c985760405162461bcd60e51b815260040161044890616c1d565b6111af81614fa7565b600054610100900460ff16613cc85760405162461bcd60e51b815260040161044890616c1d565b6111af81614fce565b600054610100900460ff16613cf85760405162461bcd60e51b815260040161044890616c1d565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b6060609a80546111c2906168b1565b6060609b80546111c2906168b1565b600065ffffffffffff82111561394f5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610448565b6101f854604051630748d63560e31b81526001600160a01b038581166004830152602482018590526000921690633a46b1a890604401602060405180830381865afa158015613dfc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120429190616a77565b8054600090801561219457613e3a836139d5600184616a04565b54600160201b90046001600160e01b0316612045565b61022b54604080516001600160a01b03928316815291831660208301527f08f74ea46ef7894f65eabfb5e6e695de773a000b47c529ab559178069b226401910160405180910390a161022b80546001600160a01b0319166001600160a01b0392909216919091179055565b600081604051602001613ece9190616c68565b6040516020818303038152906040528051906020012083604051602001613ef59190616c68565b6040516020818303038152906040528051906020012014905092915050565b015190565b60008111613f795760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253657474696e67733a20766f74696e6720706572696f6420604482015266746f6f206c6f7760c81b6064820152608401610448565b6101955460408051918252602082018390527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828910160405180910390a161019555565b6101965460408051918252602082018390527fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc05461910160405180910390a161019655565b61028f54604080516001600160401b03928316815291831660208301527f7ca4ac117ed3cdce75c1161d8207c440389b1a15d69d096831664657c07dafc2910160405180910390a161028f805467ffffffffffffffff19166001600160401b0392909216919091179055565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008181526101636020526040812060010154610f99906001600160401b0316600084815261029060205260409020546001600160401b0316614ff5565b60608315614124575081612045565b612045838361500b565b80516020820120600061414c878761414688886141ec565b85612a09565b60008181526101c6602052604090206009810154919250906141e15780546001600160a01b0319166001600160a01b038a16178155875161419690600183019060208b0190615ada565b5086516141ac90600283019060208a0190615b3b565b5085516141c29060038301906020890190615b76565b5084516141d89060048301906020880190615bc8565b50600981018390555b505050505050505050565b6060600082516001600160401b0381111561420957614209615d3f565b60405190808252806020026020018201604052801561423c57816020015b60608152602001906001900390816142275790505b50905060005b81518110156143165784818151811061425d5761425d6168eb565b6020026020010151516000146142cd5784818151811061427f5761427f6168eb565b6020026020010151805190602001208482815181106142a0576142a06168eb565b60200260200101516040516020016142b9929190616c84565b6040516020818303038152906040526142e8565b8381815181106142df576142df6168eb565b60200260200101515b8282815181106142fa576142fa6168eb565b60200260200101819052508061430f90616917565b9050614242565b509392505050565b600063288ace0360e11b6318df743f60e31b63bf26d89760e01b6379dd796f60e01b6001600160e01b0319861682148061436457506001600160e01b0319868116908216145b8061437b57506001600160e01b0319868116908516145b8061439657506001600160e01b03198616630271189760e51b145b80611b3657506301ffc9a760e01b6001600160e01b03198716149695505050505050565b6000610ece615035565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143fb575060009050600361447f565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561444f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166144785760006001925092505061447f565b9150600090505b94509492505050565b600081600481111561449c5761449c616307565b036144a45750565b60018160048111156144b8576144b8616307565b036145055760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610448565b600281600481111561451957614519616307565b036145665760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610448565b600381600481111561457a5761457a616307565b036111af5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610448565b6000806145e287878787876150a9565b600088815261029060205260409020549091506001600160401b031615801561460f575061460f876151ff565b15611b3657600061462961028f546001600160401b031690565b614631611fc1565b65ffffffffffff166146439190616cb5565b905061464e886128ee565b816001600160401b0316111561469d576040516001600160401b038216815288907f541f725fb9f7c98a30cc9c0ff32fbb14358cd7159c847a3aa20a2bdc442ba5119060200160405180910390a25b600088815261029060205260409020805467ffffffffffffffff19166001600160401b03929092169190911790559695505050505050565b60006001600160e01b0382111561394f5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610448565b60008061474c85858561523f565b915091505b935093915050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b61022b5460405163e38335e560e01b81526001600160a01b039091169063e38335e59034906147d1908890889088906000908990600401616b42565b6000604051808303818588803b1580156147ea57600080fd5b505af11580156147fe573d6000803e3d6000fd5b50505050505050505050565b600081815261016360205260408120600281015460ff161561482f5750600792915050565b6002810154610100900460ff161561484a5750600292915050565b600083815261016360205260408120546001600160401b0316908190036148b35760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610448565b60006148bd611fc1565b65ffffffffffff1690508082106148d957506000949350505050565b60006148e4866128ee565b90508181106148f95750600195945050505050565b614902866151ff565b8015614925575060008681526101c6602052604090206006810154600590910154115b156149365750600495945050505050565b50600395945050505050565b6000611327858585856153de565b60008160000361496257506000919050565b6000600161496f84615494565b901c6001901b9050600181848161498857614988616a17565b048201901c905060018184816149a0576149a0616a17565b048201901c905060018184816149b8576149b8616a17565b048201901c905060018184816149d0576149d0616a17565b048201901c905060018184816149e8576149e8616a17565b048201901c90506001818481614a0057614a00616a17565b048201901c90506001818481614a1857614a18616a17565b048201901c905061204581828581614a3257614a32616a17565b04615528565b60005b81831015614316576000614a4f8484615537565b60008781526020902090915063ffffffff86169082015463ffffffff161115614a7a57809250614a88565b614a85816001616be8565b93505b50614a3b565b600033614a9b8184615552565b614ae75760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73657220726573747269637465640000006044820152606401610448565b6000614af1611fc1565b65ffffffffffff169050614b036128e2565b614b1283610e14600185616a04565b1015614b7a5760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610448565b6000614b8f8888888880519060200120612a09565b90508651885114614bb25760405162461bcd60e51b815260040161044890616cd5565b8551885114614bd35760405162461bcd60e51b815260040161044890616cd5565b6000885111614c245760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610448565b600081815261016360205260409020546001600160401b031615614c945760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610448565b6000614ca06101945490565b614caa9084616be8565b90506000614cb86101955490565b614cc29083616be8565b90506040518060e00160405280614cd884615643565b6001600160401b031681526001600160a01b038716602082015260006040820152606001614d0583615643565b6001600160401b03908116825260006020808401829052604080850183905260609485018390528883526101638252918290208551815492870151878501519186166001600160e01b031990941693909317600160401b6001600160a01b039094168402176001600160e01b0316600160e01b60e09290921c91909102178155938501516080860151908416921c0217600183015560a08301516002909201805460c09094015161ffff1990941692151561ff00191692909217610100931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e91811115614e0a57614e0a615d3f565b604051908082528060200260200182016040528015614e3d57816020015b6060815260200190600190039081614e285790505b508d88888f604051614e5799989796959493929190616d16565b60405180910390a1509098975050505050505050565b600054610100900460ff16614e945760405162461bcd60e51b815260040161044890616c1d565b609a614ea08382616df4565b50609b614ead8282616df4565b50506000609881905560995550565b600054610100900460ff16614ee35760405162461bcd60e51b815260040161044890616c1d565b610162614ef08282616df4565b5050565b600054610100900460ff16614f1b5760405162461bcd60e51b815260040161044890616c1d565b614f2483613a06565b614f2d82613f19565b613be581613fbc565b600054610100900460ff16614f5d5760405162461bcd60e51b815260040161044890616c1d565b6101f880546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166120f85760405162461bcd60e51b815260040161044890616c1d565b600054610100900460ff166111a65760405162461bcd60e51b815260040161044890616c1d565b600054610100900460ff16612ac25760405162461bcd60e51b815260040161044890616c1d565b60008183116150045781612045565b5090919050565b81511561501b5781518083602001fd5b8060405162461bcd60e51b81526004016104489190615ef8565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f6150606156ab565b615068615704565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60008581526101636020526040812060016150c388611751565b60078111156150d4576150d4616307565b1461512d5760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610448565b80546000906151479088906001600160401b031686613da9565b90506151568888888488615735565b83516000036151ab57866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48988848960405161519e9493929190616eb3565b60405180910390a2611746565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb871289888489896040516151ec959493929190616edb565b60405180910390a2979650505050505050565b60008181526101c6602052604081206005810154615236610e8085600090815261016360205260409020546001600160401b031690565b11159392505050565b82546000908190801561538557600061525d876139d5600185616a04565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090871610156152de5760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610448565b805163ffffffff80881691160361532657846152ff886139d5600186616a04565b80546001600160e01b0392909216600160201b0263ffffffff909216919091179055615375565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b6020015192508391506147519050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b029190931617920191909155905081614751565b6000806153ed868686866158d3565b600081815261022c6020526040902054909150156113275761022b54600082815261022c60205260409081902054905163c4d252f560e01b81526001600160a01b039092169163c4d252f5916154499160040190815260200190565b600060405180830381600087803b15801561546357600080fd5b505af1158015615477573d6000803e3d6000fd5b505050600082815261022c60205260408120555095945050505050565b600080608083901c156154a957608092831c92015b604083901c156154bb57604092831c92015b602083901c156154cd57602092831c92015b601083901c156154df57601092831c92015b600883901c156154f157600892831c92015b600483901c1561550357600492831c92015b600283901c1561551557600292831c92015b600183901c15610f995760010192915050565b60008183106150045781612045565b60006155466002848418616a2d565b61204590848416616be8565b8051600090603481101561556a576001915050610f99565b82810160131901516001600160a01b031981166b046e0e4dee0dee6cae47a60f60a31b1461559d57600192505050610f99565b6000806155ab602885616a04565b90505b83811015615622576000806155e28884815181106155ce576155ce6168eb565b01602001516001600160f81b0319166159e0565b91509150816155fa5760019650505050505050610f99565b8060ff166004856001600160a01b0316901b17935050508061561b90616917565b90506155ae565b50856001600160a01b0316816001600160a01b031614935050505092915050565b60006001600160401b0382111561394f5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610448565b6000806156b6613d24565b8051909150156156cd578051602090910120919050565b60985480156156dc5792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b60008061570f613d33565b805190915015615726578051602090910120919050565b60995480156156dc5792915050565b60008581526101c6602090815260408083206001600160a01b038816845260088101909252909120805460ff16156157c55760405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20766f746560448201526c08185b1c9958591e4818d85cdd609a1b6064820152608401610448565b805460ff86166101000261ffff199091161760011781556157e584615a72565b81546001600160601b039190911662010000026dffffffffffffffffffffffff00001990911617815560ff8516615835578382600601600082825461582a9190616be8565b90915550612a009050565b60001960ff861601615855578382600501600082825461582a9190616be8565b60011960ff861601615875578382600701600082825461582a9190616be8565b60405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20696e766160448201526c6c696420766f7465207479706560981b6064820152608401610448565b6000806158e286868686612a09565b905060006158ef82611751565b9050600281600781111561590557615905616307565b141580156159255750600681600781111561592257615922616307565b14155b80156159435750600781600781111561594057615940616307565b14155b61598f5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610448565b6000828152610163602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c9061324e9084815260200190565b60008060f883901c602f811180156159fb5750603a8160ff16105b15615a1057600194602f199091019350915050565b8060ff166040108015615a26575060478160ff16105b15615a3b576001946036199091019350915050565b8060ff166060108015615a51575060678160ff16105b15615a66576001946056199091019350915050565b50600093849350915050565b60006001600160601b0382111561394f5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610448565b828054828255906000526020600020908101928215615b2f579160200282015b82811115615b2f57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615afa565b5061394f929150615c1a565b828054828255906000526020600020908101928215615b2f579160200282015b82811115615b2f578251825591602001919060010190615b5b565b828054828255906000526020600020908101928215615bbc579160200282015b82811115615bbc5782518290615bac9082616df4565b5091602001919060010190615b96565b5061394f929150615c2f565b828054828255906000526020600020908101928215615c0e579160200282015b82811115615c0e5782518290615bfe9082616df4565b5091602001919060010190615be8565b5061394f929150615c4c565b5b8082111561394f5760008155600101615c1b565b8082111561394f576000615c438282615c69565b50600101615c2f565b8082111561394f576000615c608282615c69565b50600101615c4c565b508054615c75906168b1565b6000825580601f10615c85575050565b601f0160209004906000526020600020908101906111af9190615c1a565b600060208284031215615cb557600080fd5b5035919050565b600060208284031215615cce57600080fd5b81356001600160e01b03198116811461204557600080fd5b803560ff8116811461193957600080fd5b60008083601f840112615d0957600080fd5b5081356001600160401b03811115615d2057600080fd5b602083019150836020828501011115615d3857600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715615d7d57615d7d615d3f565b604052919050565b60006001600160401b03821115615d9e57615d9e615d3f565b50601f01601f191660200190565b600082601f830112615dbd57600080fd5b8135615dd0615dcb82615d85565b615d55565b818152846020838601011115615de557600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060e0898b031215615e1e57600080fd5b88359750615e2e60208a01615ce6565b965060408901356001600160401b0380821115615e4a57600080fd5b615e568c838d01615cf7565b909850965060608b0135915080821115615e6f57600080fd5b50615e7c8b828c01615dac565b945050615e8b60808a01615ce6565b925060a0890135915060c089013590509295985092959890939650565b60005b83811015615ec3578181015183820152602001615eab565b50506000910152565b60008151808452615ee4816020860160208601615ea8565b601f01601f19169290920160200192915050565b6020815260006120456020830184615ecc565b6001600160a01b03811681146111af57600080fd5b60008060008060808587031215615f3657600080fd5b8435615f4181615f0b565b93506020850135615f5181615f0b565b92506040850135915060608501356001600160401b03811115615f7357600080fd5b615f7f87828801615dac565b91505092959194509250565b60006001600160401b03821115615fa457615fa4615d3f565b5060051b60200190565b600082601f830112615fbf57600080fd5b81356020615fcf615dcb83615f8b565b82815260059290921b84018101918181019086841115615fee57600080fd5b8286015b8481101561601257803561600581615f0b565b8352918301918301615ff2565b509695505050505050565b600082601f83011261602e57600080fd5b8135602061603e615dcb83615f8b565b82815260059290921b8401810191818101908684111561605d57600080fd5b8286015b848110156160125780358352918301918301616061565b600082601f83011261608957600080fd5b81356020616099615dcb83615f8b565b82815260059290921b840181019181810190868411156160b857600080fd5b8286015b848110156160125780356001600160401b038111156160db5760008081fd5b6160e98986838b0101615dac565b8452509183019183016160bc565b6000806000806080858703121561610d57600080fd5b84356001600160401b038082111561612457600080fd5b61613088838901615fae565b9550602087013591508082111561614657600080fd5b6161528883890161601d565b9450604087013591508082111561616857600080fd5b5061617587828801616078565b949793965093946060013593505050565b60006020828403121561619857600080fd5b813561204581615f0b565b600081518084526020808501945080840160005b838110156161dc5781516001600160a01b0316875295820195908201906001016161b7565b509495945050505050565b600081518084526020808501945080840160005b838110156161dc578151875295820195908201906001016161fb565b600081518084526020808501808196508360051b8101915082860160005b8581101561625f57828403895261624d848351615ecc565b98850198935090840190600101616235565b5091979650505050505050565b60808152600061627f60808301876161a3565b828103602084015261629181876161e7565b905082810360408401526162a58186616217565b905082810360608401526117468185616217565b600080600080600060a086880312156162d157600080fd5b853594506162e160208701615ce6565b93506162ef60408701615ce6565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b602081016008831061633f57634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561635857600080fd5b82359150602083013561636a81615f0b565b809150509250929050565b6000806040838503121561638857600080fd5b8235915061639860208401615ce6565b90509250929050565b6000806000806000608086880312156163b957600080fd5b853594506163c960208701615ce6565b935060408601356001600160401b03808211156163e557600080fd5b6163f189838a01615cf7565b9095509350606088013591508082111561640a57600080fd5b5061641788828901615dac565b9150509295509295909350565b6000806000806060858703121561643a57600080fd5b8435935061644a60208601615ce6565b925060408501356001600160401b0381111561646557600080fd5b61647187828801615cf7565b95989497509550505050565b6000806000806080858703121561649357600080fd5b84356001600160401b03808211156164aa57600080fd5b6164b688838901615fae565b955060208701359150808211156164cc57600080fd5b6164d88883890161601d565b945060408701359150808211156164ee57600080fd5b6164fa88838901616078565b9350606087013591508082111561651057600080fd5b50615f7f87828801615dac565b60ff60f81b8816815260e06020820152600061653c60e0830189615ecc565b828103604084015261654e8189615ecc565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152905061108981856161e7565b60008060006060848603121561659457600080fd5b833561659f81615f0b565b92506020840135915060408401356001600160401b038111156165c157600080fd5b6165cd86828701615dac565b9150509250925092565b600080600080604085870312156165ed57600080fd5b84356001600160401b038082111561660457600080fd5b61661088838901615cf7565b9096509450602087013591508082111561662957600080fd5b5061647187828801615cf7565b600080600080600060a0868803121561664e57600080fd5b853561665981615f0b565b9450602086013561666981615f0b565b935060408601356001600160401b038082111561668557600080fd5b61669189838a0161601d565b945060608801359150808211156166a757600080fd5b6166b389838a0161601d565b9350608088013591508082111561640a57600080fd5b600080600080606085870312156166df57600080fd5b84356166ea81615f0b565b93506020850135925060408501356001600160401b0381111561646557600080fd5b60006020828403121561671e57600080fd5b81356001600160401b038116811461204557600080fd5b600080600080600060a0868803121561674d57600080fd5b85356001600160401b038082111561676457600080fd5b61677089838a01615fae565b9650602088013591508082111561678657600080fd5b61679289838a0161601d565b955060408801359150808211156167a857600080fd5b6167b489838a01616078565b945060608801359150808211156167ca57600080fd5b6166b389838a01616078565b600080604083850312156167e957600080fd5b82356167f481615f0b565b946020939093013593505050565b600080600080600060a0868803121561681a57600080fd5b853561682581615f0b565b9450602086013561683581615f0b565b9350604086013592506060860135915060808601356001600160401b0381111561685e57600080fd5b61641788828901615dac565b8183823760009101908152919050565b60208082526018908201527f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000604082015260600190565b600181811c908216806168c557607f821691505b6020821081036168e557634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820161692957616929616901565b5060010190565b65ffffffffffff82811682821603908082111561694f5761694f616901565b5092915050565b60208082526021908201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756040820152601b60fa1b606082015260800190565b6000602082840312156169a957600080fd5b81516001600160401b038111156169bf57600080fd5b8201601f810184136169d057600080fd5b80516169de615dcb82615d85565b8181528560208385010111156169f357600080fd5b611327826020830160208601615ea8565b81810381811115610f9957610f99616901565b634e487b7160e01b600052601260045260246000fd5b600082616a4a57634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215616a6157600080fd5b815165ffffffffffff8116811461204557600080fd5b600060208284031215616a8957600080fd5b5051919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000616acd604083018688616a90565b8281036020840152611746818587616a90565b608081526000616af360808301876161a3565b8281036020840152616b0581876161e7565b90508281036040840152616b198186616217565b91505082606083015295945050505050565b8082028115828204841417610f9957610f99616901565b60a081526000616b5560a08301886161a3565b8281036020840152616b6781886161e7565b90508281036040840152616b7b8187616217565b60608401959095525050608001529392505050565b60c081526000616ba360c08301896161a3565b8281036020840152616bb581896161e7565b90508281036040840152616bc98188616217565b60608401969096525050608081019290925260a0909101529392505050565b80820180821115610f9957610f99616901565b600060208284031215616c0d57600080fd5b8151801515811461204557600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251616c7a818460208701615ea8565b9190910192915050565b6001600160e01b0319831681528151600090616ca7816004850160208701615ea8565b919091016004019392505050565b6001600160401b0381811683821601908082111561694f5761694f616901565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b8981526001600160a01b038916602082015261012060408201819052600090616d418382018b6161a3565b90508281036060840152616d55818a6161e7565b90508281036080840152616d698189616217565b905082810360a0840152616d7d8188616217565b90508560c08401528460e0840152828103610100840152616d9e8185615ecc565b9c9b505050505050505050505050565b601f821115613be557600081815260208120601f850160051c81016020861015616dd55750805b601f850160051c820191505b8181101561177f57828155600101616de1565b81516001600160401b03811115616e0d57616e0d615d3f565b616e2181616e1b84546168b1565b84616dae565b602080601f831160018114616e565760008415616e3e5750858301515b600019600386901b1c1916600185901b17855561177f565b600085815260208120601f198616915b82811015616e8557888601518255948401946001909101908401616e66565b5085821015616ea35787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b84815260ff84166020820152826040820152608060608201526000611b366080830184615ecc565b85815260ff8516602082015283604082015260a060608201526000616f0360a0830185615ecc565b8281036080840152611c4f8185615ecc56fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/pasteur/mainnet/StakeHubContract b/core/systemcontracts/pasteur/mainnet/StakeHubContract new file mode 100644 index 0000000000..23b1f5b576 --- /dev/null +++ b/core/systemcontracts/pasteur/mainnet/StakeHubContract @@ -0,0 +1 @@ +6080604052600436106200043b5760003560e01c806386d545061162000233578063ca47908f116200012f578063dd42a1dd11620000b9578063f1f74d841162000084578063f1f74d841462000d75578063f80a34021462000d8d578063fb50b31f1462000db2578063fc0c5ff11462000dd7578063ff69ab611462000def57600080fd5b8063dd42a1dd1462000ce2578063e8f67c3b1462000d09578063e992aaf51462000d21578063efdbf0e11462000d3957600080fd5b8063d7c2dfc811620000fa578063d7c2dfc81462000c68578063d8ca511f1462000c8d578063daacdb661462000ca5578063dbda7fb31462000cbd57600080fd5b8063ca47908f1462000bd1578063cbb04d9d1462000be9578063d115a2061462000c2a578063d6ca429d1462000c4357600080fd5b8063b187bd2611620001bd578063bfff04751162000188578063bfff04751462000b58578063c166f58a1462000b7d578063c38fbec81462000b94578063c473318f1462000bb9578063c8509d81146200095157600080fd5b8063b187bd261462000ac5578063baa7199e1462000ae5578063bdceadf31462000b0a578063bff02e201462000b2257600080fd5b8063a1832e6411620001fe578063a1832e641462000a22578063a43569b31462000a47578063aad3ec961462000a7b578063ac4317511462000aa057600080fd5b806386d54506146200098e5780638a4d3fa814620009c85780638cd22b2214620009e6578063982ef0a71462000a0b57600080fd5b80634838d165116200034357806364028fbd11620002cd57806375cc7d89116200029857806375cc7d8914620008fc57806376e7d6d614620009215780638129fc1c1462000939578063831d65d114620009515780638456cb59146200097657600080fd5b806364028fbd1462000837578063663706d3146200084e5780636ec01b27146200087f5780636f8e2fa414620008d757600080fd5b80634e6fd6c4116200030e5780634e6fd6c4146200079e5780635949187114620007b65780635e7cc1c914620007db57806363a036b5146200080057600080fd5b80634838d16514620006ea57806349f41a42146200072f5780634a49ac4c14620007545780634d99dd16146200077957600080fd5b80631fab701511620003c5578063384099881162000390578063384099881462000663578063417c73a7146200067b578063449ecfe614620006a057806345211bfd14620006c557600080fd5b80631fab701514620005aa5780632b727c8614620005cf5780632e8e8c7114620005f4578063367dad49146200062e57600080fd5b80630e9fbf5111620004065780630e9fbf5114620004f35780631182b875146200051857806317b4f353146200054c5780631fa8882b146200059157600080fd5b8063046f7da2146200045b578063059ddd2214620004735780630661806e14620004b5578063092193ab14620004dc57600080fd5b36620004565760345460ff166001146200045457600080fd5b005b600080fd5b3480156200046857600080fd5b506200045462000e07565b3480156200048057600080fd5b506200049862000492366004620097cc565b62000e99565b6040516001600160a01b0390911681526020015b60405180910390f35b348015620004c257600080fd5b50620004cd60365481565b604051908152602001620004ac565b62000454620004ed366004620097cc565b620012c1565b3480156200050057600080fd5b5062000454620005123660046200982e565b62001912565b3480156200052557600080fd5b506200053d6200053736600462009873565b62001c9e565b604051620004ac919062009926565b3480156200055957600080fd5b50620004986200056b366004620099f8565b80516020818301810180516045825292820191909301209152546001600160a01b031681565b3480156200059e57600080fd5b50620004cd6201518081565b348015620005b757600080fd5b5062000454620005c936600462009a94565b62001d36565b348015620005dc57600080fd5b5062000498620005ee366004620097cc565b6200208d565b3480156200060157600080fd5b506200049862000613366004620097cc565b604d602052600090815260409020546001600160a01b031681565b3480156200063b57600080fd5b50620006536200064d36600462009a94565b620020e2565b604051620004ac92919062009b13565b3480156200067057600080fd5b50620004cd60375481565b3480156200068857600080fd5b50620004546200069a366004620097cc565b620026b1565b348015620006ad57600080fd5b5062000454620006bf366004620097cc565b62002733565b348015620006d257600080fd5b5062000454620006e4366004620097cc565b62002918565b348015620006f757600080fd5b506200071e62000709366004620097cc565b60016020526000908152604090205460ff1681565b6040519015158152602001620004ac565b3480156200073c57600080fd5b50620004546200074e366004620097cc565b62002af1565b3480156200076157600080fd5b506200045462000773366004620097cc565b62002d0d565b3480156200078657600080fd5b50620004546200079836600462009bb2565b62002d89565b348015620007ab57600080fd5b506200049861dead81565b348015620007c357600080fd5b5062000454620007d536600462009bf0565b620033b9565b348015620007e857600080fd5b5062000454620007fa36600462009c5a565b620041b2565b3480156200080d57600080fd5b50620008256200081f36600462009c81565b620043dc565b604051620004ac949392919062009ca4565b620004546200084836600462009d60565b62004a81565b3480156200085b57600080fd5b50620004cd6200086d366004620097cc565b60446020526000908152604090205481565b3480156200088c57600080fd5b50620008a46200089e366004620097cc565b620050d0565b6040805182516001600160401b0390811682526020808501518216908301529282015190921690820152606001620004ac565b348015620008e457600080fd5b506200053d620008f6366004620097cc565b62005175565b3480156200090957600080fd5b50620004546200091b366004620097cc565b620055a1565b3480156200092e57600080fd5b50620004cd603d5481565b3480156200094657600080fd5b506200045462005773565b3480156200095e57600080fd5b50620004546200097036600462009873565b6200593e565b3480156200098357600080fd5b50620004546200599c565b3480156200099b57600080fd5b5062000498620009ad366004620097cc565b6043602052600090815260409020546001600160a01b031681565b348015620009d557600080fd5b50620004cd670de0b6b3a764000081565b348015620009f357600080fd5b50620004cd62000a0536600462009bb2565b62005a34565b6200045462000a1c36600462009e36565b62005aed565b34801562000a2f57600080fd5b506200045462000a4136600462009a94565b6200619b565b34801562000a5457600080fd5b5062000a6c62000a66366004620097cc565b620064a1565b604051620004ac919062009e6e565b34801562000a8857600080fd5b506200045462000a9a36600462009bb2565b6200678e565b34801562000aad57600080fd5b506200045462000abf36600462009eeb565b620067fb565b34801562000ad257600080fd5b5060005462010000900460ff166200071e565b34801562000af257600080fd5b506200045462000b0436600462009f5d565b620077ad565b34801562000b1757600080fd5b50620004cd603c5481565b34801562000b2f57600080fd5b5062000b4762000b4136600462009c81565b6200797a565b604051620004ac9392919062009fb6565b34801562000b6557600080fd5b50620004cd62000b77366004620097cc565b62007b56565b34801562000b8a57600080fd5b50620004cd600581565b34801562000ba157600080fd5b506200045462000bb3366004620097cc565b62007ba4565b34801562000bc657600080fd5b50620004cd60385481565b34801562000bde57600080fd5b50620004cd604e5481565b34801562000bf657600080fd5b5062000c0e62000c08366004620097cc565b62007ec6565b60408051938452911515602084015290820152606001620004ac565b34801562000c3757600080fd5b50620004cd620186a081565b34801562000c5057600080fd5b506200045462000c623660046200a013565b62008309565b34801562000c7557600080fd5b506200045462000c873660046200a0fc565b6200852f565b34801562000c9a57600080fd5b50620004cd603b5481565b34801562000cb257600080fd5b50620004cd60495481565b34801562000cca57600080fd5b506200049862000cdc366004620097cc565b62008625565b34801562000cef57600080fd5b50600054630100000090046001600160a01b031662000498565b34801562000d1657600080fd5b50620004cd60355481565b34801562000d2e57600080fd5b50620004cd603a5481565b34801562000d4657600080fd5b50620004cd62000d58366004620099f8565b805160208183018101805160468252928201919093012091525481565b34801562000d8257600080fd5b50620004cd603e5481565b34801562000d9a57600080fd5b50620004cd62000dac36600462009bb2565b62008a4f565b34801562000dbf57600080fd5b506200045462000dd136600462009eeb565b62008ac0565b34801562000de457600080fd5b50620004cd60395481565b34801562000dfc57600080fd5b50620004cd604a5481565b600054630100000090046001600160a01b0316331462000e3a576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1662000e6457604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162000f04906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462000f32906200a162565b801562000f835780601f1062000f575761010080835404028352916020019162000f83565b820191906000526020600020905b81548152906001019060200180831162000f6557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462000fae906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462000fdc906200a162565b80156200102d5780601f1062001001576101008083540402835291602001916200102d565b820191906000526020600020905b8154815290600101906020018083116200100f57829003601f168201915b5050505050815260200160018201805462001048906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462001076906200a162565b8015620010c75780601f106200109b57610100808354040283529160200191620010c7565b820191906000526020600020905b815481529060010190602001808311620010a957829003601f168201915b50505050508152602001600282018054620010e2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462001110906200a162565b8015620011615780601f10620011355761010080835404028352916020019162001161565b820191906000526020600020905b8154815290600101906020018083116200114357829003601f168201915b505050505081526020016003820180546200117c906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620011aa906200a162565b8015620011fb5780601f10620011cf57610100808354040283529160200191620011fb565b820191906000526020600020905b815481529060010190602001808311620011dd57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200129a575050509190925250509051949350505050565b3361100014620012ed57604051630f22c43960e41b815261100060048201526024015b60405180910390fd5b6001600160a01b0380821660009081526043602090815260408083205484168084526041835281842082516101808101845281548716815260018201548716948101949094526002810154909516918301919091526003840154606083015260048401805491949160808401919062001366906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462001394906200a162565b8015620013e55780601f10620013b957610100808354040283529160200191620013e5565b820191906000526020600020905b815481529060010190602001808311620013c757829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462001410906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200143e906200a162565b80156200148f5780601f1062001463576101008083540402835291602001916200148f565b820191906000526020600020905b8154815290600101906020018083116200147157829003601f168201915b50505050508152602001600182018054620014aa906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620014d8906200a162565b8015620015295780601f10620014fd5761010080835404028352916020019162001529565b820191906000526020600020905b8154815290600101906020018083116200150b57829003601f168201915b5050505050815260200160028201805462001544906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462001572906200a162565b8015620015c35780601f106200159757610100808354040283529160200191620015c3565b820191906000526020600020905b815481529060010190602001808311620015a557829003601f168201915b50505050508152602001600382018054620015de906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200160c906200a162565b80156200165d5780601f1062001631576101008083540402835291602001916200165d565b820191906000526020600020905b8154815290600101906020018083116200163f57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620016fc575050509190925250505060408101519091506001600160a01b031615806200173957508060e001515b15620017f657604051611002903490600081818185875af1925050503d806000811462001783576040519150601f19603f3d011682016040523d82523d6000602084013e62001788565b606091505b505050816001600160a01b03167ffc8bff675087dd2da069cc3fb517b9ed001e19750c0865241a5542dba1ba170d604051620017e99060208082526011908201527024a72b20a624a22fab20a624a220aa27a960791b604082015260600190565b60405180910390a2505050565b60408181015160c0830151519151632f303ebb60e11b81526001600160401b0390921660048301526001600160a01b031690635e607d769034906024016000604051808303818588803b1580156200184d57600080fd5b505af115801562001862573d6000803e3d6000fd5b5050505050816001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea634604051620018a391815260200190565b60405180910390a26040808201519051633041949b60e01b815261200591633041949b91620018d8919086906004016200a198565b600060405180830381600087803b158015620018f357600080fd5b505af115801562001908573d6000803e3d6000fd5b5050505050505b50565b33611001146200193a57604051630f22c43960e41b81526110016004820152602401620012e4565b60005462010000900460ff16156200196557604051631785c68160e01b815260040160405180910390fd5b6000604583836040516200197b9291906200a1b2565b908152604051908190036020019020546001600160a01b03169050620019a3603f8262008cf9565b620019c15760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038116600090815260416020526040812090620019e962015180426200a1d8565b604a546000828152604b60205260409020549192501162001a1d5760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062001a3e9084906200a1fb565b909155505060405160469062001a5890879087906200a1b2565b90815260200160405180910390205460001415801562001aa9575042620151806046878760405162001a8c9291906200a1b2565b90815260200160405180910390205462001aa791906200a1fb565b105b1562001ac857604051631898eb6b60e01b815260040160405180910390fd5b60008062001ad885600262008d1c565b915091508162001afb57604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562001b4e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001b7491906200a211565b905062001b82858362008da4565b84546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562001bc957600080fd5b505af115801562001bde573d6000803e3d6000fd5b50505050856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600260405162001c22939291906200a22b565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162001c60916001600160a01b0316908a906004016200a198565b600060405180830381600087803b15801562001c7b57600080fd5b505af115801562001c90573d6000803e3d6000fd5b505050505050505050505050565b6060336120001462001cc857604051630f22c43960e41b81526120006004820152602401620012e4565b60005462010000900460ff161562001cf357604051631785c68160e01b815260040160405180910390fd5b6034805460ff1916600117905560405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e4565b60005462010000900460ff161562001d6157604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562001d935760405163b1d02c3d60e01b815260040160405180910390fd5b62001d9d62008e98565b62001daa603f8262008cf9565b62001dc85760405163056e881160e01b815260040160405180910390fd5b62001dd262008eff565b600082900362001df557604051636490ffd360e01b815260040160405180910390fd5b600062001e0162008e98565b6001600160a01b0381166000908152604f602052604090208054604e54929350909162001e2f86836200a1fb565b111562001e4f5760405163091af98560e21b815260040160405180910390fd5b60005b8581101562001f3557600087878381811062001e725762001e726200a266565b905060200201350362001e9857604051636490ffd360e01b815260040160405180910390fd5b600062001ea78260016200a1fb565b90505b8681101562001f1f5787878281811062001ec85762001ec86200a266565b9050602002013588888481811062001ee45762001ee46200a266565b905060200201350362001f0a57604051632205e3c760e11b815260040160405180910390fd5b8062001f16816200a27c565b91505062001eaa565b508062001f2c816200a27c565b91505062001e52565b5060005b8581101562001fd45760005b8281101562001fbe5783818154811062001f635762001f636200a266565b906000526020600020015488888481811062001f835762001f836200a266565b905060200201350362001fa957604051632205e3c760e11b815260040160405180910390fd5b8062001fb5816200a27c565b91505062001f45565b508062001fcb816200a27c565b91505062001f39565b5060005b8581101562001908578287878381811062001ff75762001ff76200a266565b835460018101855560009485526020948590209190940292909201359190920155506001600160a01b0384167f7c4ff4c9a343a2daef608f3b5a91016e994a15fc0ef8611109e4f45823249f298888848181106200205957620020596200a266565b905060200201356040516200207091815260200190565b60405180910390a28062002084816200a27c565b91505062001fd8565b6000816200209d603f8262008cf9565b620020bb5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160205260409020600d01541691505b50919050565b60608082806001600160401b038111156200210157620021016200993b565b6040519080825280602002602001820160405280156200212b578160200160208202803683370190505b509250806001600160401b038111156200214957620021496200993b565b6040519080825280602002602001820160405280156200217e57816020015b6060815260200190600190039081620021685790505b50915060005b81811015620026a7576000868683818110620021a457620021a46200a266565b9050602002016020810190620021bb9190620097cc565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549495509193909291608084019162002228906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002256906200a162565b8015620022a75780601f106200227b57610100808354040283529160200191620022a7565b820191906000526020600020905b8154815290600101906020018083116200228957829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620022d2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002300906200a162565b8015620023515780601f10620023255761010080835404028352916020019162002351565b820191906000526020600020905b8154815290600101906020018083116200233357829003601f168201915b505050505081526020016001820180546200236c906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200239a906200a162565b8015620023eb5780601f10620023bf57610100808354040283529160200191620023eb565b820191906000526020600020905b815481529060010190602001808311620023cd57829003601f168201915b5050505050815260200160028201805462002406906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002434906200a162565b8015620024855780601f10620024595761010080835404028352916020019162002485565b820191906000526020600020905b8154815290600101906020018083116200246757829003601f168201915b50505050508152602001600382018054620024a0906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620024ce906200a162565b80156200251f5780601f10620024f3576101008083540402835291602001916200251f565b820191906000526020600020905b8154815290600101906020018083116200250157829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620025be5750505050508152505090508060000151868481518110620025f757620025f76200a266565b6001600160a01b039283166020918202929092018101919091529083166000908152604f8252604090819020805482518185028101850190935280835291929091908301828280156200266a57602002820191906000526020600020905b81548152602001906001019080831162002655575b50505050508584815181106200268457620026846200a266565b6020026020010181905250505080806200269e906200a27c565b91505062002184565b50505b9250929050565b600054630100000090046001600160a01b03163314620026e4576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60005462010000900460ff16156200275e57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620027905760405163b1d02c3d60e01b815260040160405180910390fd5b806200279e603f8262008cf9565b620027bc5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166000908152604160205260409020600a81015460ff16620027fa57604051634b6b857d60e01b815260040160405180910390fd5b6036546002820154604051630913db4760e01b81526001600160a01b03868116600483015290911690630913db4790602401602060405180830381865afa1580156200284a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200287091906200a211565b101562002890576040516317b204bf60e11b815260040160405180910390fd5b4281600b01541115620028b65760405163170cb76760e21b815260040160405180910390fd5b600a8101805460ff191690556049805460019190600090620028da9084906200a298565b90915550506040516001600160a01b038416907f9390b453426557da5ebdc31f19a37753ca04addf656d32f35232211bb2af3f1990600090a2505050565b60005462010000900460ff16156200294357604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620029755760405163b1d02c3d60e01b815260040160405180910390fd5b6200297f62008f12565b6200298c603f8262008cf9565b620029aa5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038216620029d257604051636520611b60e11b815260040160405180910390fd5b6001600160a01b03828116600090815260436020526040902054161562002a0c57604051631e6f587560e11b815260040160405180910390fd5b600062002a1862008f12565b6001600160a01b0381166000908152604160205260409020600c81015491925090429062002a4b9062015180906200a1fb565b111562002a6b57604051631f92cdbd60e11b815260040160405180910390fd5b80546001600160a01b039081166000908152604460209081526040808320429081905585548986166001600160a01b031991821681178855600c88019290925581855260439093528184208054958816959093168517909255519092917f6e4e747ca35203f16401c69805c7dd52fff67ef60b0ebc5c7fe16890530f223591a350505050565b3362002aff603f8262008cf9565b62002b1d5760405163056e881160e01b815260040160405180910390fd5b60005462010000900460ff161562002b4857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002b7a5760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b038281166000908152604d6020526040902054161562002bb45760405163bebdc75760e01b815260040160405180910390fd5b62002bc1603f8362008cf9565b1562002be05760405163bebdc75760e01b815260040160405180910390fd5b336000818152604160205260409020600d01546001600160a01b03908116908416810362002c215760405163bebdc75760e01b815260040160405180910390fd5b6001600160a01b0381161562002c58576001600160a01b0381166000908152604d6020526040902080546001600160a01b03191690555b6001600160a01b038281166000908152604160205260409020600d0180546001600160a01b03191691861691821790551562002cbd576001600160a01b038481166000908152604d6020526040902080546001600160a01b0319169184169190911790555b836001600160a01b0316816001600160a01b0316836001600160a01b03167fcbb728765de145e99c00e8ae32a325231e850359b7b8a6da3b84d672ab3f1d0a60405160405180910390a450505050565b600054630100000090046001600160a01b0316331462002d40576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60005462010000900460ff161562002db457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002de65760405163b1d02c3d60e01b815260040160405180910390fd5b8162002df4603f8262008cf9565b62002e125760405163056e881160e01b815260040160405180910390fd5b8160000362002e3457604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162002e9c906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002eca906200a162565b801562002f1b5780601f1062002eef5761010080835404028352916020019162002f1b565b820191906000526020600020905b81548152906001019060200180831162002efd57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002f46906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462002f74906200a162565b801562002fc55780601f1062002f995761010080835404028352916020019162002fc5565b820191906000526020600020905b81548152906001019060200180831162002fa757829003601f168201915b5050505050815260200160018201805462002fe0906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200300e906200a162565b80156200305f5780601f1062003033576101008083540402835291602001916200305f565b820191906000526020600020905b8154815290600101906020018083116200304157829003601f168201915b505050505081526020016002820180546200307a906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620030a8906200a162565b8015620030f95780601f10620030cd57610100808354040283529160200191620030f9565b820191906000526020600020905b815481529060010190602001808311620030db57829003601f168201915b5050505050815260200160038201805462003114906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003142906200a162565b8015620031935780601f10620031675761010080835404028352916020019162003193565b820191906000526020600020905b8154815290600101906020018083116200317557829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162003232575050509190925250505060408082015190516326ccee8b60e11b81526001600160a01b0385811660048301526024820188905292935060009290911690634d99dd16906044016020604051808303816000875af1158015620032ac573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620032d291906200a211565b9050826001600160a01b0316866001600160a01b03167f3aace7340547de7b9156593a7652dc07ee900cea3fd8f82cb6c9d38b40829802878460405162003323929190918252602082015260400190565b60405180910390a3856001600160a01b0316836001600160a01b0316036200335057620033508662008f53565b6040808301519051633041949b60e01b815261200591633041949b916200337d919087906004016200a198565b600060405180830381600087803b1580156200339857600080fd5b505af1158015620033ad573d6000803e3d6000fd5b50505050505050505050565b60005462010000900460ff1615620033e457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620034165760405163b1d02c3d60e01b815260040160405180910390fd5b8362003424603f8262008cf9565b620034425760405163056e881160e01b815260040160405180910390fd5b8362003450603f8262008cf9565b6200346e5760405163056e881160e01b815260040160405180910390fd5b6034805460ff1916600117905560008490036200349e57604051639811e0c760e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031603620034d15760405163f0e3e62960e01b815260040160405180910390fd5b6001600160a01b038087166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162003539906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003567906200a162565b8015620035b85780601f106200358c57610100808354040283529160200191620035b8565b820191906000526020600020905b8154815290600101906020018083116200359a57829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620035e3906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003611906200a162565b8015620036625780601f10620036365761010080835404028352916020019162003662565b820191906000526020600020905b8154815290600101906020018083116200364457829003601f168201915b505050505081526020016001820180546200367d906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620036ab906200a162565b8015620036fc5780601f10620036d057610100808354040283529160200191620036fc565b820191906000526020600020905b815481529060010190602001808311620036de57829003601f168201915b5050505050815260200160028201805462003717906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003745906200a162565b8015620037965780601f106200376a5761010080835404028352916020019162003796565b820191906000526020600020905b8154815290600101906020018083116200377857829003601f168201915b50505050508152602001600382018054620037b1906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620037df906200a162565b8015620038305780601f10620038045761010080835404028352916020019162003830565b820191906000526020600020905b8154815290600101906020018083116200381257829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620038cf57505050919092525050506001600160a01b038089166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054949550919390929160808401916200395a906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003988906200a162565b8015620039d95780601f10620039ad57610100808354040283529160200191620039d9565b820191906000526020600020905b815481529060010190602001808311620039bb57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462003a04906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003a32906200a162565b801562003a835780601f1062003a575761010080835404028352916020019162003a83565b820191906000526020600020905b81548152906001019060200180831162003a6557829003601f168201915b5050505050815260200160018201805462003a9e906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003acc906200a162565b801562003b1d5780601f1062003af15761010080835404028352916020019162003b1d565b820191906000526020600020905b81548152906001019060200180831162003aff57829003601f168201915b5050505050815260200160028201805462003b38906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003b66906200a162565b801562003bb75780601f1062003b8b5761010080835404028352916020019162003bb7565b820191906000526020600020905b81548152906001019060200180831162003b9957829003601f168201915b5050505050815260200160038201805462003bd2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462003c00906200a162565b801562003c515780601f1062003c255761010080835404028352916020019162003c51565b820191906000526020600020905b81548152906001019060200180831162003c3357829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162003cf05750505050508152505090508060e00151801562003d335750876001600160a01b0316836001600160a01b031614155b1562003d5257604051636468920360e01b815260040160405180910390fd5b60408083015190516352e82ce560e11b81526001600160a01b038581166004830152602482018a9052600092169063a5d059ca906044016020604051808303816000875af115801562003da9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003dcf91906200a211565b905060375481101562003df55760405163dc6f0bdd60e01b815260040160405180910390fd5b896001600160a01b0316846001600160a01b031614801562003e8a57506036546040808501519051630913db4760e01b81526001600160a01b038d8116600483015290911690630913db4790602401602060405180830381865afa15801562003e62573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e8891906200a211565b105b1562003ea9576040516317b204bf60e11b815260040160405180910390fd5b6000620186a0603a548362003ebf91906200a2ae565b62003ecb91906200a1d8565b9050600083604001516001600160a01b03168260405160006040518083038185875af1925050503d806000811462003f20576040519150601f19603f3d011682016040523d82523d6000602084013e62003f25565b606091505b505090508062003f48576040516312171d8360e31b815260040160405180910390fd5b62003f5482846200a298565b60408086015190516317066a5760e21b81526001600160a01b03898116600483015292955060009290911690635c19a95c90869060240160206040518083038185885af115801562003faa573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062003fd191906200a211565b9050866001600160a01b03168c6001600160a01b03168e6001600160a01b03167ffdac6e81913996d95abcc289e90f2d8bd235487ce6fe6f821e7d21002a1915b48e858960405162004036939291909283526020830191909152604082015260600190565b60405180910390a46040805160028082526060820183526000926020830190803683370190505090508660400151816000815181106200407a576200407a6200a266565b60200260200101906001600160a01b031690816001600160a01b031681525050856040015181600181518110620040b557620040b56200a266565b6001600160a01b0390921660209283029190910190910152604051634484077560e01b815261200590634484077590620040f69084908c906004016200a2c8565b600060405180830381600087803b1580156200411157600080fd5b505af115801562004126573d6000803e3d6000fd5b505050508a1562004198576120056001600160a01b031663e5ed5b1e898f6040518363ffffffff1660e01b8152600401620041639291906200a198565b600060405180830381600087803b1580156200417e57600080fd5b505af115801562004193573d6000803e3d6000fd5b505050505b50506034805460ff19169055505050505050505050505050565b60005462010000900460ff1615620041dd57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200420f5760405163b1d02c3d60e01b815260040160405180910390fd5b6200421962008f12565b62004226603f8262008cf9565b620042445760405163056e881160e01b815260040160405180910390fd5b60006200425062008f12565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620042839062015180906200a1fb565b1115620042a357604051631f92cdbd60e11b815260040160405180910390fd5b60098101546001600160401b03600160401b90910481169085161115620042dd5760405163dc81db8560e01b815260040160405180910390fd5b60098101546000906001600160401b0390811690861610156200431b576009820154620043159086906001600160401b03166200a2f4565b62004335565b600982015462004335906001600160401b0316866200a2f4565b60098301546001600160401b039182169250600160801b900416811115620043705760405163dc81db8560e01b815260040160405180910390fd5b60098201805467ffffffffffffffff19166001600160401b03871690811790915542600c8401556040519081526001600160a01b038416907f78cdd96edf59e09cfd4d26ef6ef6c92d166effe6a40970c54821206d541932cb9060200160405180910390a25050505050565b60608060606000620043ef603f62009071565b90508086101562004a785784156200440857846200440a565b805b94506000856200441b88846200a298565b1162004433576200442d87836200a298565b62004435565b855b9050806001600160401b038111156200445257620044526200993b565b6040519080825280602002602001820160405280156200447c578160200160208202803683370190505b509450806001600160401b038111156200449a576200449a6200993b565b604051908082528060200260200182016040528015620044c4578160200160208202803683370190505b509350806001600160401b03811115620044e257620044e26200993b565b6040519080825280602002602001820160405280156200451757816020015b6060815260200190600190039081620045015790505b50925060005b8181101562004a755760006200454162004538838b6200a1fb565b603f906200907c565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620045ae906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620045dc906200a162565b80156200462d5780601f1062004601576101008083540402835291602001916200462d565b820191906000526020600020905b8154815290600101906020018083116200460f57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462004658906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462004686906200a162565b8015620046d75780601f10620046ab57610100808354040283529160200191620046d7565b820191906000526020600020905b815481529060010190602001808311620046b957829003601f168201915b50505050508152602001600182018054620046f2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462004720906200a162565b8015620047715780601f10620047455761010080835404028352916020019162004771565b820191906000526020600020905b8154815290600101906020018083116200475357829003601f168201915b505050505081526020016002820180546200478c906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620047ba906200a162565b80156200480b5780601f10620047df576101008083540402835291602001916200480b565b820191906000526020600020905b815481529060010190602001808311620047ed57829003601f168201915b5050505050815260200160038201805462004826906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462004854906200a162565b8015620048a55780601f106200487957610100808354040283529160200191620048a5565b820191906000526020600020905b8154815290600101906020018083116200488757829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200494457505050505081525050905080600001518884815181106200497d576200497d6200a266565b60200260200101906001600160a01b031690816001600160a01b0316815250508060e0015162004a165780604001516001600160a01b03166315d1f8986040518163ffffffff1660e01b8152600401602060405180830381865afa158015620049ea573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062004a1091906200a211565b62004a19565b60005b87848151811062004a2e5762004a2e6200a266565b602002602001018181525050806080015186848151811062004a545762004a546200a266565b602002602001018190525050508062004a6d906200a27c565b90506200451d565b50505b92959194509250565b60005462010000900460ff161562004aac57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562004ade5760405163b1d02c3d60e01b815260040160405180910390fd5b3362004aec603f8262008cf9565b1562004b0b57604051635f28f62b60e01b815260040160405180910390fd5b6001600160a01b038181166000908152604d6020526040902054161562004b4557604051631a0a9b9f60e21b815260040160405180910390fd5b6001600160a01b03888116600090815260436020526040902054161562004b7f57604051631e6f587560e11b815260040160405180910390fd5b60006001600160a01b03166045888860405162004b9e9291906200a1b2565b908152604051908190036020019020546001600160a01b03161462004bd6576040516311fdb94760e01b815260040160405180910390fd5b600062004be483806200a31e565b60405160200162004bf79291906200a1b2565b60408051601f1981840301815291815281516020928301206000818152604290935291205490915060ff161562004c415760405163c0bf414360e01b815260040160405180910390fd5b600062004c57670de0b6b3a7640000346200a298565b905060365481101562004c7d576040516317b204bf60e11b815260040160405180910390fd5b6001600160a01b038a1662004ca557604051636520611b60e11b815260040160405180910390fd5b61138862004cba604087016020880162009c5a565b6001600160401b0316118062004d00575062004cdd604086016020870162009c5a565b6001600160401b031662004cf5602087018762009c5a565b6001600160401b0316115b8062004d3f575062004d19604086016020870162009c5a565b6001600160401b031662004d34606087016040880162009c5a565b6001600160401b0316115b1562004d5e5760405163dc81db8560e01b815260040160405180910390fd5b62004da962004d6e85806200a31e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200908a92505050565b62004dc757604051635dba5ad760e01b815260040160405180910390fd5b62004dd6838a8a8a8a6200922c565b62004df457604051631647e3cb60e11b815260040160405180910390fd5b600062004e428462004e0787806200a31e565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200935c92505050565b905062004e51603f856200945d565b506000838152604260209081526040808320805460ff191660019081179091556001600160a01b0380891680865260419094529190932080548f83166001600160a01b03199182161782559381018054851690931790925560028201805491851691909316179091554260038201556004810162004ed18b8d836200a3c6565b50856005820162004ee382826200a48e565b508790506009820162004ef782826200a5c7565b505042600c8201556001600160a01b038c81166000908152604360205260409081902080546001600160a01b0319169288169290921790915551859060459062004f45908e908e906200a1b2565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316856001600160a01b03168d6001600160a01b03167faecd9fb95e79c75a3a1de93362c6be5fe6ab65770d8614be583884161cd8228d8e8e60405162004fc89291906200a697565b60405180910390a460408051848152602081018590526001600160a01b0387169182917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a360408051670de0b6b3a7640000808252602082015261dead916001600160a01b038816917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a3604051633041949b60e01b815261200590633041949b906200508e90859089906004016200a198565b600060405180830381600087803b158015620050a957600080fd5b505af1158015620050be573d6000803e3d6000fd5b50505050505050505050505050505050565b604080516060810182526000808252602082018190529181019190915281620050fb603f8262008cf9565b620051195760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b031660009081526041602090815260409182902082516060810184526009909101546001600160401b038082168352600160401b8204811693830193909352600160801b90049091169181019190915290565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082810191909152600484018054919491608084019190620051e2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005210906200a162565b8015620052615780601f10620052355761010080835404028352916020019162005261565b820191906000526020600020905b8154815290600101906020018083116200524357829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200528c906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620052ba906200a162565b80156200530b5780601f10620052df576101008083540402835291602001916200530b565b820191906000526020600020905b815481529060010190602001808311620052ed57829003601f168201915b5050505050815260200160018201805462005326906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005354906200a162565b8015620053a55780601f106200537957610100808354040283529160200191620053a5565b820191906000526020600020905b8154815290600101906020018083116200538757829003601f168201915b50505050508152602001600282018054620053c0906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620053ee906200a162565b80156200543f5780601f1062005413576101008083540402835291602001916200543f565b820191906000526020600020905b8154815290600101906020018083116200542157829003601f168201915b505050505081526020016003820180546200545a906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005488906200a162565b8015620054d95780601f10620054ad57610100808354040283529160200191620054d9565b820191906000526020600020905b815481529060010190602001808311620054bb57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620055785750505091909252505050608001519392505050565b3361100114620055c957604051630f22c43960e41b81526110016004820152602401620012e4565b6001600160a01b0380821660009081526043602052604090205416620055f1603f8262008cf9565b6200560f5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038181166000908152604160205260408082206002810154603b54925163045bc4d160e41b81526004810193909352909316906345bc4d10906024016020604051808303816000875af115801562005672573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200569891906200a211565b90506000603d5442620056ac91906200a1fb565b9050620056ba838262008da4565b836001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb282846001604051620056fa939291906200a22b565b60405180910390a26002830154604051633041949b60e01b815261200591633041949b9162005738916001600160a01b03169088906004016200a198565b600060405180830381600087803b1580156200575357600080fd5b505af115801562005768573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff1615808015620057945750600054600160ff909116105b80620057b05750303b158015620057b0575060005460ff166001145b620058155760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620012e4565b6000805460ff19166001179055801562005839576000805461ff0019166101001790555b3341146200585a5760405163022d8c9560e31b815260040160405180910390fd5b3a156200587a576040516383f1b1d360e01b815260040160405180910390fd5b611388603555686c6b935b8bbd400000603655670de0b6b3a7640000603755602d60385562093a806039556002603a819055678ac7230489e80000603b55680ad78ebc5ac6200000603c556202a300603d5562278d00603e55604a55620058f57308e68ec70fa3b629784fdb28887e206ce8561e0862009474565b80156200190f576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b33612000146200596657604051630f22c43960e41b81526120006004820152602401620012e4565b60405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e4565b600054630100000090046001600160a01b03163314620059cf576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1615620059fa57604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b600062005a43603f8462008cf9565b62005a615760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383811660009081526041602052604090819020600201549051636bbf224960e01b815260048101859052911690636bbf2249906024015b602060405180830381865afa15801562005abe573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062005ae491906200a211565b90505b92915050565b60005462010000900460ff161562005b1857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562005b4a5760405163b1d02c3d60e01b815260040160405180910390fd5b8162005b58603f8262008cf9565b62005b765760405163056e881160e01b815260040160405180910390fd5b603754349081101562005b9c5760405163dc6f0bdd60e01b815260040160405180910390fd5b6001600160a01b038085166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162005c04906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005c32906200a162565b801562005c835780601f1062005c575761010080835404028352916020019162005c83565b820191906000526020600020905b81548152906001019060200180831162005c6557829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462005cae906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005cdc906200a162565b801562005d2d5780601f1062005d015761010080835404028352916020019162005d2d565b820191906000526020600020905b81548152906001019060200180831162005d0f57829003601f168201915b5050505050815260200160018201805462005d48906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005d76906200a162565b801562005dc75780601f1062005d9b5761010080835404028352916020019162005dc7565b820191906000526020600020905b81548152906001019060200180831162005da957829003601f168201915b5050505050815260200160028201805462005de2906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005e10906200a162565b801562005e615780601f1062005e355761010080835404028352916020019162005e61565b820191906000526020600020905b81548152906001019060200180831162005e4357829003601f168201915b5050505050815260200160038201805462005e7c906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462005eaa906200a162565b801562005efb5780601f1062005ecf5761010080835404028352916020019162005efb565b820191906000526020600020905b81548152906001019060200180831162005edd57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162005f9a5750505050508152505090508060e00151801562005fdd5750856001600160a01b0316826001600160a01b031614155b1562005ffc57604051636468920360e01b815260040160405180910390fd5b60408082015190516317066a5760e21b81526001600160a01b0384811660048301526000921690635c19a95c90869060240160206040518083038185885af11580156200604d573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200607491906200a211565b9050826001600160a01b0316876001600160a01b03167f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e048387604051620060c5929190918252602082015260400190565b60405180910390a36040808301519051633041949b60e01b815261200591633041949b91620060fa919087906004016200a198565b600060405180830381600087803b1580156200611557600080fd5b505af11580156200612a573d6000803e3d6000fd5b50505050851562001908576040516372f6ad8f60e11b81526120059063e5ed5b1e906200615e9086908b906004016200a198565b600060405180830381600087803b1580156200617957600080fd5b505af11580156200618e573d6000803e3d6000fd5b5050505050505050505050565b60005462010000900460ff1615620061c657604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620061f85760405163b1d02c3d60e01b815260040160405180910390fd5b6200620262008e98565b6200620f603f8262008cf9565b6200622d5760405163056e881160e01b815260040160405180910390fd5b60006200623962008e98565b6001600160a01b0381166000908152604f6020526040812080549293509190859003620063105760005b81811015620062e457836001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a848381548110620062ac57620062ac6200a266565b9060005260206000200154604051620062c791815260200190565b60405180910390a280620062db816200a27c565b91505062006263565b506001600160a01b0383166000908152604f60205260408120620063089162009766565b505050505050565b60005b858110156200646e5760008787838181106200633357620063336200a266565b90506020020135905060005b838110156200645657818582815481106200635e576200635e6200a266565b9060005260206000200154036200644157846200637d6001866200a298565b815481106200639057620063906200a266565b9060005260206000200154858281548110620063b057620063b06200a266565b906000526020600020018190555084805480620063d157620063d16200a6ad565b600190038181906000526020600020016000905590558380620063f4906200a6c3565b945050856001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a836040516200643391815260200190565b60405180910390a262006456565b806200644d816200a27c565b9150506200633f565b5050808062006465906200a27c565b91505062006313565b50815460000362006308576001600160a01b0383166000908152604f60205260408120620063089162009766565b505050565b620064cd6040518060800160405280606081526020016060815260200160608152602001606081525090565b81620064db603f8262008cf9565b620064f95760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383166000908152604160205260409081902081516080810190925260050180548290829062006530906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200655e906200a162565b8015620065af5780601f106200658357610100808354040283529160200191620065af565b820191906000526020600020905b8154815290600101906020018083116200659157829003601f168201915b50505050508152602001600182018054620065ca906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620065f8906200a162565b8015620066495780601f106200661d5761010080835404028352916020019162006649565b820191906000526020600020905b8154815290600101906020018083116200662b57829003601f168201915b5050505050815260200160028201805462006664906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462006692906200a162565b8015620066e35780601f10620066b757610100808354040283529160200191620066e3565b820191906000526020600020905b815481529060010190602001808311620066c557829003601f168201915b50505050508152602001600382018054620066fe906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200672c906200a162565b80156200677d5780601f1062006751576101008083540402835291602001916200677d565b820191906000526020600020905b8154815290600101906020018083116200675f57829003601f168201915b505050505081525050915050919050565b60005462010000900460ff1615620067b957604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620067eb5760405163b1d02c3d60e01b815260040160405180910390fd5b620067f782826200950d565b5050565b33611007146200682357604051630f22c43960e41b81526110076004820152602401620012e4565b620068906040518060400160405280601081526020016f1d1c985b9cd9995c91d85cd31a5b5a5d60821b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b156200694b5760208114620068c25783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006905918585808385018382808284376000920191909152509293925050620096769050565b90506108fc81108062006919575061271081115b15620069425784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60355562007768565b620069bc6040518060400160405280601481526020017336b4b729b2b6332232b632b3b0ba34b7b721272160611b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006a865760208114620069ee5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006a31918585808385018382808284376000920191909152509293925050620096769050565b9050683635c9adc5dea0000081108062006a54575069152d02c7e14af680000081115b1562006a7d5784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60365562007768565b62006af9604051806040016040528060168152602001756d696e44656c65676174696f6e424e424368616e676560501b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006bc0576020811462006b2b5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006b6e918585808385018382808284376000920191909152509293925050620096769050565b905067016345785d8a000081108062006b8e5750678ac7230489e8000081115b1562006bb75784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60375562007768565b62006c31604051806040016040528060148152602001736d6178456c656374656456616c696461746f727360601b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006ce9576020811462006c635783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006ca6918585808385018382808284376000920191909152509293925050620096769050565b905080158062006cb757506101f481115b1562006ce05784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60385562007768565b62006d526040518060400160405280600c81526020016b1d5b989bdb9914195c9a5bd960a21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006e0f576020811462006d845783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006dc7918585808385018382808284376000920191909152509293925050620096769050565b90506203f48081108062006ddd575062278d0081115b1562006e065784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b60395562007768565b62006e7d60405180604001604052806011815260200170726564656c65676174654665655261746560781b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b1562006f2a576020811462006eaf5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162006ef2918585808385018382808284376000920191909152509293925050620096769050565b9050606481111562006f215784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603a5562007768565b62006f9a60405180604001604052806013815260200172191bdddb9d1a5b5954db185cda105b5bdd5b9d606a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b156200705c576020811462006fcc5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f84018190048102820181019092528281526000916200700f918585808385018382808284376000920191909152509293925050620096769050565b9050670de0b6b3a76400008110806200702a5750603c548110155b15620070535784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603b5562007768565b620070ca6040518060400160405280601181526020017019995b1bdb9e54db185cda105b5bdd5b9d607a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b156200718c5760208114620070fc5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f84018190048102820181019092528281526000916200713f918585808385018382808284376000920191909152509293925050620096769050565b9050678ac7230489e800008110806200715a5750603b548111155b15620071835784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603c5562007768565b620071f96040518060400160405280601081526020016f646f776e74696d654a61696c54696d6560801b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b15620072b657602081146200722b5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f84018190048102820181019092528281526000916200726e918585808385018382808284376000920191909152509293925050620096769050565b905062015180811080620072845750603e548110155b15620072ad5784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603d5562007768565b620073216040518060400160405280600e81526020016d66656c6f6e794a61696c54696d6560901b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b15620073de5760208114620073535783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f840181900481028201810190925282815260009162007396918585808385018382808284376000920191909152509293925050620096769050565b90506203f480811080620073ac5750603d548111155b15620073d55784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b603e5562007768565b620074586040518060400160405280601c81526020017f6d617846656c6f6e794265747765656e42726561746865426c6f636b0000000081525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b156200750457602081146200748a5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f8401819004810282018101909252828152600091620074cd918585808385018382808284376000920191909152509293925050620096769050565b905080600003620074fb5784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604a5562007768565b620075726040518060400160405280601181526020017039ba30b5b2a43ab1283937ba32b1ba37b960791b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b15620076325760148114620075a45783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b6000620075ec601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096769050565b90506001600160a01b038116620076205784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b6200762b816200967b565b5062007768565b620076996040518060400160405280600a8152602001696d61784e6f646549447360b01b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050620096199050565b15620077455760208114620076cb5783838383604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604080516020601f84018190048102820181019092528281526000916200770e918585808385018382808284376000920191909152509293925050620096769050565b9050806000036200773c5784848484604051630a5a604160e01b8152600401620012e494939291906200a6dd565b604e5562007768565b838383836040516325ee20d560e21b8152600401620012e494939291906200a6dd565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516200779f94939291906200a6dd565b60405180910390a150505050565b60005462010000900460ff1615620077d857604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200780a5760405163b1d02c3d60e01b815260040160405180910390fd5b816000816001600160401b038111156200782857620078286200993b565b60405190808252806020026020018201604052801562007852578160200160208202803683370190505b5090506000805b8381101562007950576200789b8787838181106200787b576200787b6200a266565b9050602002016020810190620078929190620097cc565b603f9062008cf9565b620078b95760405163056e881160e01b815260040160405180910390fd5b60416000888884818110620078d257620078d26200a266565b9050602002016020810190620078e99190620097cc565b6001600160a01b03908116825260208201929092526040016000206002015484519116925082908490839081106200792557620079256200a266565b6001600160a01b039092166020928302919091019091015262007948816200a27c565b905062007859565b50604051634484077560e01b8152612005906344840775906200337d90859088906004016200a2c8565b60608060006200798b603f62009071565b90508085101562007b4f578315620079a45783620079a6565b805b9350600084620079b787846200a298565b11620079cf57620079c986836200a298565b620079d1565b845b9050806001600160401b03811115620079ee57620079ee6200993b565b60405190808252806020026020018201604052801562007a18578160200160208202803683370190505b509350806001600160401b0381111562007a365762007a366200993b565b60405190808252806020026020018201604052801562007a60578160200160208202803683370190505b50925060005b8181101562007b4c5762007a7f6200453882896200a1fb565b85828151811062007a945762007a946200a266565b60200260200101906001600160a01b031690816001600160a01b0316815250506041600086838151811062007acd5762007acd6200a266565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060020160009054906101000a90046001600160a01b031684828151811062007b215762007b216200a266565b6001600160a01b039092166020928302919091019091015262007b44816200a27c565b905062007a66565b50505b9250925092565b60008162007b66603f8262008cf9565b62007b845760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b03166000908152604160205260409020600c015490565b336110011462007bcc57604051630f22c43960e41b81526110016004820152602401620012e4565b60005462010000900460ff161562007bf757604051631785c68160e01b815260040160405180910390fd5b6001600160a01b038082166000908152604360205260409020541662007c1f603f8262008cf9565b62007c3d5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062007c6562015180426200a1d8565b604a546000828152604b60205260409020549192501162007c995760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062007cba9084906200a1fb565b90915550506001600160a01b0384166000908152604460205260409020541580159062007d0f57506001600160a01b038416600090815260446020526040902054429062007d0d9062015180906200a1fb565b105b1562007d2e576040516330abb81d60e21b815260040160405180910390fd5b60008062007d3e85600062008d1c565b915091508162007d6157604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562007db4573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062007dda91906200a211565b905062007de8858362008da4565b84546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562007e2f57600080fd5b505af115801562007e44573d6000803e3d6000fd5b50505050856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600060405162007e88939291906200a22b565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b916200615e916001600160a01b0316908a906004016200a198565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384938493849390929160808401919062007f37906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462007f65906200a162565b801562007fb65780601f1062007f8a5761010080835404028352916020019162007fb6565b820191906000526020600020905b81548152906001019060200180831162007f9857829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462007fe1906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200800f906200a162565b8015620080605780601f10620080345761010080835404028352916020019162008060565b820191906000526020600020905b8154815290600101906020018083116200804257829003601f168201915b505050505081526020016001820180546200807b906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620080a9906200a162565b8015620080fa5780601f10620080ce57610100808354040283529160200191620080fa565b820191906000526020600020905b815481529060010190602001808311620080dc57829003601f168201915b5050505050815260200160028201805462008115906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008143906200a162565b8015620081945780601f10620081685761010080835404028352916020019162008194565b820191906000526020600020905b8154815290600101906020018083116200817657829003601f168201915b50505050508152602001600382018054620081af906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620081dd906200a162565b80156200822e5780601f1062008202576101008083540402835291602001916200822e565b820191906000526020600020905b8154815290600101906020018083116200821057829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620082cd5750505091909252505050606081015160e0820151610100909201519097919650945092505050565b60005462010000900460ff16156200833457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620083665760405163b1d02c3d60e01b815260040160405180910390fd5b6200837062008f12565b6200837d603f8262008cf9565b6200839b5760405163056e881160e01b815260040160405180910390fd5b6000620083a762008f12565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620083da9062015180906200a1fb565b1115620083fa57604051631f92cdbd60e11b815260040160405180910390fd5b6005810180546200840b906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008439906200a162565b80156200848a5780601f106200845e576101008083540402835291602001916200848a565b820191906000526020600020905b8154815290600101906020018083116200846c57829003601f168201915b5050508287525085916005840191508190620084a790826200a713565b5060208201516001820190620084be90826200a713565b5060408201516002820190620084d590826200a713565b5060608201516003820190620084ec90826200a713565b505042600c830155506040516001600160a01b038316907f85d6366b336ade7f106987ec7a8eac1e8799e508aeab045a39d2f63e0dc969d990600090a250505050565b60005462010000900460ff16156200855a57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200858c5760405163b1d02c3d60e01b815260040160405180910390fd5b828114620085ad576040516341abc80160e01b815260040160405180910390fd5b60005b838110156200861e576200860b858583818110620085d257620085d26200a266565b9050602002016020810190620085e99190620097cc565b848484818110620085fe57620085fe6200a266565b905060200201356200950d565b62008616816200a27c565b9050620085b0565b5050505050565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162008690906200a162565b80601f0160208091040260200160405190810160405280929190818152602001828054620086be906200a162565b80156200870f5780601f10620086e3576101008083540402835291602001916200870f565b820191906000526020600020905b815481529060010190602001808311620086f157829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200873a906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008768906200a162565b8015620087b95780601f106200878d57610100808354040283529160200191620087b9565b820191906000526020600020905b8154815290600101906020018083116200879b57829003601f168201915b50505050508152602001600182018054620087d4906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008802906200a162565b8015620088535780601f10620088275761010080835404028352916020019162008853565b820191906000526020600020905b8154815290600101906020018083116200883557829003601f168201915b505050505081526020016002820180546200886e906200a162565b80601f01602080910402602001604051908101604052809291908181526020018280546200889c906200a162565b8015620088ed5780601f10620088c157610100808354040283529160200191620088ed565b820191906000526020600020905b815481529060010190602001808311620088cf57829003601f168201915b5050505050815260200160038201805462008908906200a162565b80601f016020809104026020016040519081016040528092919081815260200182805462008936906200a162565b8015620089875780601f106200895b5761010080835404028352916020019162008987565b820191906000526020600020905b8154815290600101906020018083116200896957829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162008a265750505091909252505050604001519392505050565b600062008a5e603f8462008cf9565b62008a7c5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038381166000908152604160205260409081902060020154905163aa1966cd60e01b81526004810185905291169063aa1966cd9060240162005aa0565b60005462010000900460ff161562008aeb57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562008b1d5760405163b1d02c3d60e01b815260040160405180910390fd5b62008b2762008f12565b62008b34603f8262008cf9565b62008b525760405163056e881160e01b815260040160405180910390fd5b600062008b5e62008f12565b905062008b6f81878787876200922c565b62008b8d57604051631647e3cb60e11b815260040160405180910390fd5b60006001600160a01b03166045878760405162008bac9291906200a1b2565b908152604051908190036020019020546001600160a01b03161462008be4576040516311fdb94760e01b815260040160405180910390fd5b6001600160a01b0381166000908152604160205260409020600c810154429062008c139062015180906200a1fb565b111562008c3357604051631f92cdbd60e11b815260040160405180910390fd5b4260468260040160405162008c4991906200a7db565b908152604051908190036020019020556004810162008c6a8789836200a3c6565b5042600c820155604051829060459062008c88908a908a906200a1b2565b90815260405190819003602001812080546001600160a01b039384166001600160a01b0319909116179055908316907f783156582145bd0ff7924fae6953ba054cf1233eb60739a200ddb10de068ff0d9062008ce8908a908a906200a697565b60405180910390a250505050505050565b6001600160a01b0381166000908152600183016020526040812054151562005ae4565b6000806000848460405160200162008d369291906200a859565b60408051601f1981840301815291815281516020928301206000818152604c9093529120549091504281111562008d7657600080935093505050620026aa565b603e5462008d8590426200a1fb565b6000928352604c60205260409092208290555060019590945092505050565b6000600162008db4603f62009071565b62008dc091906200a298565b604954108015915062008e0c5760018301546040516001600160a01b03909116907f2afdc18061ac21cff7d9f11527ab9c8dec6fabd4edf6f894ed634bebd6a20d4590600090a2505050565b82600b015482111562008e2157600b83018290555b600a83015460ff166200649c57600a8301805460ff191660019081179091556049805460009062008e549084906200a1fb565b909155505060018301546040516001600160a01b03909116907f4905ac32602da3fb8b4b7b00c285e5fc4c6c2308cc908b4a1e4e9625a29c90a390600090a2505050565b336000908152604360205260408120546001600160a01b03161580159062008ecd575033600090815260446020526040902054155b1562008ef05750336000908152604360205260409020546001600160a01b031690565b62008efa62008f12565b905090565b604e5460000362008f10576005604e555b565b336000908152604d60205260408120546001600160a01b03161562008f4e5750336000908152604d60205260409020546001600160a01b031690565b503390565b6001600160a01b0381166000908152604160205260409020600a81015460ff161562008f7d575050565b6036546002820154604051630913db4760e01b81526001600160a01b03858116600483015290911690630913db4790602401602060405180830381865afa15801562008fcd573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008ff391906200a211565b1015620067f7576200901581603d54426200900f91906200a1fb565b62008da4565b80546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b1580156200905c57600080fd5b505af115801562006308573d6000803e3d6000fd5b600062005ae7825490565b600062005ae48383620096e7565b600080829050600381511080620090a2575060098151115b15620090b15750600092915050565b604181600081518110620090c957620090c96200a266565b016020015160f81c1080620090fb5750605a81600081518110620090f157620090f16200a266565b016020015160f81c115b156200910a5750600092915050565b60015b8151811015620092225760308282815181106200912e576200912e6200a266565b016020015160f81c10806200915f575060398282815181106200915557620091556200a266565b016020015160f81c115b8015620091af575060418282815181106200917e576200917e6200a266565b016020015160f81c1080620091af5750605a828281518110620091a557620091a56200a266565b016020015160f81c115b8015620091ff57506061828281518110620091ce57620091ce6200a266565b016020015160f81c1080620091ff5750607a828281518110620091f557620091f56200a266565b016020015160f81c115b156200920f575060009392505050565b6200921a816200a27c565b90506200910d565b5060019392505050565b600060308414158062009240575060608214155b156200924f5750600062009353565b6000868686466040516020016200926a94939291906200a8a3565b60408051808303601f1901815282825280516020918201208184528383019092529092506000919060208201818036833701905050905081602082015260008186868a8a604051602001620092c49594939291906200a8d0565b60408051808303601f190181526001808452838301909252925060009190602082018180368337019050509050815160016020830182602086016066600019fa6200930e57600080fd5b506000816000815181106200932757620093276200a266565b016020015160f81c905060018114620093495760009550505050505062009353565b6001955050505050505b95945050505050565b60008061200361dead604051620093739062009786565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f080158015620093b6573d6000803e3d6000fd5b509050806001600160a01b031663f399e22e3486866040518463ffffffff1660e01b8152600401620093ea9291906200a908565b6000604051808303818588803b1580156200940457600080fd5b505af115801562009419573d6000803e3d6000fd5b50506040516001600160a01b038086169450881692507fd481492e4e93bb36b4c12a5af93f03be3bf04b454dfbc35dd2663fa26f44d5b09150600090a39392505050565b600062005ae4836001600160a01b03841662009714565b600054610100900460ff16620094e15760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620012e4565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b816200951b603f8262008cf9565b620095395760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03838116600090815260416020526040808220600201549051635569f64b60e11b8152336004820152602481018690529192169063aad3ec96906044016020604051808303816000875af11580156200959d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620095c391906200a211565b9050336001600160a01b0316846001600160a01b03167ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd3992683836040516200960b91815260200190565b60405180910390a350505050565b6000816040516020016200962e91906200a92e565b60405160208183030381529060405280519060200120836040516020016200965791906200a92e565b6040516020818303038152906040528051906020012014905092915050565b015190565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008260000182815481106200970157620097016200a266565b9060005260206000200154905092915050565b60008181526001830160205260408120546200975d5750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562005ae7565b50600062005ae7565b50805460008255906000526020600020908101906200190f919062009794565b610e96806200a94d83390190565b5b80821115620097ab576000815560010162009795565b5090565b80356001600160a01b0381168114620097c757600080fd5b919050565b600060208284031215620097df57600080fd5b62005ae482620097af565b60008083601f840112620097fd57600080fd5b5081356001600160401b038111156200981557600080fd5b602083019150836020828501011115620026aa57600080fd5b600080602083850312156200984257600080fd5b82356001600160401b038111156200985957600080fd5b6200986785828601620097ea565b90969095509350505050565b6000806000604084860312156200988957600080fd5b833560ff811681146200989b57600080fd5b925060208401356001600160401b03811115620098b757600080fd5b620098c586828701620097ea565b9497909650939450505050565b60005b83811015620098ef578181015183820152602001620098d5565b50506000910152565b6000815180845262009912816020860160208601620098d2565b601f01601f19169290920160200192915050565b60208152600062005ae46020830184620098f8565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200997657620099766200993b565b60405290565b60006001600160401b03808411156200999957620099996200993b565b604051601f8501601f19908116603f01168101908282118183101715620099c457620099c46200993b565b81604052809350858152868686011115620099de57600080fd5b858560208301376000602087830101525050509392505050565b60006020828403121562009a0b57600080fd5b81356001600160401b0381111562009a2257600080fd5b8201601f8101841362009a3457600080fd5b62009a45848235602084016200997c565b949350505050565b60008083601f84011262009a6057600080fd5b5081356001600160401b0381111562009a7857600080fd5b6020830191508360208260051b8501011115620026aa57600080fd5b6000806020838503121562009aa857600080fd5b82356001600160401b0381111562009abf57600080fd5b620098678582860162009a4d565b600081518084526020808501945080840160005b8381101562009b085781516001600160a01b03168752958201959082019060010162009ae1565b509495945050505050565b60408152600062009b28604083018562009acd565b6020838203818501528185518084528284019150828160051b8501018388016000805b8481101562009ba257878403601f19018652825180518086529088019088860190845b8181101562009b8c5783518352928a0192918a019160010162009b6e565b5050968801969450509186019160010162009b4b565b50919a9950505050505050505050565b6000806040838503121562009bc657600080fd5b62009bd183620097af565b946020939093013593505050565b80358015158114620097c757600080fd5b6000806000806080858703121562009c0757600080fd5b62009c1285620097af565b935062009c2260208601620097af565b92506040850135915062009c396060860162009bdf565b905092959194509250565b6001600160401b03811681146200190f57600080fd5b60006020828403121562009c6d57600080fd5b813562009c7a8162009c44565b9392505050565b6000806040838503121562009c9557600080fd5b50508035926020909101359150565b60808152600062009cb9608083018762009acd565b82810360208481019190915286518083528782019282019060005b8181101562009cf25784518352938301939183019160010162009cd4565b5050848103604086015286518082528282019350600581901b8201830183890160005b8381101562009d4757601f1985840301875262009d34838351620098f8565b9686019692509085019060010162009d15565b5050809550505050505082606083015295945050505050565b600080600080600080600087890360e081121562009d7d57600080fd5b62009d8889620097af565b975060208901356001600160401b038082111562009da557600080fd5b62009db38c838d01620097ea565b909950975060408b013591508082111562009dcd57600080fd5b62009ddb8c838d01620097ea565b90975095508591506060605f198401121562009df657600080fd5b60608b01945060c08b013592508083111562009e1157600080fd5b505088016080818b03121562009e2657600080fd5b8091505092959891949750929550565b6000806040838503121562009e4a57600080fd5b62009e5583620097af565b915062009e656020840162009bdf565b90509250929050565b60208152600082516080602084015262009e8c60a0840182620098f8565b90506020840151601f198085840301604086015262009eac8383620098f8565b9250604086015191508085840301606086015262009ecb8383620098f8565b9250606086015191508085840301608086015250620093538282620098f8565b6000806000806040858703121562009f0257600080fd5b84356001600160401b038082111562009f1a57600080fd5b62009f2888838901620097ea565b9096509450602087013591508082111562009f4257600080fd5b5062009f5187828801620097ea565b95989497509550505050565b60008060006040848603121562009f7357600080fd5b83356001600160401b0381111562009f8a57600080fd5b62009f988682870162009a4d565b909450925062009fad905060208501620097af565b90509250925092565b60608152600062009fcb606083018662009acd565b828103602084015262009fdf818662009acd565b915050826040830152949350505050565b600082601f8301126200a00257600080fd5b62005ae4838335602085016200997c565b6000602082840312156200a02657600080fd5b81356001600160401b03808211156200a03e57600080fd5b90830190608082860312156200a05357600080fd5b6200a05d62009951565b8235828111156200a06d57600080fd5b6200a07b8782860162009ff0565b8252506020830135828111156200a09157600080fd5b6200a09f8782860162009ff0565b6020830152506040830135828111156200a0b857600080fd5b6200a0c68782860162009ff0565b6040830152506060830135828111156200a0df57600080fd5b6200a0ed8782860162009ff0565b60608301525095945050505050565b600080600080604085870312156200a11357600080fd5b84356001600160401b03808211156200a12b57600080fd5b6200a1398883890162009a4d565b909650945060208701359150808211156200a15357600080fd5b5062009f518782880162009a4d565b600181811c908216806200a17757607f821691505b602082108103620020dc57634e487b7160e01b600052602260045260246000fd5b6001600160a01b0392831681529116602082015260400190565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b6000826200a1f657634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562005ae75762005ae76200a1c2565b6000602082840312156200a22457600080fd5b5051919050565b8381526020810183905260608101600383106200a25857634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200a291576200a2916200a1c2565b5060010190565b8181038181111562005ae75762005ae76200a1c2565b808202811582820484141762005ae75762005ae76200a1c2565b6040815260006200a2dd604083018562009acd565b905060018060a01b03831660208301529392505050565b6001600160401b038281168282160390808211156200a317576200a3176200a1c2565b5092915050565b6000808335601e198436030181126200a33657600080fd5b8301803591506001600160401b038211156200a35157600080fd5b602001915036819003821315620026aa57600080fd5b601f8211156200649c57600081815260208120601f850160051c810160208610156200a3905750805b601f850160051c820191505b8181101562006308578281556001016200a39c565b600019600383901b1c191660019190911b1790565b6001600160401b038311156200a3e0576200a3e06200993b565b6200a3f8836200a3f183546200a162565b836200a367565b6000601f8411600181146200a42b57600085156200a4165750838201355b6200a42286826200a3b1565b8455506200861e565b600083815260209020601f19861690835b828110156200a45e57868501358255602094850194600190920191016200a43c565b50868210156200a47c5760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6200a49a82836200a31e565b6001600160401b038111156200a4b4576200a4b46200993b565b6200a4cc816200a4c585546200a162565b856200a367565b6000601f8211600181146200a4ff57600083156200a4ea5750838201355b6200a4f684826200a3b1565b8655506200a55c565b600085815260209020601f19841690835b828110156200a53257868501358255602094850194600190920191016200a510565b50848210156200a5505760001960f88660031b161c19848701351681555b505060018360011b0185555b505050506200a56f60208301836200a31e565b6200a57f8183600186016200a3c6565b50506200a59060408301836200a31e565b6200a5a08183600286016200a3c6565b50506200a5b160608301836200a31e565b6200a5c18183600386016200a3c6565b50505050565b81356200a5d48162009c44565b6001600160401b03811690508154816001600160401b0319821617835560208401356200a6018162009c44565b6fffffffffffffffff0000000000000000604091821b166fffffffffffffffffffffffffffffffff198316841781178555908501356200a6418162009c44565b6001600160c01b0319929092169092179190911760809190911b67ffffffffffffffff60801b1617905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600062009a456020830184866200a66e565b634e487b7160e01b600052603160045260246000fd5b6000816200a6d5576200a6d56200a1c2565b506000190190565b6040815260006200a6f36040830186886200a66e565b82810360208401526200a7088185876200a66e565b979650505050505050565b81516001600160401b038111156200a72f576200a72f6200993b565b6200a747816200a74084546200a162565b846200a367565b602080601f8311600181146200a77b57600084156200a7665750858301515b6200a77285826200a3b1565b86555062006308565b600085815260208120601f198616915b828110156200a7ac578886015182559484019460019091019084016200a78b565b50858210156200a7cb5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200a7eb816200a162565b600182811680156200a80657600181146200a81c576200a84d565b60ff19841687528215158302870194506200a84d565b8760005260208060002060005b858110156200a8445781548a8201529084019082016200a829565b50505082870194505b50929695505050505050565b6bffffffffffffffffffffffff198360601b1681526000600383106200a88f57634e487b7160e01b600052602160045260246000fd5b5060f89190911b6014820152601501919050565b6bffffffffffffffffffffffff198560601b16815282846014830137601492019182015260340192915050565b600086516200a8e4818460208b01620098d2565b82018587823760009086019081528385823760009301928352509095945050505050565b6001600160a01b038316815260406020820181905260009062009a4590830184620098f8565b600082516200a942818460208701620098d2565b919091019291505056fe608060405260405162000e9638038062000e96833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e6f60279139620002f8565b9392505050565b60006200018060008051602062000e4f83398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e4f83398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61087580620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/pasteur/rialto/GovernorContract b/core/systemcontracts/pasteur/rialto/GovernorContract new file mode 100644 index 0000000000..d8ac9bcb87 --- /dev/null +++ b/core/systemcontracts/pasteur/rialto/GovernorContract @@ -0,0 +1 @@ +6080604052600436106103e85760003560e01c80637b3c71d311610208578063c28bc2fa11610118578063deaaa7cc116100ab578063ece40cc11161007a578063ece40cc114610e19578063f23a6e6114610e39578063f8ce560a14610e65578063fc0c546a14610e85578063fe0d94c114610ea657600080fd5b8063deaaa7cc14610cda578063e23a9a5214610d0e578063ea0217cf14610dd9578063eb9019d414610df957600080fd5b8063da95691a116100e7578063da95691a14610c2f578063dd42a1dd14610c4f578063dd4e2ba514610c74578063ddf0b00914610cba57600080fd5b8063c28bc2fa14610bbd578063c59057e414610bd0578063d07f91e914610bf0578063d33219b414610c1057600080fd5b8063a7713a701161019b578063b187bd261161016a578063b187bd2614610b23578063b58131b014610b41578063bc197c8114610b56578063c01f9e3714610b82578063c170ec0b14610ba257600080fd5b8063a7713a7014610aae578063a890c91014610ac3578063ab58fb8e14610ae3578063ac43175114610b0357600080fd5b806384b0196e116101d757806384b0196e14610a2657806391ddadf414610a4e57806397c3d33414610a7a5780639a802a6d14610a8e57600080fd5b80637b3c71d3146109bc5780637d5e81e2146109dc5780638129fc1c146109fc5780638456cb5914610a1157600080fd5b806332b8113e116103035780634838d1651161029657806354fd4d501161026557806354fd4d5014610912578063567813881461093c5780635f398a141461095c57806360c4247f1461097c57806370b0f6601461099c57600080fd5b80634838d1651461087c5780634a49ac4c146108ac5780634bf5d7e9146108cc578063533ddd14146108e157600080fd5b806340e58ee5116102d257806340e58ee5146107d1578063417c73a7146107f15780634385963214610811578063452115d61461085c57600080fd5b806332b8113e146107455780633932abb11461076e5780633bccf4fd146107845780633e4f49e6146107a457600080fd5b8063150b7a021161037b5780632656227d1161034a5780632656227d146106975780632d63f693146106aa5780632fe3e261146106e1578063328dd9821461071557600080fd5b8063150b7a02146105f0578063160cbed71461063457806317977c611461065457806324bc1a641461068257600080fd5b8063046f7da2116103b7578063046f7da21461054357806306f3f9e61461055857806306fdde0314610578578063143489d01461059a57600080fd5b8063013cf08b1461045857806301ffc9a7146104d357806302a251a314610503578063034201811461052357600080fd5b3661045357306103f6610eb9565b6001600160a01b0316146104515760405162461bcd60e51b815260206004820152601f60248201527f476f7665726e6f723a206d7573742073656e6420746f206578656375746f720060448201526064015b60405180910390fd5b005b600080fd5b34801561046457600080fd5b50610478610473366004615c9f565b610ed3565b604080519a8b526001600160a01b0390991660208b0152978901969096526060880194909452608087019290925260a086015260c085015260e084015215156101008301521515610120820152610140015b60405180910390f35b3480156104df57600080fd5b506104f36104ee366004615cb8565b610f8e565b60405190151581526020016104ca565b34801561050f57600080fd5b50610195545b6040519081526020016104ca565b34801561052f57600080fd5b5061051561053e366004615dfe565b610f9f565b34801561054f57600080fd5b50610451611097565b34801561056457600080fd5b50610451610573366004615c9f565b611127565b34801561058457600080fd5b5061058d6111b2565b6040516104ca9190615ef4565b3480156105a657600080fd5b506105d86105b5366004615c9f565b60009081526101636020526040902054600160401b90046001600160a01b031690565b6040516001600160a01b0390911681526020016104ca565b3480156105fc57600080fd5b5061061b61060b366004615f1c565b630a85bd0160e11b949350505050565b6040516001600160e01b031990911681526020016104ca565b34801561064057600080fd5b5061051561064f3660046160f3565b611245565b34801561066057600080fd5b5061051561066f366004616182565b6102c36020526000908152604090205481565b34801561068e57600080fd5b50610515611330565b6105156106a53660046160f3565b611356565b3480156106b657600080fd5b506105156106c5366004615c9f565b600090815261016360205260409020546001600160401b031690565b3480156106ed57600080fd5b506105157fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af8881565b34801561072157600080fd5b50610735610730366004615c9f565b611449565b6040516104ca9493929190616268565b34801561075157600080fd5b5061028f546040516001600160401b0390911681526020016104ca565b34801561077a57600080fd5b5061019454610515565b34801561079057600080fd5b5061051561079f3660046162b5565b6116db565b3480156107b057600080fd5b506107c46107bf366004615c9f565b611751565b6040516104ca9190616319565b3480156107dd57600080fd5b506104516107ec366004615c9f565b61175c565b3480156107fd57600080fd5b5061045161080c366004616182565b611787565b34801561081d57600080fd5b506104f361082c366004616341565b60008281526101c6602090815260408083206001600160a01b038516845260080190915290205460ff1692915050565b34801561086857600080fd5b506105156108773660046160f3565b611808565b34801561088857600080fd5b506104f3610897366004616182565b60016020526000908152604090205460ff1681565b3480156108b857600080fd5b506104516108c7366004616182565b611816565b3480156108d857600080fd5b5061058d611891565b3480156108ed57600080fd5b506104f36108fc366004616182565b6102c16020526000908152604090205460ff1681565b34801561091e57600080fd5b506040805180820190915260018152603160f81b602082015261058d565b34801561094857600080fd5b50610515610957366004616371565b61193e565b34801561096857600080fd5b5061051561097736600461639d565b611967565b34801561098857600080fd5b50610515610997366004615c9f565b6119b1565b3480156109a857600080fd5b506104516109b7366004615c9f565b611a66565b3480156109c857600080fd5b506105156109d7366004616420565b611aee565b3480156109e857600080fd5b506105156109f7366004616479565b611b40565b348015610a0857600080fd5b50610451611c5b565b348015610a1d57600080fd5b50610451611e89565b348015610a3257600080fd5b50610a3b611f1f565b6040516104ca9796959493929190616519565b348015610a5a57600080fd5b50610a63611fbd565b60405165ffffffffffff90911681526020016104ca565b348015610a8657600080fd5b506064610515565b348015610a9a57600080fd5b50610515610aa936600461657b565b612031565b348015610aba57600080fd5b50610515612048565b348015610acf57600080fd5b50610451610ade366004616182565b612075565b348015610aef57600080fd5b50610515610afe366004615c9f565b6120fd565b348015610b0f57600080fd5b50610451610b1e3660046165d3565b612199565b348015610b2f57600080fd5b5060005462010000900460ff166104f3565b348015610b4d57600080fd5b506105156128de565b348015610b6257600080fd5b5061061b610b71366004616632565b63bc197c8160e01b95945050505050565b348015610b8e57600080fd5b50610515610b9d366004615c9f565b6128ea565b348015610bae57600080fd5b506102c2546104f39060ff1681565b610451610bcb3660046166c5565b6128f5565b348015610bdc57600080fd5b50610515610beb3660046160f3565b612a05565b348015610bfc57600080fd5b50610451610c0b366004616708565b612a3f565b348015610c1c57600080fd5b5061022b546001600160a01b03166105d8565b348015610c3b57600080fd5b50610515610c4a366004616731565b612ac7565b348015610c5b57600080fd5b50600054630100000090046001600160a01b03166105d8565b348015610c8057600080fd5b5060408051808201909152601a81527f737570706f72743d627261766f2671756f72756d3d627261766f000000000000602082015261058d565b348015610cc657600080fd5b50610451610cd5366004615c9f565b612b4e565b348015610ce657600080fd5b506105157f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f81565b348015610d1a57600080fd5b50610da9610d29366004616341565b60408051606081018252600080825260208201819052918101919091525060009182526101c6602090815260408084206001600160a01b0393909316845260089092018152918190208151606081018352905460ff8082161515835261010082041693820193909352620100009092046001600160601b03169082015290565b6040805182511515815260208084015160ff1690820152918101516001600160601b0316908201526060016104ca565b348015610de557600080fd5b50610451610df4366004615c9f565b612b71565b348015610e0557600080fd5b50610515610e143660046167d2565b612bf9565b348015610e2557600080fd5b50610451610e34366004615c9f565b612c1a565b348015610e4557600080fd5b5061061b610e543660046167fe565b63f23a6e6160e01b95945050505050565b348015610e7157600080fd5b50610515610e80366004615c9f565b612ca2565b348015610e9157600080fd5b506101f8546105d8906001600160a01b031681565b610451610eb4366004615c9f565b612d31565b6000610ece61022b546001600160a01b031690565b905090565b8060008080808080808080610ee78a6120fd565b60008c815261016360205260409020549098506001600160401b03169650610f0e8b6128ea565b60008c81526101c66020526040812080546005820154600683015460078401546001600160a01b039093169e50949a509850929650919450610f4f8d611751565b90506002816007811115610f6557610f65616303565b1493506007816007811115610f7c57610f7c616303565b14925050509193959799509193959799565b6000610f9982612d54565b92915050565b60008061104361103b7fb3b3f3b703cd84ce352197dcff232b1b5d3cfb2025ce47cf04742d0651f1af888c8c8c8c604051610fdb929190616866565b60405180910390208b80519060200120604051602001611020959493929190948552602085019390935260ff9190911660408401526060830152608082015260a00190565b60405160208183030381529060405280519060200120612d79565b868686612da6565b90506110898a828b8b8b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508d9250612dc4915050565b9a9950505050505050505050565b600054630100000090046001600160a01b031633146110c9576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff166110f257604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b61112f610eb9565b6001600160a01b0316336001600160a01b03161461115f5760405162461bcd60e51b815260040161044890616876565b30611168610eb9565b6001600160a01b0316146111a65760008036604051611188929190616866565b604051809103902090505b8061119f610164612e67565b0361119357505b6111af81612ee6565b50565b606061016280546111c2906168ad565b80601f01602080910402602001604051908101604052809291908181526020018280546111ee906168ad565b801561123b5780601f106112105761010080835404028352916020019161123b565b820191906000526020600020905b81548152906001019060200180831161121e57829003601f168201915b5050505050905090565b6000805462010000900460ff161561127057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156112a15760405163b1d02c3d60e01b815260040160405180910390fd5b60005b855181101561131a576102c160008783815181106112c4576112c46168e7565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1661130857604051630b094f2760e31b815260040160405180910390fd5b8061131281616913565b9150506112a4565b5061132785858585613057565b95945050505050565b6000610ece600161133f611fbd565b611349919061692c565b65ffffffffffff16612ca2565b60008061136586868686612a05565b9050600061137282611751565b9050600481600781111561138857611388616303565b14806113a5575060058160078111156113a3576113a3616303565b145b6113c15760405162461bcd60e51b815260040161044890616952565b6000828152610163602052604090819020600201805460ff19166001179055517f712ae1383f79ac853f8d882153778e0260ef8f03b504e2866e0593e04d2b291f906114109084815260200190565b60405180910390a1611425828888888861325c565b61143282888888886132fd565b61143f82888888886133df565b5095945050505050565b60608060608060006101c66000878152602001908152602001600020905080600101816002018260030183600401838054806020026020016040519081016040528092919081815260200182805480156114cc57602002820191906000526020600020905b81546001600160a01b031681526001909101906020018083116114ae575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561151e57602002820191906000526020600020905b81548152602001906001019080831161150a575b5050505050925081805480602002602001604051908101604052809291908181526020016000905b828210156115f2578382906000526020600020018054611565906168ad565b80601f0160208091040260200160405190810160405280929190818152602001828054611591906168ad565b80156115de5780601f106115b3576101008083540402835291602001916115de565b820191906000526020600020905b8154815290600101906020018083116115c157829003601f168201915b505050505081526020019060010190611546565b50505050915080805480602002602001604051908101604052809291908181526020016000905b828210156116c5578382906000526020600020018054611638906168ad565b80601f0160208091040260200160405190810160405280929190818152602001828054611664906168ad565b80156116b15780601f10611686576101008083540402835291602001916116b1565b820191906000526020600020905b81548152906001019060200180831161169457829003601f168201915b505050505081526020019060010190611619565b5050505090509450945094509450509193509193565b604080517f150214d74d59b7d1e90c73fc22ef3d991dd0a76b046543d4d80ab92d2a50328f602082015290810186905260ff8516606082015260009081906117299061103b90608001611020565b90506117468782886040518060200160405280600081525061341a565b979650505050505050565b6000610f998261343d565b60008060008061176b8561358a565b935093509350935061177f84848484611808565b505050505050565b600054630100000090046001600160a01b031633146117b9576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60006113278585858561381b565b600054630100000090046001600160a01b03163314611848576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b6101f85460408051634bf5d7e960e01b815290516060926001600160a01b031691634bf5d7e99160048083019260009291908290030181865afa9250505080156118fd57506040513d6000823e601f3d908101601f191682016040526118fa9190810190616993565b60015b611939575060408051808201909152601d81527f6d6f64653d626c6f636b6e756d6265722666726f6d3d64656661756c74000000602082015290565b919050565b60008033905061195f8482856040518060200160405280600081525061341a565b949350505050565b60008033905061174687828888888080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508a9250612dc4915050565b61025e546000908082036119ca57505061025d54919050565b600061025e6119da600184616a00565b815481106119ea576119ea6168e7565b60009182526020918290206040805180820190915291015463ffffffff8116808352600160201b9091046001600160e01b03169282019290925291508410611a4057602001516001600160e01b03169392505050565b611a55611a4c856138e6565b61025e9061394f565b6001600160e01b0316949350505050565b611a6e610eb9565b6001600160a01b0316336001600160a01b031614611a9e5760405162461bcd60e51b815260040161044890616876565b30611aa7610eb9565b6001600160a01b031614611ae55760008036604051611ac7929190616866565b604051809103902090505b80611ade610164612e67565b03611ad257505b6111af81613a02565b600080339050611b3686828787878080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061341a92505050565b9695505050505050565b6000805462010000900460ff1615611b6b57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615611b9c5760405163b1d02c3d60e01b815260040160405180910390fd5b611ba4613a45565b3360009081526102c360205260409020548015611c19576000611bc682611751565b90506001816007811115611bdc57611bdc616303565b1480611bf957506000816007811115611bf757611bf7616303565b145b15611c175760405163867f3ee560e01b815260040160405180910390fd5b505b825160208401206000611c2e88888885612a05565b3360009081526102c3602052604090208190559050611c4f88888888613af0565b98975050505050505050565b600054610100900460ff1615808015611c7b5750600054600160ff909116105b80611c955750303b158015611c95575060005460ff166001145b611cf85760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401610448565b6000805460ff191660011790558015611d1b576000805461ff0019166101001790555b334114611d3b5760405163022d8c9560e31b815260040160405180910390fd5b3a15611d5a576040516383f1b1d360e01b815260040160405180910390fd5b611d866040518060400160405280600b81526020016a2129a1a3b7bb32b93737b960a91b815250613b58565b611db0611d9560036000616a29565b611da160036078616a29565b680ad78ebc5ac6200000613baf565b611db8613be6565b611dc3612005613c0d565b611dce612006613c3d565b611dd8600a613c6d565b611dec611de76003603c616a29565b613c9d565b6110076000526102c16020527f2f832952f0ef896b8c8edd6d16a2e4f2591a90375e33021e3b9ff197f3793fc0805460ff19166001179055611e417304d63abcd2b9b1baa327f2dda0f873f197ccd186613ccd565b80156111af576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b600054630100000090046001600160a01b03163314611ebb576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1615611ee557604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b6000606080600080600060606098546000801b148015611f3f5750609954155b611f835760405162461bcd60e51b81526020600482015260156024820152741152540dcc4c8e88155b9a5b9a5d1a585b1a5e9959605a1b6044820152606401610448565b611f8b613d20565b611f93613d2f565b60408051600080825260208201909252600f60f81b9b939a50919850469750309650945092509050565b6101f854604080516324776b7d60e21b815290516000926001600160a01b0316916391ddadf49160048083019260209291908290030181865afa925050508015612024575060408051601f3d908101601f1916820190925261202191810190616a4b565b60015b61193957610ece43613d3e565b600061203e848484613da5565b90505b9392505050565b61025e546000901561206d5761205f61025e613e1c565b6001600160e01b0316905090565b5061025d5490565b61207d610eb9565b6001600160a01b0316336001600160a01b0316146120ad5760405162461bcd60e51b815260040161044890616876565b306120b6610eb9565b6001600160a01b0316146120f457600080366040516120d6929190616866565b604051809103902090505b806120ed610164612e67565b036120e157505b6111af81613e4c565b61022b54600082815261022c602052604080822054905163d45c443560e01b81526004810191909152909182916001600160a01b039091169063d45c443590602401602060405180830381865afa15801561215c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121809190616a73565b9050806001146121905780612041565b60009392505050565b33611007146121bf57604051630f22c43960e41b81526110076004820152602401610448565b6122256040518060400160405280600b81526020016a766f74696e6744656c617960a81b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eb79050565b156122da57602081146122535783838383604051630a5a604160e01b81526004016104489493929190616ab5565b604080516020601f8401819004810282018101909252828152600091612294918585808385018382808284376000920191909152509293925050613f109050565b90508015806122a557506201518081115b156122cb5784848484604051630a5a604160e01b81526004016104489493929190616ab5565b6122d481613a02565b5061289b565b6123416040518060400160405280600c81526020016b1d9bdd1a5b99d4195c9a5bd960a21b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eb79050565b156123f0576020811461236f5783838383604051630a5a604160e01b81526004016104489493929190616ab5565b604080516020601f84018190048102820181019092528281526000916123b0918585808385018382808284376000920191909152509293925050613f109050565b90508015806123c1575062278d0081115b156123e75784848484604051630a5a604160e01b81526004016104489493929190616ab5565b6122d481613f15565b61245c604051806040016040528060118152602001701c1c9bdc1bdcd85b151a1c995cda1bdb19607a1b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eb79050565b15612512576020811461248a5783838383604051630a5a604160e01b81526004016104489493929190616ab5565b604080516020601f84018190048102820181019092528281526000916124cb918585808385018382808284376000920191909152509293925050613f109050565b90508015806124e3575069021e19e0c9bab240000081115b156125095784848484604051630a5a604160e01b81526004016104489493929190616ab5565b6122d481613fb8565b61257c6040518060400160405280600f81526020016e38bab7b93ab6a73ab6b2b930ba37b960891b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eb79050565b1561262b57602081146125aa5783838383604051630a5a604160e01b81526004016104489493929190616ab5565b604080516020601f84018190048102820181019092528281526000916125eb918585808385018382808284376000920191909152509293925050613f109050565b905060058110806125fc5750601481115b156126225784848484604051630a5a604160e01b81526004016104489493929190616ab5565b6122d481612ee6565b61269a604051806040016040528060148152602001736d696e506572696f64416674657251756f72756d60601b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eb79050565b1561276057600881146126c85783838383604051630a5a604160e01b81526004016104489493929190616ab5565b600061270e600884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613f109050565b90506001600160401b038116158061273157506202a300816001600160401b0316115b156127575784848484604051630a5a604160e01b81526004016104489493929190616ab5565b6122d481613ffb565b6127cc6040518060400160405280601181526020017033b7bb32b93737b9283937ba32b1ba37b960791b81525085858080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613eb79050565b1561287a57601481146127fa5783838383604051630a5a604160e01b81526004016104489493929190616ab5565b6000612840601484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509293925050613f109050565b90506001600160a01b0381166128715784848484604051630a5a604160e01b81526004016104489493929190616ab5565b6122d481614067565b838383836040516325ee20d560e21b81526004016104489493929190616ab5565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516128d09493929190616ab5565b60405180910390a150505050565b6000610ece6101965490565b6000610f99826140d3565b6128fd610eb9565b6001600160a01b0316336001600160a01b03161461292d5760405162461bcd60e51b815260040161044890616876565b30612936610eb9565b6001600160a01b0316146129745760008036604051612956929190616866565b604051809103902090505b8061296d610164612e67565b0361296157505b600080856001600160a01b0316858585604051612992929190616866565b60006040518083038185875af1925050503d80600081146129cf576040519150601f19603f3d011682016040523d82523d6000602084013e6129d4565b606091505b50915091506129fc8282604051806060016040528060288152602001616f1260289139614111565b50505050505050565b600084848484604051602001612a1e9493929190616adc565b60408051601f19818403018152919052805160209091012095945050505050565b612a47610eb9565b6001600160a01b0316336001600160a01b031614612a775760405162461bcd60e51b815260040161044890616876565b30612a80610eb9565b6001600160a01b031614612abe5760008036604051612aa0929190616866565b604051809103902090505b80612ab7610164612e67565b03612aab57505b6111af81613ffb565b60008251845114612b2b5760405162461bcd60e51b815260206004820152602860248201527f476f7665726e6f72427261766f3a20696e76616c6964207369676e61747572656044820152670e640d8cadccee8d60c31b6064820152608401610448565b612b3933878787878761412a565b611b368686612b4887876141e8565b85611b40565b600080600080612b5d8561358a565b935093509350935061177f84848484611245565b612b79610eb9565b6001600160a01b0316336001600160a01b031614612ba95760405162461bcd60e51b815260040161044890616876565b30612bb2610eb9565b6001600160a01b031614612bf05760008036604051612bd2929190616866565b604051809103902090505b80612be9610164612e67565b03612bdd57505b6111af81613f15565b60006120418383612c1560408051602081019091526000815290565b613da5565b612c22610eb9565b6001600160a01b0316336001600160a01b031614612c525760405162461bcd60e51b815260040161044890616876565b30612c5b610eb9565b6001600160a01b031614612c995760008036604051612c7b929190616866565b604051809103902090505b80612c92610164612e67565b03612c8657505b6111af81613fb8565b60006064612caf836119b1565b6101f854604051632394e7a360e21b8152600481018690526001600160a01b0390911690638e539e8c90602401602060405180830381865afa158015612cf9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612d1d9190616a73565b612d279190616b27565b610f999190616a29565b600080600080612d408561358a565b935093509350935061177f84848484611356565b60006001600160e01b03198216636e665ced60e01b1480610f995750610f998261431a565b6000610f99612d866143b6565b8360405161190160f01b8152600281019290925260228201526042902090565b6000806000612db7878787876143c0565b9150915061143f81614484565b6000805462010000900460ff1615612def57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615612e205760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b03851660009081526001602052604090205460ff1615612e5a5760405163b1d02c3d60e01b815260040160405180910390fd5b611b3686868686866145ce565b6000612e828254600f81810b600160801b909204900b131590565b15612ea057604051631ed9509560e11b815260040160405180910390fd5b508054600f0b6000818152600180840160205260408220805492905583546fffffffffffffffffffffffffffffffff191692016001600160801b03169190911790915590565b6064811115612f695760405162461bcd60e51b815260206004820152604360248201527f476f7665726e6f72566f74657351756f72756d4672616374696f6e3a2071756f60448201527f72756d4e756d657261746f72206f7665722071756f72756d44656e6f6d696e616064820152623a37b960e91b608482015260a401610448565b6000612f73612048565b90508015801590612f85575061025e54155b15612fea57604080518082019091526000815261025e9060208101612fa9846146d1565b6001600160e01b039081169091528254600181018455600093845260209384902083519490930151909116600160201b0263ffffffff909316929092179101555b613018613005612ff8611fbd565b65ffffffffffff166138e6565b61300e846146d1565b61025e919061473a565b505060408051828152602081018490527f0553476bf02ef2726e8ce5ced78d63e26e602e4a2257b1f559418e24b4633997910160405180910390a15050565b60008061306686868686612a05565b9050600461307382611751565b600781111561308457613084616303565b146130a15760405162461bcd60e51b815260040161044890616952565b61022b546040805163793d064960e11b815290516000926001600160a01b03169163f27a0c929160048083019260209291908290030181865afa1580156130ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906131109190616a73565b61022b5460405163b1c5f42760e01b81529192506001600160a01b03169063b1c5f4279061314b908a908a908a906000908b90600401616b3e565b602060405180830381865afa158015613168573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061318c9190616a73565b600083815261022c60205260408082209290925561022b5491516308f2a0bb60e41b81526001600160a01b0390921691638f2a0bb0916131d9918b918b918b91908b908990600401616b8c565b600060405180830381600087803b1580156131f357600080fd5b505af1158015613207573d6000803e3d6000fd5b505050507f9a2e42fd6722813d69113e7d0079d3d940171428df7373df9c7f7617cfda28928282426132399190616be4565b604080519283526020830191909152015b60405180910390a15095945050505050565b30613265610eb9565b6001600160a01b0316146132f65760005b845181101561177f57306001600160a01b031685828151811061329b5761329b6168e7565b60200260200101516001600160a01b0316036132e6576132e68382815181106132c6576132c66168e7565b60200260200101518051906020012061016461475590919063ffffffff16565b6132ef81616913565b9050613276565b5050505050565b60005462010000900460ff161561332757604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156133585760405163b1d02c3d60e01b815260040160405180910390fd5b60005b84518110156133d1576102c1600086838151811061337b5761337b6168e7565b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff166133bf57604051630b094f2760e31b815260040160405180910390fd5b806133c981616913565b91505061335b565b506132f68585858585614791565b306133e8610eb9565b6001600160a01b0316146132f65761016454600f81810b600160801b909204900b13156132f6576000610164556132f6565b60006113278585858561343860408051602081019091526000815290565b612dc4565b60008061344983614806565b9050600481600781111561345f5761345f616303565b1461346a5792915050565b600083815261022c602052604090205480613486575092915050565b61022b54604051632ab0f52960e01b8152600481018390526001600160a01b0390911690632ab0f52990602401602060405180830381865afa1580156134d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906134f49190616bf7565b15613503575060079392505050565b61022b54604051632c258a9f60e11b8152600481018390526001600160a01b039091169063584b153e90602401602060405180830381865afa15801561354d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906135719190616bf7565b15613580575060059392505050565b5060029392505050565b60608060606000806101c660008781526020019081526020016000209050806001018160020161375c83600301805480602002602001604051908101604052809291908181526020016000905b828210156136835783829060005260206000200180546135f6906168ad565b80601f0160208091040260200160405190810160405280929190818152602001828054613622906168ad565b801561366f5780601f106136445761010080835404028352916020019161366f565b820191906000526020600020905b81548152906001019060200180831161365257829003601f168201915b5050505050815260200190600101906135d7565b50505060048601805460408051602080840282018101909252828152935060009084015b828210156137535783829060005260206000200180546136c6906168ad565b80601f01602080910402602001604051908101604052809291908181526020018280546136f2906168ad565b801561373f5780601f106137145761010080835404028352916020019161373f565b820191906000526020600020905b81548152906001019060200180831161372257829003601f168201915b5050505050815260200190600101906136a7565b505050506141e8565b60098401548354604080516020808402820181019092528281529186918301828280156137b257602002820191906000526020600020905b81546001600160a01b03168152600190910190602001808311613794575b505050505093508280548060200260200160405190810160405280929190818152602001828054801561380457602002820191906000526020600020905b8154815260200190600101908083116137f0575b505050505092509450945094509450509193509193565b60008061382a86868686612a05565b60008181526101c660205260409020549091506001600160a01b03163381148061387e57506138576128de565b61387c826001613865611fbd565b61386f919061692c565b65ffffffffffff16612bf9565b105b6138da5760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f72427261766f3a2070726f706f7365722061626f76652074686044820152661c995cda1bdb1960ca1b6064820152608401610448565b6117468787878761493e565b600063ffffffff82111561394b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203360448201526532206269747360d01b6064820152608401610448565b5090565b8154600090818160058111156139ac57600061396a8461494c565b6139749085616a00565b60008881526020902090915081015463ffffffff908116908716101561399c578091506139aa565b6139a7816001616be4565b92505b505b60006139ba87878585614a34565b905080156139f5576139df876139d1600184616a00565b600091825260209091200190565b54600160201b90046001600160e01b0316611746565b6000979650505050505050565b6101945460408051918252602082018390527fc565b045403dc03c2eea82b81a0465edad9e2e7fc4d97e11421c209da93d7a93910160405180910390a161019455565b6102c25460ff16613aee576a084595161401484a0000006120056001600160a01b03166318160ddd6040518163ffffffff1660e01b8152600401602060405180830381865afa158015613a9c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613ac09190616a73565b1015613adf576040516311b6707f60e01b815260040160405180910390fd5b6102c2805460ff191660011790555b565b6000613b4c33868686516001600160401b03811115613b1157613b11615d3b565b604051908082528060200260200182016040528015613b4457816020015b6060815260200190600190039081613b2f5790505b50878761412a565b61132785858585614a8a565b600054610100900460ff16613b7f5760405162461bcd60e51b815260040161044890616c19565b613ba681613ba16040805180820190915260018152603160f81b602082015290565b614e69565b6111af81614eb8565b600054610100900460ff16613bd65760405162461bcd60e51b815260040161044890616c19565b613be1838383614ef0565b505050565b600054610100900460ff16613aee5760405162461bcd60e51b815260040161044890616c19565b600054610100900460ff16613c345760405162461bcd60e51b815260040161044890616c19565b6111af81614f32565b600054610100900460ff16613c645760405162461bcd60e51b815260040161044890616c19565b6111af81614f7c565b600054610100900460ff16613c945760405162461bcd60e51b815260040161044890616c19565b6111af81614fa3565b600054610100900460ff16613cc45760405162461bcd60e51b815260040161044890616c19565b6111af81614fca565b600054610100900460ff16613cf45760405162461bcd60e51b815260040161044890616c19565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b6060609a80546111c2906168ad565b6060609b80546111c2906168ad565b600065ffffffffffff82111561394b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203460448201526538206269747360d01b6064820152608401610448565b6101f854604051630748d63560e31b81526001600160a01b038581166004830152602482018590526000921690633a46b1a890604401602060405180830381865afa158015613df8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061203e9190616a73565b8054600090801561219057613e36836139d1600184616a00565b54600160201b90046001600160e01b0316612041565b61022b54604080516001600160a01b03928316815291831660208301527f08f74ea46ef7894f65eabfb5e6e695de773a000b47c529ab559178069b226401910160405180910390a161022b80546001600160a01b0319166001600160a01b0392909216919091179055565b600081604051602001613eca9190616c64565b6040516020818303038152906040528051906020012083604051602001613ef19190616c64565b6040516020818303038152906040528051906020012014905092915050565b015190565b60008111613f755760405162461bcd60e51b815260206004820152602760248201527f476f7665726e6f7253657474696e67733a20766f74696e6720706572696f6420604482015266746f6f206c6f7760c81b6064820152608401610448565b6101955460408051918252602082018390527f7e3f7f0708a84de9203036abaa450dccc85ad5ff52f78c170f3edb55cf5e8828910160405180910390a161019555565b6101965460408051918252602082018390527fccb45da8d5717e6c4544694297c4ba5cf151d455c9bb0ed4fc7a38411bc05461910160405180910390a161019655565b61028f54604080516001600160401b03928316815291831660208301527f7ca4ac117ed3cdce75c1161d8207c440389b1a15d69d096831664657c07dafc2910160405180910390a161028f805467ffffffffffffffff19166001600160401b0392909216919091179055565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b60008181526101636020526040812060010154610f99906001600160401b0316600084815261029060205260409020546001600160401b0316614ff1565b60608315614120575081612041565b6120418383615007565b805160208201206000614148878761414288886141e8565b85612a05565b60008181526101c6602052604090206009810154919250906141dd5780546001600160a01b0319166001600160a01b038a16178155875161419290600183019060208b0190615ad6565b5086516141a890600283019060208a0190615b37565b5085516141be9060038301906020890190615b72565b5084516141d49060048301906020880190615bc4565b50600981018390555b505050505050505050565b6060600082516001600160401b0381111561420557614205615d3b565b60405190808252806020026020018201604052801561423857816020015b60608152602001906001900390816142235790505b50905060005b815181101561431257848181518110614259576142596168e7565b6020026020010151516000146142c95784818151811061427b5761427b6168e7565b60200260200101518051906020012084828151811061429c5761429c6168e7565b60200260200101516040516020016142b5929190616c80565b6040516020818303038152906040526142e4565b8381815181106142db576142db6168e7565b60200260200101515b8282815181106142f6576142f66168e7565b60200260200101819052508061430b90616913565b905061423e565b509392505050565b600063288ace0360e11b6318df743f60e31b63bf26d89760e01b6379dd796f60e01b6001600160e01b0319861682148061436057506001600160e01b0319868116908216145b8061437757506001600160e01b0319868116908516145b8061439257506001600160e01b03198616630271189760e51b145b80611b3657506301ffc9a760e01b6001600160e01b03198716149695505050505050565b6000610ece615031565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156143f7575060009050600361447b565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561444b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166144745760006001925092505061447b565b9150600090505b94509492505050565b600081600481111561449857614498616303565b036144a05750565b60018160048111156144b4576144b4616303565b036145015760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e617475726500000000000000006044820152606401610448565b600281600481111561451557614515616303565b036145625760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e677468006044820152606401610448565b600381600481111561457657614576616303565b036111af5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b6064820152608401610448565b6000806145de87878787876150a5565b600088815261029060205260409020549091506001600160401b031615801561460b575061460b876151fb565b15611b3657600061462561028f546001600160401b031690565b61462d611fbd565b65ffffffffffff1661463f9190616cb1565b905061464a886128ea565b816001600160401b03161115614699576040516001600160401b038216815288907f541f725fb9f7c98a30cc9c0ff32fbb14358cd7159c847a3aa20a2bdc442ba5119060200160405180910390a25b600088815261029060205260409020805467ffffffffffffffff19166001600160401b03929092169190911790559695505050505050565b60006001600160e01b0382111561394b5760405162461bcd60e51b815260206004820152602760248201527f53616665436173743a2076616c756520646f65736e27742066697420696e20326044820152663234206269747360c81b6064820152608401610448565b60008061474885858561523b565b915091505b935093915050565b8154600160801b90819004600f0b6000818152600180860160205260409091209390935583546001600160801b03908116939091011602179055565b61022b5460405163e38335e560e01b81526001600160a01b039091169063e38335e59034906147cd908890889088906000908990600401616b3e565b6000604051808303818588803b1580156147e657600080fd5b505af11580156147fa573d6000803e3d6000fd5b50505050505050505050565b600081815261016360205260408120600281015460ff161561482b5750600792915050565b6002810154610100900460ff16156148465750600292915050565b600083815261016360205260408120546001600160401b0316908190036148af5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a20756e6b6e6f776e2070726f706f73616c2069640000006044820152606401610448565b60006148b9611fbd565b65ffffffffffff1690508082106148d557506000949350505050565b60006148e0866128ea565b90508181106148f55750600195945050505050565b6148fe866151fb565b8015614921575060008681526101c6602052604090206006810154600590910154115b156149325750600495945050505050565b50600395945050505050565b6000611327858585856153da565b60008160000361495e57506000919050565b6000600161496b84615490565b901c6001901b9050600181848161498457614984616a13565b048201901c9050600181848161499c5761499c616a13565b048201901c905060018184816149b4576149b4616a13565b048201901c905060018184816149cc576149cc616a13565b048201901c905060018184816149e4576149e4616a13565b048201901c905060018184816149fc576149fc616a13565b048201901c90506001818481614a1457614a14616a13565b048201901c905061204181828581614a2e57614a2e616a13565b04615524565b60005b81831015614312576000614a4b8484615533565b60008781526020902090915063ffffffff86169082015463ffffffff161115614a7657809250614a84565b614a81816001616be4565b93505b50614a37565b600033614a97818461554e565b614ae35760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73657220726573747269637465640000006044820152606401610448565b6000614aed611fbd565b65ffffffffffff169050614aff6128de565b614b0e83610e14600185616a00565b1015614b765760405162461bcd60e51b815260206004820152603160248201527f476f7665726e6f723a2070726f706f73657220766f7465732062656c6f7720706044820152701c9bdc1bdcd85b081d1a1c995cda1bdb19607a1b6064820152608401610448565b6000614b8b8888888880519060200120612a05565b90508651885114614bae5760405162461bcd60e51b815260040161044890616cd1565b8551885114614bcf5760405162461bcd60e51b815260040161044890616cd1565b6000885111614c205760405162461bcd60e51b815260206004820152601860248201527f476f7665726e6f723a20656d7074792070726f706f73616c00000000000000006044820152606401610448565b600081815261016360205260409020546001600160401b031615614c905760405162461bcd60e51b815260206004820152602160248201527f476f7665726e6f723a2070726f706f73616c20616c72656164792065786973746044820152607360f81b6064820152608401610448565b6000614c9c6101945490565b614ca69084616be4565b90506000614cb46101955490565b614cbe9083616be4565b90506040518060e00160405280614cd48461563f565b6001600160401b031681526001600160a01b038716602082015260006040820152606001614d018361563f565b6001600160401b03908116825260006020808401829052604080850183905260609485018390528883526101638252918290208551815492870151878501519186166001600160e01b031990941693909317600160401b6001600160a01b039094168402176001600160e01b0316600160e01b60e09290921c91909102178155938501516080860151908416921c0217600183015560a08301516002909201805460c09094015161ffff1990941692151561ff00191692909217610100931515939093029290921790558a517f7d84a6263ae0d98d3329bd7b46bb4e8d6f98cd35a7adb45c274c8b7fd5ebd5e091859188918e918e91811115614e0657614e06615d3b565b604051908082528060200260200182016040528015614e3957816020015b6060815260200190600190039081614e245790505b508d88888f604051614e5399989796959493929190616d12565b60405180910390a1509098975050505050505050565b600054610100900460ff16614e905760405162461bcd60e51b815260040161044890616c19565b609a614e9c8382616df0565b50609b614ea98282616df0565b50506000609881905560995550565b600054610100900460ff16614edf5760405162461bcd60e51b815260040161044890616c19565b610162614eec8282616df0565b5050565b600054610100900460ff16614f175760405162461bcd60e51b815260040161044890616c19565b614f2083613a02565b614f2982613f15565b613be181613fb8565b600054610100900460ff16614f595760405162461bcd60e51b815260040161044890616c19565b6101f880546001600160a01b0319166001600160a01b0392909216919091179055565b600054610100900460ff166120f45760405162461bcd60e51b815260040161044890616c19565b600054610100900460ff166111a65760405162461bcd60e51b815260040161044890616c19565b600054610100900460ff16612abe5760405162461bcd60e51b815260040161044890616c19565b60008183116150005781612041565b5090919050565b8151156150175781518083602001fd5b8060405162461bcd60e51b81526004016104489190615ef4565b60007f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f61505c6156a7565b615064615700565b60408051602081019490945283019190915260608201524660808201523060a082015260c00160405160208183030381529060405280519060200120905090565b60008581526101636020526040812060016150bf88611751565b60078111156150d0576150d0616303565b146151295760405162461bcd60e51b815260206004820152602360248201527f476f7665726e6f723a20766f7465206e6f742063757272656e746c792061637460448201526269766560e81b6064820152608401610448565b80546000906151439088906001600160401b031686613da5565b90506151528888888488615731565b83516000036151a757866001600160a01b03167fb8e138887d0aa13bab447e82de9d5c1777041ecd21ca36ba824ff1e6c07ddda48988848960405161519a9493929190616eaf565b60405180910390a2611746565b866001600160a01b03167fe2babfbac5889a709b63bb7f598b324e08bc5a4fb9ec647fb3cbc9ec07eb871289888489896040516151e8959493929190616ed7565b60405180910390a2979650505050505050565b60008181526101c6602052604081206005810154615232610e8085600090815261016360205260409020546001600160401b031690565b11159392505050565b825460009081908015615381576000615259876139d1600185616a00565b60408051808201909152905463ffffffff808216808452600160201b9092046001600160e01b0316602084015291925090871610156152da5760405162461bcd60e51b815260206004820152601b60248201527f436865636b706f696e743a2064656372656173696e67206b65797300000000006044820152606401610448565b805163ffffffff80881691160361532257846152fb886139d1600186616a00565b80546001600160e01b0392909216600160201b0263ffffffff909216919091179055615371565b6040805180820190915263ffffffff80881682526001600160e01b0380881660208085019182528b54600181018d5560008d81529190912094519151909216600160201b029216919091179101555b60200151925083915061474d9050565b50506040805180820190915263ffffffff80851682526001600160e01b0380851660208085019182528854600181018a5560008a815291822095519251909316600160201b02919093161792019190915590508161474d565b6000806153e9868686866158cf565b600081815261022c6020526040902054909150156113275761022b54600082815261022c60205260409081902054905163c4d252f560e01b81526001600160a01b039092169163c4d252f5916154459160040190815260200190565b600060405180830381600087803b15801561545f57600080fd5b505af1158015615473573d6000803e3d6000fd5b505050600082815261022c60205260408120555095945050505050565b600080608083901c156154a557608092831c92015b604083901c156154b757604092831c92015b602083901c156154c957602092831c92015b601083901c156154db57601092831c92015b600883901c156154ed57600892831c92015b600483901c156154ff57600492831c92015b600283901c1561551157600292831c92015b600183901c15610f995760010192915050565b60008183106150005781612041565b60006155426002848418616a29565b61204190848416616be4565b80516000906034811015615566576001915050610f99565b82810160131901516001600160a01b031981166b046e0e4dee0dee6cae47a60f60a31b1461559957600192505050610f99565b6000806155a7602885616a00565b90505b8381101561561e576000806155de8884815181106155ca576155ca6168e7565b01602001516001600160f81b0319166159dc565b91509150816155f65760019650505050505050610f99565b8060ff166004856001600160a01b0316901b17935050508061561790616913565b90506155aa565b50856001600160a01b0316816001600160a01b031614935050505092915050565b60006001600160401b0382111561394b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203660448201526534206269747360d01b6064820152608401610448565b6000806156b2613d20565b8051909150156156c9578051602090910120919050565b60985480156156d85792915050565b7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a4709250505090565b60008061570b613d2f565b805190915015615722578051602090910120919050565b60995480156156d85792915050565b60008581526101c6602090815260408083206001600160a01b038816845260088101909252909120805460ff16156157c15760405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20766f746560448201526c08185b1c9958591e4818d85cdd609a1b6064820152608401610448565b805460ff86166101000261ffff199091161760011781556157e184615a6e565b81546001600160601b039190911662010000026dffffffffffffffffffffffff00001990911617815560ff851661583157838260060160008282546158269190616be4565b909155506129fc9050565b60001960ff86160161585157838260050160008282546158269190616be4565b60011960ff86160161587157838260070160008282546158269190616be4565b60405162461bcd60e51b815260206004820152602d60248201527f476f7665726e6f72436f6d7061746962696c697479427261766f3a20696e766160448201526c6c696420766f7465207479706560981b6064820152608401610448565b6000806158de86868686612a05565b905060006158eb82611751565b9050600281600781111561590157615901616303565b141580156159215750600681600781111561591e5761591e616303565b14155b801561593f5750600781600781111561593c5761593c616303565b14155b61598b5760405162461bcd60e51b815260206004820152601d60248201527f476f7665726e6f723a2070726f706f73616c206e6f74206163746976650000006044820152606401610448565b6000828152610163602052604090819020600201805461ff001916610100179055517f789cf55be980739dad1d0699b93b58e806b51c9d96619bfa8fe0a28abaa7b30c9061324a9084815260200190565b60008060f883901c602f811180156159f75750603a8160ff16105b15615a0c57600194602f199091019350915050565b8060ff166040108015615a22575060478160ff16105b15615a37576001946036199091019350915050565b8060ff166060108015615a4d575060678160ff16105b15615a62576001946056199091019350915050565b50600093849350915050565b60006001600160601b0382111561394b5760405162461bcd60e51b815260206004820152602660248201527f53616665436173743a2076616c756520646f65736e27742066697420696e203960448201526536206269747360d01b6064820152608401610448565b828054828255906000526020600020908101928215615b2b579160200282015b82811115615b2b57825182546001600160a01b0319166001600160a01b03909116178255602090920191600190910190615af6565b5061394b929150615c16565b828054828255906000526020600020908101928215615b2b579160200282015b82811115615b2b578251825591602001919060010190615b57565b828054828255906000526020600020908101928215615bb8579160200282015b82811115615bb85782518290615ba89082616df0565b5091602001919060010190615b92565b5061394b929150615c2b565b828054828255906000526020600020908101928215615c0a579160200282015b82811115615c0a5782518290615bfa9082616df0565b5091602001919060010190615be4565b5061394b929150615c48565b5b8082111561394b5760008155600101615c17565b8082111561394b576000615c3f8282615c65565b50600101615c2b565b8082111561394b576000615c5c8282615c65565b50600101615c48565b508054615c71906168ad565b6000825580601f10615c81575050565b601f0160209004906000526020600020908101906111af9190615c16565b600060208284031215615cb157600080fd5b5035919050565b600060208284031215615cca57600080fd5b81356001600160e01b03198116811461204157600080fd5b803560ff8116811461193957600080fd5b60008083601f840112615d0557600080fd5b5081356001600160401b03811115615d1c57600080fd5b602083019150836020828501011115615d3457600080fd5b9250929050565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715615d7957615d79615d3b565b604052919050565b60006001600160401b03821115615d9a57615d9a615d3b565b50601f01601f191660200190565b600082601f830112615db957600080fd5b8135615dcc615dc782615d81565b615d51565b818152846020838601011115615de157600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060008060008060e0898b031215615e1a57600080fd5b88359750615e2a60208a01615ce2565b965060408901356001600160401b0380821115615e4657600080fd5b615e528c838d01615cf3565b909850965060608b0135915080821115615e6b57600080fd5b50615e788b828c01615da8565b945050615e8760808a01615ce2565b925060a0890135915060c089013590509295985092959890939650565b60005b83811015615ebf578181015183820152602001615ea7565b50506000910152565b60008151808452615ee0816020860160208601615ea4565b601f01601f19169290920160200192915050565b6020815260006120416020830184615ec8565b6001600160a01b03811681146111af57600080fd5b60008060008060808587031215615f3257600080fd5b8435615f3d81615f07565b93506020850135615f4d81615f07565b92506040850135915060608501356001600160401b03811115615f6f57600080fd5b615f7b87828801615da8565b91505092959194509250565b60006001600160401b03821115615fa057615fa0615d3b565b5060051b60200190565b600082601f830112615fbb57600080fd5b81356020615fcb615dc783615f87565b82815260059290921b84018101918181019086841115615fea57600080fd5b8286015b8481101561600e57803561600181615f07565b8352918301918301615fee565b509695505050505050565b600082601f83011261602a57600080fd5b8135602061603a615dc783615f87565b82815260059290921b8401810191818101908684111561605957600080fd5b8286015b8481101561600e578035835291830191830161605d565b600082601f83011261608557600080fd5b81356020616095615dc783615f87565b82815260059290921b840181019181810190868411156160b457600080fd5b8286015b8481101561600e5780356001600160401b038111156160d75760008081fd5b6160e58986838b0101615da8565b8452509183019183016160b8565b6000806000806080858703121561610957600080fd5b84356001600160401b038082111561612057600080fd5b61612c88838901615faa565b9550602087013591508082111561614257600080fd5b61614e88838901616019565b9450604087013591508082111561616457600080fd5b5061617187828801616074565b949793965093946060013593505050565b60006020828403121561619457600080fd5b813561204181615f07565b600081518084526020808501945080840160005b838110156161d85781516001600160a01b0316875295820195908201906001016161b3565b509495945050505050565b600081518084526020808501945080840160005b838110156161d8578151875295820195908201906001016161f7565b600081518084526020808501808196508360051b8101915082860160005b8581101561625b578284038952616249848351615ec8565b98850198935090840190600101616231565b5091979650505050505050565b60808152600061627b608083018761619f565b828103602084015261628d81876161e3565b905082810360408401526162a18186616213565b905082810360608401526117468185616213565b600080600080600060a086880312156162cd57600080fd5b853594506162dd60208701615ce2565b93506162eb60408701615ce2565b94979396509394606081013594506080013592915050565b634e487b7160e01b600052602160045260246000fd5b602081016008831061633b57634e487b7160e01b600052602160045260246000fd5b91905290565b6000806040838503121561635457600080fd5b82359150602083013561636681615f07565b809150509250929050565b6000806040838503121561638457600080fd5b8235915061639460208401615ce2565b90509250929050565b6000806000806000608086880312156163b557600080fd5b853594506163c560208701615ce2565b935060408601356001600160401b03808211156163e157600080fd5b6163ed89838a01615cf3565b9095509350606088013591508082111561640657600080fd5b5061641388828901615da8565b9150509295509295909350565b6000806000806060858703121561643657600080fd5b8435935061644660208601615ce2565b925060408501356001600160401b0381111561646157600080fd5b61646d87828801615cf3565b95989497509550505050565b6000806000806080858703121561648f57600080fd5b84356001600160401b03808211156164a657600080fd5b6164b288838901615faa565b955060208701359150808211156164c857600080fd5b6164d488838901616019565b945060408701359150808211156164ea57600080fd5b6164f688838901616074565b9350606087013591508082111561650c57600080fd5b50615f7b87828801615da8565b60ff60f81b8816815260e06020820152600061653860e0830189615ec8565b828103604084015261654a8189615ec8565b606084018890526001600160a01b038716608085015260a0840186905283810360c0850152905061108981856161e3565b60008060006060848603121561659057600080fd5b833561659b81615f07565b92506020840135915060408401356001600160401b038111156165bd57600080fd5b6165c986828701615da8565b9150509250925092565b600080600080604085870312156165e957600080fd5b84356001600160401b038082111561660057600080fd5b61660c88838901615cf3565b9096509450602087013591508082111561662557600080fd5b5061646d87828801615cf3565b600080600080600060a0868803121561664a57600080fd5b853561665581615f07565b9450602086013561666581615f07565b935060408601356001600160401b038082111561668157600080fd5b61668d89838a01616019565b945060608801359150808211156166a357600080fd5b6166af89838a01616019565b9350608088013591508082111561640657600080fd5b600080600080606085870312156166db57600080fd5b84356166e681615f07565b93506020850135925060408501356001600160401b0381111561646157600080fd5b60006020828403121561671a57600080fd5b81356001600160401b038116811461204157600080fd5b600080600080600060a0868803121561674957600080fd5b85356001600160401b038082111561676057600080fd5b61676c89838a01615faa565b9650602088013591508082111561678257600080fd5b61678e89838a01616019565b955060408801359150808211156167a457600080fd5b6167b089838a01616074565b945060608801359150808211156167c657600080fd5b6166af89838a01616074565b600080604083850312156167e557600080fd5b82356167f081615f07565b946020939093013593505050565b600080600080600060a0868803121561681657600080fd5b853561682181615f07565b9450602086013561683181615f07565b9350604086013592506060860135915060808601356001600160401b0381111561685a57600080fd5b61641388828901615da8565b8183823760009101908152919050565b60208082526018908201527f476f7665726e6f723a206f6e6c79476f7665726e616e63650000000000000000604082015260600190565b600181811c908216806168c157607f821691505b6020821081036168e157634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201616925576169256168fd565b5060010190565b65ffffffffffff82811682821603908082111561694b5761694b6168fd565b5092915050565b60208082526021908201527f476f7665726e6f723a2070726f706f73616c206e6f74207375636365737366756040820152601b60fa1b606082015260800190565b6000602082840312156169a557600080fd5b81516001600160401b038111156169bb57600080fd5b8201601f810184136169cc57600080fd5b80516169da615dc782615d81565b8181528560208385010111156169ef57600080fd5b611327826020830160208601615ea4565b81810381811115610f9957610f996168fd565b634e487b7160e01b600052601260045260246000fd5b600082616a4657634e487b7160e01b600052601260045260246000fd5b500490565b600060208284031215616a5d57600080fd5b815165ffffffffffff8116811461204157600080fd5b600060208284031215616a8557600080fd5b5051919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b604081526000616ac9604083018688616a8c565b8281036020840152611746818587616a8c565b608081526000616aef608083018761619f565b8281036020840152616b0181876161e3565b90508281036040840152616b158186616213565b91505082606083015295945050505050565b8082028115828204841417610f9957610f996168fd565b60a081526000616b5160a083018861619f565b8281036020840152616b6381886161e3565b90508281036040840152616b778187616213565b60608401959095525050608001529392505050565b60c081526000616b9f60c083018961619f565b8281036020840152616bb181896161e3565b90508281036040840152616bc58188616213565b60608401969096525050608081019290925260a0909101529392505050565b80820180821115610f9957610f996168fd565b600060208284031215616c0957600080fd5b8151801515811461204157600080fd5b6020808252602b908201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960408201526a6e697469616c697a696e6760a81b606082015260800190565b60008251616c76818460208701615ea4565b9190910192915050565b6001600160e01b0319831681528151600090616ca3816004850160208701615ea4565b919091016004019392505050565b6001600160401b0381811683821601908082111561694b5761694b6168fd565b60208082526021908201527f476f7665726e6f723a20696e76616c69642070726f706f73616c206c656e67746040820152600d60fb1b606082015260800190565b8981526001600160a01b038916602082015261012060408201819052600090616d3d8382018b61619f565b90508281036060840152616d51818a6161e3565b90508281036080840152616d658189616213565b905082810360a0840152616d798188616213565b90508560c08401528460e0840152828103610100840152616d9a8185615ec8565b9c9b505050505050505050505050565b601f821115613be157600081815260208120601f850160051c81016020861015616dd15750805b601f850160051c820191505b8181101561177f57828155600101616ddd565b81516001600160401b03811115616e0957616e09615d3b565b616e1d81616e1784546168ad565b84616daa565b602080601f831160018114616e525760008415616e3a5750858301515b600019600386901b1c1916600185901b17855561177f565b600085815260208120601f198616915b82811015616e8157888601518255948401946001909101908401616e62565b5085821015616e9f5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b84815260ff84166020820152826040820152608060608201526000611b366080830184615ec8565b85815260ff8516602082015283604082015260a060608201526000616eff60a0830185615ec8565b8281036080840152611c4f8185615ec856fe476f7665726e6f723a2072656c617920726576657274656420776974686f7574206d657373616765a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/pasteur/rialto/StakeHubContract b/core/systemcontracts/pasteur/rialto/StakeHubContract new file mode 100644 index 0000000000..da3f8cc6f2 --- /dev/null +++ b/core/systemcontracts/pasteur/rialto/StakeHubContract @@ -0,0 +1 @@ +6080604052600436106200043b5760003560e01c806386d545061162000233578063ca47908f116200012f578063dd42a1dd11620000b9578063f1f74d841162000084578063f1f74d841462000d74578063f80a34021462000d8c578063fb50b31f1462000db1578063fc0c5ff11462000dd6578063ff69ab611462000dee57600080fd5b8063dd42a1dd1462000ce1578063e8f67c3b1462000d08578063e992aaf51462000d20578063efdbf0e11462000d3857600080fd5b8063d7c2dfc811620000fa578063d7c2dfc81462000c67578063d8ca511f1462000c8c578063daacdb661462000ca4578063dbda7fb31462000cbc57600080fd5b8063ca47908f1462000bd0578063cbb04d9d1462000be8578063d115a2061462000c29578063d6ca429d1462000c4257600080fd5b8063b187bd2611620001bd578063bfff04751162000188578063bfff04751462000b57578063c166f58a1462000b7c578063c38fbec81462000b93578063c473318f1462000bb8578063c8509d81146200095057600080fd5b8063b187bd261462000ac4578063baa7199e1462000ae4578063bdceadf31462000b09578063bff02e201462000b2157600080fd5b8063a1832e6411620001fe578063a1832e641462000a21578063a43569b31462000a46578063aad3ec961462000a7a578063ac4317511462000a9f57600080fd5b806386d54506146200098d5780638a4d3fa814620009c75780638cd22b2214620009e5578063982ef0a71462000a0a57600080fd5b80634838d165116200034357806364028fbd11620002cd57806375cc7d89116200029857806375cc7d8914620008fb57806376e7d6d614620009205780638129fc1c1462000938578063831d65d114620009505780638456cb59146200097557600080fd5b806364028fbd1462000836578063663706d3146200084d5780636ec01b27146200087e5780636f8e2fa414620008d657600080fd5b80634e6fd6c4116200030e5780634e6fd6c4146200079d5780635949187114620007b55780635e7cc1c914620007da57806363a036b514620007ff57600080fd5b80634838d16514620006e957806349f41a42146200072e5780634a49ac4c14620007535780634d99dd16146200077857600080fd5b80631fab701511620003c5578063384099881162000390578063384099881462000662578063417c73a7146200067a578063449ecfe6146200069f57806345211bfd14620006c457600080fd5b80631fab701514620005a95780632b727c8614620005ce5780632e8e8c7114620005f3578063367dad49146200062d57600080fd5b80630e9fbf5111620004065780630e9fbf5114620004f35780631182b875146200051857806317b4f353146200054c5780631fa8882b146200059157600080fd5b8063046f7da2146200045b578063059ddd2214620004735780630661806e14620004b5578063092193ab14620004dc57600080fd5b36620004565760345460ff166001146200045457600080fd5b005b600080fd5b3480156200046857600080fd5b506200045462000e06565b3480156200048057600080fd5b506200049862000492366004620097c0565b62000e98565b6040516001600160a01b0390911681526020015b60405180910390f35b348015620004c257600080fd5b50620004cd60365481565b604051908152602001620004ac565b62000454620004ed366004620097c0565b620012c0565b3480156200050057600080fd5b50620004546200051236600462009822565b62001911565b3480156200052557600080fd5b506200053d6200053736600462009867565b62001c9b565b604051620004ac91906200991a565b3480156200055957600080fd5b50620004986200056b366004620099ec565b80516020818301810180516045825292820191909301209152546001600160a01b031681565b3480156200059e57600080fd5b50620004cd61025881565b348015620005b657600080fd5b5062000454620005c836600462009a88565b62001d33565b348015620005db57600080fd5b5062000498620005ed366004620097c0565b6200208a565b3480156200060057600080fd5b506200049862000612366004620097c0565b604d602052600090815260409020546001600160a01b031681565b3480156200063a57600080fd5b50620006526200064c36600462009a88565b620020df565b604051620004ac92919062009b07565b3480156200066f57600080fd5b50620004cd60375481565b3480156200068757600080fd5b506200045462000699366004620097c0565b620026ae565b348015620006ac57600080fd5b5062000454620006be366004620097c0565b62002730565b348015620006d157600080fd5b5062000454620006e3366004620097c0565b62002915565b348015620006f657600080fd5b506200071d62000708366004620097c0565b60016020526000908152604090205460ff1681565b6040519015158152602001620004ac565b3480156200073b57600080fd5b50620004546200074d366004620097c0565b62002aed565b3480156200076057600080fd5b506200045462000772366004620097c0565b62002d09565b3480156200078557600080fd5b50620004546200079736600462009ba6565b62002d85565b348015620007aa57600080fd5b506200049861dead81565b348015620007c257600080fd5b5062000454620007d436600462009be4565b620033b5565b348015620007e757600080fd5b5062000454620007f936600462009c4e565b620041ae565b3480156200080c57600080fd5b50620008246200081e36600462009c75565b620043d7565b604051620004ac949392919062009c98565b620004546200084736600462009d54565b62004a7c565b3480156200085a57600080fd5b50620004cd6200086c366004620097c0565b60446020526000908152604090205481565b3480156200088b57600080fd5b50620008a36200089d366004620097c0565b620050cb565b6040805182516001600160401b0390811682526020808501518216908301529282015190921690820152606001620004ac565b348015620008e357600080fd5b506200053d620008f5366004620097c0565b62005170565b3480156200090857600080fd5b50620004546200091a366004620097c0565b6200559c565b3480156200092d57600080fd5b50620004cd603d5481565b3480156200094557600080fd5b50620004546200576e565b3480156200095d57600080fd5b50620004546200096f36600462009867565b62005936565b3480156200098257600080fd5b506200045462005994565b3480156200099a57600080fd5b5062000498620009ac366004620097c0565b6043602052600090815260409020546001600160a01b031681565b348015620009d457600080fd5b50620004cd670de0b6b3a764000081565b348015620009f257600080fd5b50620004cd62000a0436600462009ba6565b62005a2c565b6200045462000a1b36600462009e2a565b62005ae5565b34801562000a2e57600080fd5b506200045462000a4036600462009a88565b62006193565b34801562000a5357600080fd5b5062000a6b62000a65366004620097c0565b62006499565b604051620004ac919062009e62565b34801562000a8757600080fd5b506200045462000a9936600462009ba6565b62006786565b34801562000aac57600080fd5b506200045462000abe36600462009edf565b620067f3565b34801562000ad157600080fd5b5060005462010000900460ff166200071d565b34801562000af157600080fd5b506200045462000b0336600462009f51565b620077a5565b34801562000b1657600080fd5b50620004cd603c5481565b34801562000b2e57600080fd5b5062000b4662000b4036600462009c75565b62007972565b604051620004ac9392919062009faa565b34801562000b6457600080fd5b50620004cd62000b76366004620097c0565b62007b4e565b34801562000b8957600080fd5b50620004cd600581565b34801562000ba057600080fd5b506200045462000bb2366004620097c0565b62007b9c565b34801562000bc557600080fd5b50620004cd60385481565b34801562000bdd57600080fd5b50620004cd604e5481565b34801562000bf557600080fd5b5062000c0d62000c07366004620097c0565b62007ebc565b60408051938452911515602084015290820152606001620004ac565b34801562000c3657600080fd5b50620004cd620186a081565b34801562000c4f57600080fd5b506200045462000c613660046200a007565b620082ff565b34801562000c7457600080fd5b506200045462000c863660046200a0f0565b62008524565b34801562000c9957600080fd5b50620004cd603b5481565b34801562000cb157600080fd5b50620004cd60495481565b34801562000cc957600080fd5b506200049862000cdb366004620097c0565b6200861a565b34801562000cee57600080fd5b50600054630100000090046001600160a01b031662000498565b34801562000d1557600080fd5b50620004cd60355481565b34801562000d2d57600080fd5b50620004cd603a5481565b34801562000d4557600080fd5b50620004cd62000d57366004620099ec565b805160208183018101805160468252928201919093012091525481565b34801562000d8157600080fd5b50620004cd603e5481565b34801562000d9957600080fd5b50620004cd62000dab36600462009ba6565b62008a44565b34801562000dbe57600080fd5b506200045462000dd036600462009edf565b62008ab5565b34801562000de357600080fd5b50620004cd60395481565b34801562000dfb57600080fd5b50620004cd604a5481565b600054630100000090046001600160a01b0316331462000e39576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1662000e6357604051636cd6020160e01b815260040160405180910390fd5b6000805462ff0000191681556040517f62451d457bc659158be6e6247f56ec1df424a5c7597f71c20c2bc44e0965c8f99190a1565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162000f03906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462000f31906200a156565b801562000f825780601f1062000f565761010080835404028352916020019162000f82565b820191906000526020600020905b81548152906001019060200180831162000f6457829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462000fad906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462000fdb906200a156565b80156200102c5780601f1062001000576101008083540402835291602001916200102c565b820191906000526020600020905b8154815290600101906020018083116200100e57829003601f168201915b5050505050815260200160018201805462001047906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462001075906200a156565b8015620010c65780601f106200109a57610100808354040283529160200191620010c6565b820191906000526020600020905b815481529060010190602001808311620010a857829003601f168201915b50505050508152602001600282018054620010e1906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200110f906200a156565b8015620011605780601f10620011345761010080835404028352916020019162001160565b820191906000526020600020905b8154815290600101906020018083116200114257829003601f168201915b505050505081526020016003820180546200117b906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620011a9906200a156565b8015620011fa5780601f10620011ce57610100808354040283529160200191620011fa565b820191906000526020600020905b815481529060010190602001808311620011dc57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162001299575050509190925250509051949350505050565b3361100014620012ec57604051630f22c43960e41b815261100060048201526024015b60405180910390fd5b6001600160a01b0380821660009081526043602090815260408083205484168084526041835281842082516101808101845281548716815260018201548716948101949094526002810154909516918301919091526003840154606083015260048401805491949160808401919062001365906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462001393906200a156565b8015620013e45780601f10620013b857610100808354040283529160200191620013e4565b820191906000526020600020905b815481529060010190602001808311620013c657829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200140f906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200143d906200a156565b80156200148e5780601f1062001462576101008083540402835291602001916200148e565b820191906000526020600020905b8154815290600101906020018083116200147057829003601f168201915b50505050508152602001600182018054620014a9906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620014d7906200a156565b8015620015285780601f10620014fc5761010080835404028352916020019162001528565b820191906000526020600020905b8154815290600101906020018083116200150a57829003601f168201915b5050505050815260200160028201805462001543906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462001571906200a156565b8015620015c25780601f106200159657610100808354040283529160200191620015c2565b820191906000526020600020905b815481529060010190602001808311620015a457829003601f168201915b50505050508152602001600382018054620015dd906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200160b906200a156565b80156200165c5780601f1062001630576101008083540402835291602001916200165c565b820191906000526020600020905b8154815290600101906020018083116200163e57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620016fb575050509190925250505060408101519091506001600160a01b031615806200173857508060e001515b15620017f557604051611002903490600081818185875af1925050503d806000811462001782576040519150601f19603f3d011682016040523d82523d6000602084013e62001787565b606091505b505050816001600160a01b03167ffc8bff675087dd2da069cc3fb517b9ed001e19750c0865241a5542dba1ba170d604051620017e89060208082526011908201527024a72b20a624a22fab20a624a220aa27a960791b604082015260600190565b60405180910390a2505050565b60408181015160c0830151519151632f303ebb60e11b81526001600160401b0390921660048301526001600160a01b031690635e607d769034906024016000604051808303818588803b1580156200184c57600080fd5b505af115801562001861573d6000803e3d6000fd5b5050505050816001600160a01b03167fe34918ff1c7084970068b53fd71ad6d8b04e9f15d3886cbf006443e6cdc52ea634604051620018a291815260200190565b60405180910390a26040808201519051633041949b60e01b815261200591633041949b91620018d7919086906004016200a18c565b600060405180830381600087803b158015620018f257600080fd5b505af115801562001907573d6000803e3d6000fd5b5050505050505b50565b33611001146200193957604051630f22c43960e41b81526110016004820152602401620012e3565b60005462010000900460ff16156200196457604051631785c68160e01b815260040160405180910390fd5b6000604583836040516200197a9291906200a1a6565b908152604051908190036020019020546001600160a01b03169050620019a2603f8262008ced565b620019c05760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038116600090815260416020526040812090620019e7610258426200a1cc565b604a546000828152604b60205260409020549192501162001a1b5760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062001a3c9084906200a1ef565b909155505060405160469062001a5690879087906200a1a6565b90815260200160405180910390205460001415801562001aa65750426102586046878760405162001a899291906200a1a6565b90815260200160405180910390205462001aa491906200a1ef565b105b1562001ac557604051631898eb6b60e01b815260040160405180910390fd5b60008062001ad585600262008d10565b915091508162001af857604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562001b4b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062001b7191906200a205565b905062001b7f858362008d98565b84546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562001bc657600080fd5b505af115801562001bdb573d6000803e3d6000fd5b50505050856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600260405162001c1f939291906200a21f565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162001c5d916001600160a01b0316908a906004016200a18c565b600060405180830381600087803b15801562001c7857600080fd5b505af115801562001c8d573d6000803e3d6000fd5b505050505050505050505050565b6060336120001462001cc557604051630f22c43960e41b81526120006004820152602401620012e3565b60005462010000900460ff161562001cf057604051631785c68160e01b815260040160405180910390fd5b6034805460ff1916600117905560405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e3565b60005462010000900460ff161562001d5e57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562001d905760405163b1d02c3d60e01b815260040160405180910390fd5b62001d9a62008e8c565b62001da7603f8262008ced565b62001dc55760405163056e881160e01b815260040160405180910390fd5b62001dcf62008ef3565b600082900362001df257604051636490ffd360e01b815260040160405180910390fd5b600062001dfe62008e8c565b6001600160a01b0381166000908152604f602052604090208054604e54929350909162001e2c86836200a1ef565b111562001e4c5760405163091af98560e21b815260040160405180910390fd5b60005b8581101562001f3257600087878381811062001e6f5762001e6f6200a25a565b905060200201350362001e9557604051636490ffd360e01b815260040160405180910390fd5b600062001ea48260016200a1ef565b90505b8681101562001f1c5787878281811062001ec55762001ec56200a25a565b9050602002013588888481811062001ee15762001ee16200a25a565b905060200201350362001f0757604051632205e3c760e11b815260040160405180910390fd5b8062001f13816200a270565b91505062001ea7565b508062001f29816200a270565b91505062001e4f565b5060005b8581101562001fd15760005b8281101562001fbb5783818154811062001f605762001f606200a25a565b906000526020600020015488888481811062001f805762001f806200a25a565b905060200201350362001fa657604051632205e3c760e11b815260040160405180910390fd5b8062001fb2816200a270565b91505062001f42565b508062001fc8816200a270565b91505062001f36565b5060005b8581101562001907578287878381811062001ff45762001ff46200a25a565b835460018101855560009485526020948590209190940292909201359190920155506001600160a01b0384167f7c4ff4c9a343a2daef608f3b5a91016e994a15fc0ef8611109e4f45823249f298888848181106200205657620020566200a25a565b905060200201356040516200206d91815260200190565b60405180910390a28062002081816200a270565b91505062001fd5565b6000816200209a603f8262008ced565b620020b85760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160205260409020600d01541691505b50919050565b60608082806001600160401b03811115620020fe57620020fe6200992f565b60405190808252806020026020018201604052801562002128578160200160208202803683370190505b509250806001600160401b038111156200214657620021466200992f565b6040519080825280602002602001820160405280156200217b57816020015b6060815260200190600190039081620021655790505b50915060005b81811015620026a4576000868683818110620021a157620021a16200a25a565b9050602002016020810190620021b89190620097c0565b6001600160a01b0380821660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549495509193909291608084019162002225906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462002253906200a156565b8015620022a45780601f106200227857610100808354040283529160200191620022a4565b820191906000526020600020905b8154815290600101906020018083116200228657829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620022cf906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620022fd906200a156565b80156200234e5780601f1062002322576101008083540402835291602001916200234e565b820191906000526020600020905b8154815290600101906020018083116200233057829003601f168201915b5050505050815260200160018201805462002369906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462002397906200a156565b8015620023e85780601f10620023bc57610100808354040283529160200191620023e8565b820191906000526020600020905b815481529060010190602001808311620023ca57829003601f168201915b5050505050815260200160028201805462002403906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462002431906200a156565b8015620024825780601f10620024565761010080835404028352916020019162002482565b820191906000526020600020905b8154815290600101906020018083116200246457829003601f168201915b505050505081526020016003820180546200249d906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620024cb906200a156565b80156200251c5780601f10620024f0576101008083540402835291602001916200251c565b820191906000526020600020905b815481529060010190602001808311620024fe57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620025bb5750505050508152505090508060000151868481518110620025f457620025f46200a25a565b6001600160a01b039283166020918202929092018101919091529083166000908152604f8252604090819020805482518185028101850190935280835291929091908301828280156200266757602002820191906000526020600020905b81548152602001906001019080831162002652575b50505050508584815181106200268157620026816200a25a565b6020026020010181905250505080806200269b906200a270565b91505062002181565b50505b9250929050565b600054630100000090046001600160a01b03163314620026e1576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b0381166000818152600160208190526040808320805460ff1916909217909155517f7fd26be6fc92aff63f1f4409b2b2ddeb272a888031d7f55ec830485ec61941869190a250565b60005462010000900460ff16156200275b57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200278d5760405163b1d02c3d60e01b815260040160405180910390fd5b806200279b603f8262008ced565b620027b95760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0382166000908152604160205260409020600a81015460ff16620027f757604051634b6b857d60e01b815260040160405180910390fd5b6036546002820154604051630913db4760e01b81526001600160a01b03868116600483015290911690630913db4790602401602060405180830381865afa15801562002847573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200286d91906200a205565b10156200288d576040516317b204bf60e11b815260040160405180910390fd5b4281600b01541115620028b35760405163170cb76760e21b815260040160405180910390fd5b600a8101805460ff191690556049805460019190600090620028d79084906200a28c565b90915550506040516001600160a01b038416907f9390b453426557da5ebdc31f19a37753ca04addf656d32f35232211bb2af3f1990600090a2505050565b60005462010000900460ff16156200294057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620029725760405163b1d02c3d60e01b815260040160405180910390fd5b6200297c62008f06565b62002989603f8262008ced565b620029a75760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038216620029cf57604051636520611b60e11b815260040160405180910390fd5b6001600160a01b03828116600090815260436020526040902054161562002a0957604051631e6f587560e11b815260040160405180910390fd5b600062002a1562008f06565b6001600160a01b0381166000908152604160205260409020600c81015491925090429062002a4790610258906200a1ef565b111562002a6757604051631f92cdbd60e11b815260040160405180910390fd5b80546001600160a01b039081166000908152604460209081526040808320429081905585548986166001600160a01b031991821681178855600c88019290925581855260439093528184208054958816959093168517909255519092917f6e4e747ca35203f16401c69805c7dd52fff67ef60b0ebc5c7fe16890530f223591a350505050565b3362002afb603f8262008ced565b62002b195760405163056e881160e01b815260040160405180910390fd5b60005462010000900460ff161562002b4457604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002b765760405163b1d02c3d60e01b815260040160405180910390fd5b6001600160a01b038281166000908152604d6020526040902054161562002bb05760405163bebdc75760e01b815260040160405180910390fd5b62002bbd603f8362008ced565b1562002bdc5760405163bebdc75760e01b815260040160405180910390fd5b336000818152604160205260409020600d01546001600160a01b03908116908416810362002c1d5760405163bebdc75760e01b815260040160405180910390fd5b6001600160a01b0381161562002c54576001600160a01b0381166000908152604d6020526040902080546001600160a01b03191690555b6001600160a01b038281166000908152604160205260409020600d0180546001600160a01b03191691861691821790551562002cb9576001600160a01b038481166000908152604d6020526040902080546001600160a01b0319169184169190911790555b836001600160a01b0316816001600160a01b0316836001600160a01b03167fcbb728765de145e99c00e8ae32a325231e850359b7b8a6da3b84d672ab3f1d0a60405160405180910390a450505050565b600054630100000090046001600160a01b0316331462002d3c576040516306fbb1e360e01b815260040160405180910390fd5b6001600160a01b038116600081815260016020526040808220805460ff19169055517fe0db3499b7fdc3da4cddff5f45d694549c19835e7f719fb5606d3ad1a5de40119190a250565b60005462010000900460ff161562002db057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562002de25760405163b1d02c3d60e01b815260040160405180910390fd5b8162002df0603f8262008ced565b62002e0e5760405163056e881160e01b815260040160405180910390fd5b8160000362002e3057604051639811e0c760e01b815260040160405180910390fd5b6001600160a01b038084166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162002e98906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462002ec6906200a156565b801562002f175780601f1062002eeb5761010080835404028352916020019162002f17565b820191906000526020600020905b81548152906001019060200180831162002ef957829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462002f42906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462002f70906200a156565b801562002fc15780601f1062002f955761010080835404028352916020019162002fc1565b820191906000526020600020905b81548152906001019060200180831162002fa357829003601f168201915b5050505050815260200160018201805462002fdc906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200300a906200a156565b80156200305b5780601f106200302f576101008083540402835291602001916200305b565b820191906000526020600020905b8154815290600101906020018083116200303d57829003601f168201915b5050505050815260200160028201805462003076906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620030a4906200a156565b8015620030f55780601f10620030c957610100808354040283529160200191620030f5565b820191906000526020600020905b815481529060010190602001808311620030d757829003601f168201915b5050505050815260200160038201805462003110906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200313e906200a156565b80156200318f5780601f1062003163576101008083540402835291602001916200318f565b820191906000526020600020905b8154815290600101906020018083116200317157829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200322e575050509190925250505060408082015190516326ccee8b60e11b81526001600160a01b0385811660048301526024820188905292935060009290911690634d99dd16906044016020604051808303816000875af1158015620032a8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620032ce91906200a205565b9050826001600160a01b0316866001600160a01b03167f3aace7340547de7b9156593a7652dc07ee900cea3fd8f82cb6c9d38b4082980287846040516200331f929190918252602082015260400190565b60405180910390a3856001600160a01b0316836001600160a01b0316036200334c576200334c8662008f47565b6040808301519051633041949b60e01b815261200591633041949b9162003379919087906004016200a18c565b600060405180830381600087803b1580156200339457600080fd5b505af1158015620033a9573d6000803e3d6000fd5b50505050505050505050565b60005462010000900460ff1615620033e057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620034125760405163b1d02c3d60e01b815260040160405180910390fd5b8362003420603f8262008ced565b6200343e5760405163056e881160e01b815260040160405180910390fd5b836200344c603f8262008ced565b6200346a5760405163056e881160e01b815260040160405180910390fd5b6034805460ff1916600117905560008490036200349a57604051639811e0c760e01b815260040160405180910390fd5b846001600160a01b0316866001600160a01b031603620034cd5760405163f0e3e62960e01b815260040160405180910390fd5b6001600160a01b038087166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162003535906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462003563906200a156565b8015620035b45780601f106200358857610100808354040283529160200191620035b4565b820191906000526020600020905b8154815290600101906020018083116200359657829003601f168201915b5050505050815260200160058201604051806080016040529081600082018054620035df906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200360d906200a156565b80156200365e5780601f1062003632576101008083540402835291602001916200365e565b820191906000526020600020905b8154815290600101906020018083116200364057829003601f168201915b5050505050815260200160018201805462003679906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620036a7906200a156565b8015620036f85780601f10620036cc57610100808354040283529160200191620036f8565b820191906000526020600020905b815481529060010190602001808311620036da57829003601f168201915b5050505050815260200160028201805462003713906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462003741906200a156565b8015620037925780601f10620037665761010080835404028352916020019162003792565b820191906000526020600020905b8154815290600101906020018083116200377457829003601f168201915b50505050508152602001600382018054620037ad906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620037db906200a156565b80156200382c5780601f1062003800576101008083540402835291602001916200382c565b820191906000526020600020905b8154815290600101906020018083116200380e57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620038cb57505050919092525050506001600160a01b0380891660009081526041602090815260408083208151610180810183528154861681526001820154861693810193909352600281015490941690820152600383015460608201526004830180549495509193909291608084019162003956906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462003984906200a156565b8015620039d55780601f10620039a957610100808354040283529160200191620039d5565b820191906000526020600020905b815481529060010190602001808311620039b757829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462003a00906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462003a2e906200a156565b801562003a7f5780601f1062003a535761010080835404028352916020019162003a7f565b820191906000526020600020905b81548152906001019060200180831162003a6157829003601f168201915b5050505050815260200160018201805462003a9a906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462003ac8906200a156565b801562003b195780601f1062003aed5761010080835404028352916020019162003b19565b820191906000526020600020905b81548152906001019060200180831162003afb57829003601f168201915b5050505050815260200160028201805462003b34906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462003b62906200a156565b801562003bb35780601f1062003b875761010080835404028352916020019162003bb3565b820191906000526020600020905b81548152906001019060200180831162003b9557829003601f168201915b5050505050815260200160038201805462003bce906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462003bfc906200a156565b801562003c4d5780601f1062003c215761010080835404028352916020019162003c4d565b820191906000526020600020905b81548152906001019060200180831162003c2f57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162003cec5750505050508152505090508060e00151801562003d2f5750876001600160a01b0316836001600160a01b031614155b1562003d4e57604051636468920360e01b815260040160405180910390fd5b60408083015190516352e82ce560e11b81526001600160a01b038581166004830152602482018a9052600092169063a5d059ca906044016020604051808303816000875af115801562003da5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003dcb91906200a205565b905060375481101562003df15760405163dc6f0bdd60e01b815260040160405180910390fd5b896001600160a01b0316846001600160a01b031614801562003e8657506036546040808501519051630913db4760e01b81526001600160a01b038d8116600483015290911690630913db4790602401602060405180830381865afa15801562003e5e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062003e8491906200a205565b105b1562003ea5576040516317b204bf60e11b815260040160405180910390fd5b6000620186a0603a548362003ebb91906200a2a2565b62003ec791906200a1cc565b9050600083604001516001600160a01b03168260405160006040518083038185875af1925050503d806000811462003f1c576040519150601f19603f3d011682016040523d82523d6000602084013e62003f21565b606091505b505090508062003f44576040516312171d8360e31b815260040160405180910390fd5b62003f5082846200a28c565b60408086015190516317066a5760e21b81526001600160a01b03898116600483015292955060009290911690635c19a95c90869060240160206040518083038185885af115801562003fa6573d6000803e3d6000fd5b50505050506040513d601f19601f8201168201806040525081019062003fcd91906200a205565b9050866001600160a01b03168c6001600160a01b03168e6001600160a01b03167ffdac6e81913996d95abcc289e90f2d8bd235487ce6fe6f821e7d21002a1915b48e858960405162004032939291909283526020830191909152604082015260600190565b60405180910390a46040805160028082526060820183526000926020830190803683370190505090508660400151816000815181106200407657620040766200a25a565b60200260200101906001600160a01b031690816001600160a01b031681525050856040015181600181518110620040b157620040b16200a25a565b6001600160a01b0390921660209283029190910190910152604051634484077560e01b815261200590634484077590620040f29084908c906004016200a2bc565b600060405180830381600087803b1580156200410d57600080fd5b505af115801562004122573d6000803e3d6000fd5b505050508a1562004194576120056001600160a01b031663e5ed5b1e898f6040518363ffffffff1660e01b81526004016200415f9291906200a18c565b600060405180830381600087803b1580156200417a57600080fd5b505af11580156200418f573d6000803e3d6000fd5b505050505b50506034805460ff19169055505050505050505050505050565b60005462010000900460ff1615620041d957604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200420b5760405163b1d02c3d60e01b815260040160405180910390fd5b6200421562008f06565b62004222603f8262008ced565b620042405760405163056e881160e01b815260040160405180910390fd5b60006200424c62008f06565b6001600160a01b0381166000908152604160205260409020600c8101549192509042906200427e90610258906200a1ef565b11156200429e57604051631f92cdbd60e11b815260040160405180910390fd5b60098101546001600160401b03600160401b90910481169085161115620042d85760405163dc81db8560e01b815260040160405180910390fd5b60098101546000906001600160401b03908116908616101562004316576009820154620043109086906001600160401b03166200a2e8565b62004330565b600982015462004330906001600160401b0316866200a2e8565b60098301546001600160401b039182169250600160801b9004168111156200436b5760405163dc81db8560e01b815260040160405180910390fd5b60098201805467ffffffffffffffff19166001600160401b03871690811790915542600c8401556040519081526001600160a01b038416907f78cdd96edf59e09cfd4d26ef6ef6c92d166effe6a40970c54821206d541932cb9060200160405180910390a25050505050565b60608060606000620043ea603f62009065565b90508086101562004a7357841562004403578462004405565b805b94506000856200441688846200a28c565b116200442e576200442887836200a28c565b62004430565b855b9050806001600160401b038111156200444d576200444d6200992f565b60405190808252806020026020018201604052801562004477578160200160208202803683370190505b509450806001600160401b038111156200449557620044956200992f565b604051908082528060200260200182016040528015620044bf578160200160208202803683370190505b509350806001600160401b03811115620044dd57620044dd6200992f565b6040519080825280602002602001820160405280156200451257816020015b6060815260200190600190039081620044fc5790505b50925060005b8181101562004a705760006200453c62004533838b6200a1ef565b603f9062009070565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082015260048301805494955091939092916080840191620045a9906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620045d7906200a156565b8015620046285780601f10620045fc5761010080835404028352916020019162004628565b820191906000526020600020905b8154815290600101906020018083116200460a57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462004653906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462004681906200a156565b8015620046d25780601f10620046a657610100808354040283529160200191620046d2565b820191906000526020600020905b815481529060010190602001808311620046b457829003601f168201915b50505050508152602001600182018054620046ed906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200471b906200a156565b80156200476c5780601f1062004740576101008083540402835291602001916200476c565b820191906000526020600020905b8154815290600101906020018083116200474e57829003601f168201915b5050505050815260200160028201805462004787906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620047b5906200a156565b8015620048065780601f10620047da5761010080835404028352916020019162004806565b820191906000526020600020905b815481529060010190602001808311620047e857829003601f168201915b5050505050815260200160038201805462004821906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200484f906200a156565b8015620048a05780601f106200487457610100808354040283529160200191620048a0565b820191906000526020600020905b8154815290600101906020018083116200488257829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b8154815260200190600101908083116200493f57505050505081525050905080600001518884815181106200497857620049786200a25a565b60200260200101906001600160a01b031690816001600160a01b0316815250508060e0015162004a115780604001516001600160a01b03166315d1f8986040518163ffffffff1660e01b8152600401602060405180830381865afa158015620049e5573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062004a0b91906200a205565b62004a14565b60005b87848151811062004a295762004a296200a25a565b602002602001018181525050806080015186848151811062004a4f5762004a4f6200a25a565b602002602001018190525050508062004a68906200a270565b905062004518565b50505b92959194509250565b60005462010000900460ff161562004aa757604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562004ad95760405163b1d02c3d60e01b815260040160405180910390fd5b3362004ae7603f8262008ced565b1562004b0657604051635f28f62b60e01b815260040160405180910390fd5b6001600160a01b038181166000908152604d6020526040902054161562004b4057604051631a0a9b9f60e21b815260040160405180910390fd5b6001600160a01b03888116600090815260436020526040902054161562004b7a57604051631e6f587560e11b815260040160405180910390fd5b60006001600160a01b03166045888860405162004b999291906200a1a6565b908152604051908190036020019020546001600160a01b03161462004bd1576040516311fdb94760e01b815260040160405180910390fd5b600062004bdf83806200a312565b60405160200162004bf29291906200a1a6565b60408051601f1981840301815291815281516020928301206000818152604290935291205490915060ff161562004c3c5760405163c0bf414360e01b815260040160405180910390fd5b600062004c52670de0b6b3a7640000346200a28c565b905060365481101562004c78576040516317b204bf60e11b815260040160405180910390fd5b6001600160a01b038a1662004ca057604051636520611b60e11b815260040160405180910390fd5b61138862004cb5604087016020880162009c4e565b6001600160401b0316118062004cfb575062004cd8604086016020870162009c4e565b6001600160401b031662004cf0602087018762009c4e565b6001600160401b0316115b8062004d3a575062004d14604086016020870162009c4e565b6001600160401b031662004d2f606087016040880162009c4e565b6001600160401b0316115b1562004d595760405163dc81db8560e01b815260040160405180910390fd5b62004da462004d6985806200a312565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200907e92505050565b62004dc257604051635dba5ad760e01b815260040160405180910390fd5b62004dd1838a8a8a8a62009220565b62004def57604051631647e3cb60e11b815260040160405180910390fd5b600062004e3d8462004e0287806200a312565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152506200935092505050565b905062004e4c603f8562009451565b506000838152604260209081526040808320805460ff191660019081179091556001600160a01b0380891680865260419094529190932080548f83166001600160a01b03199182161782559381018054851690931790925560028201805491851691909316179091554260038201556004810162004ecc8b8d836200a3ba565b50856005820162004ede82826200a482565b508790506009820162004ef282826200a5bb565b505042600c8201556001600160a01b038c81166000908152604360205260409081902080546001600160a01b0319169288169290921790915551859060459062004f40908e908e906200a1a6565b908152602001604051809103902060006101000a8154816001600160a01b0302191690836001600160a01b03160217905550816001600160a01b0316856001600160a01b03168d6001600160a01b03167faecd9fb95e79c75a3a1de93362c6be5fe6ab65770d8614be583884161cd8228d8e8e60405162004fc39291906200a68b565b60405180910390a460408051848152602081018590526001600160a01b0387169182917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a360408051670de0b6b3a7640000808252602082015261dead916001600160a01b038816917f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e04910160405180910390a3604051633041949b60e01b815261200590633041949b906200508990859089906004016200a18c565b600060405180830381600087803b158015620050a457600080fd5b505af1158015620050b9573d6000803e3d6000fd5b50505050505050505050505050505050565b604080516060810182526000808252602082018190529181019190915281620050f6603f8262008ced565b620051145760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b031660009081526041602090815260409182902082516060810184526009909101546001600160401b038082168352600160401b8204811693830193909352600160801b90049091169181019190915290565b6001600160a01b03808216600090815260416020908152604080832081516101808101835281548616815260018201548616938101939093526002810154909416908201526003830154606082810191909152600484018054919491608084019190620051dd906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200520b906200a156565b80156200525c5780601f1062005230576101008083540402835291602001916200525c565b820191906000526020600020905b8154815290600101906020018083116200523e57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462005287906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620052b5906200a156565b8015620053065780601f10620052da5761010080835404028352916020019162005306565b820191906000526020600020905b815481529060010190602001808311620052e857829003601f168201915b5050505050815260200160018201805462005321906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200534f906200a156565b8015620053a05780601f106200537457610100808354040283529160200191620053a0565b820191906000526020600020905b8154815290600101906020018083116200538257829003601f168201915b50505050508152602001600282018054620053bb906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620053e9906200a156565b80156200543a5780601f106200540e576101008083540402835291602001916200543a565b820191906000526020600020905b8154815290600101906020018083116200541c57829003601f168201915b5050505050815260200160038201805462005455906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462005483906200a156565b8015620054d45780601f10620054a857610100808354040283529160200191620054d4565b820191906000526020600020905b815481529060010190602001808311620054b657829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620055735750505091909252505050608001519392505050565b3361100114620055c457604051630f22c43960e41b81526110016004820152602401620012e3565b6001600160a01b0380821660009081526043602052604090205416620055ec603f8262008ced565b6200560a5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038181166000908152604160205260408082206002810154603b54925163045bc4d160e41b81526004810193909352909316906345bc4d10906024016020604051808303816000875af11580156200566d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906200569391906200a205565b90506000603d5442620056a791906200a1ef565b9050620056b5838262008d98565b836001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb282846001604051620056f5939291906200a21f565b60405180910390a26002830154604051633041949b60e01b815261200591633041949b9162005733916001600160a01b03169088906004016200a18c565b600060405180830381600087803b1580156200574e57600080fd5b505af115801562005763573d6000803e3d6000fd5b505050505050505050565b600054610100900460ff16158080156200578f5750600054600160ff909116105b80620057ab5750303b158015620057ab575060005460ff166001145b620058105760405162461bcd60e51b815260206004820152602e60248201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160448201526d191e481a5b9a5d1a585b1a5e995960921b6064820152608401620012e3565b6000805460ff19166001179055801562005834576000805461ff0019166101001790555b334114620058555760405163022d8c9560e31b815260040160405180910390fd5b3a1562005875576040516383f1b1d360e01b815260040160405180910390fd5b611388603555686c6b935b8bbd400000603655670de0b6b3a7640000603755602d603855607860398190556002603a819055678ac7230489e80000603b55680ad78ebc5ac6200000603c55603d9190915560b4603e55604a55620058ed7304d63abcd2b9b1baa327f2dda0f873f197ccd18662009468565b80156200190e576000805461ff0019169055604051600181527f7f26b83ff96e1f2b6a682f133852f6798a09c465da95921460cefb38474024989060200160405180910390a150565b33612000146200595e57604051630f22c43960e41b81526120006004820152602401620012e3565b60405162461bcd60e51b815260206004820152600a60248201526919195c1c9958d85d195960b21b6044820152606401620012e3565b600054630100000090046001600160a01b03163314620059c7576040516306fbb1e360e01b815260040160405180910390fd5b60005462010000900460ff1615620059f257604051631785c68160e01b815260040160405180910390fd5b6000805462ff00001916620100001781556040517f9e87fac88ff661f02d44f95383c817fece4bce600a3dab7a54406878b965e7529190a1565b600062005a3b603f8462008ced565b62005a595760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383811660009081526041602052604090819020600201549051636bbf224960e01b815260048101859052911690636bbf2249906024015b602060405180830381865afa15801562005ab6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062005adc91906200a205565b90505b92915050565b60005462010000900460ff161562005b1057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562005b425760405163b1d02c3d60e01b815260040160405180910390fd5b8162005b50603f8262008ced565b62005b6e5760405163056e881160e01b815260040160405180910390fd5b603754349081101562005b945760405163dc6f0bdd60e01b815260040160405180910390fd5b6001600160a01b038085166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054339491608084019162005bfc906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462005c2a906200a156565b801562005c7b5780601f1062005c4f5761010080835404028352916020019162005c7b565b820191906000526020600020905b81548152906001019060200180831162005c5d57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462005ca6906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462005cd4906200a156565b801562005d255780601f1062005cf95761010080835404028352916020019162005d25565b820191906000526020600020905b81548152906001019060200180831162005d0757829003601f168201915b5050505050815260200160018201805462005d40906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462005d6e906200a156565b801562005dbf5780601f1062005d935761010080835404028352916020019162005dbf565b820191906000526020600020905b81548152906001019060200180831162005da157829003601f168201915b5050505050815260200160028201805462005dda906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462005e08906200a156565b801562005e595780601f1062005e2d5761010080835404028352916020019162005e59565b820191906000526020600020905b81548152906001019060200180831162005e3b57829003601f168201915b5050505050815260200160038201805462005e74906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462005ea2906200a156565b801562005ef35780601f1062005ec75761010080835404028352916020019162005ef3565b820191906000526020600020905b81548152906001019060200180831162005ed557829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162005f925750505050508152505090508060e00151801562005fd55750856001600160a01b0316826001600160a01b031614155b1562005ff457604051636468920360e01b815260040160405180910390fd5b60408082015190516317066a5760e21b81526001600160a01b0384811660048301526000921690635c19a95c90869060240160206040518083038185885af115801562006045573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906200606c91906200a205565b9050826001600160a01b0316876001600160a01b03167f24d7bda8602b916d64417f0dbfe2e2e88ec9b1157bd9f596dfdb91ba26624e048387604051620060bd929190918252602082015260400190565b60405180910390a36040808301519051633041949b60e01b815261200591633041949b91620060f2919087906004016200a18c565b600060405180830381600087803b1580156200610d57600080fd5b505af115801562006122573d6000803e3d6000fd5b50505050851562001907576040516372f6ad8f60e11b81526120059063e5ed5b1e90620061569086908b906004016200a18c565b600060405180830381600087803b1580156200617157600080fd5b505af115801562006186573d6000803e3d6000fd5b5050505050505050505050565b60005462010000900460ff1615620061be57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620061f05760405163b1d02c3d60e01b815260040160405180910390fd5b620061fa62008e8c565b62006207603f8262008ced565b620062255760405163056e881160e01b815260040160405180910390fd5b60006200623162008e8c565b6001600160a01b0381166000908152604f6020526040812080549293509190859003620063085760005b81811015620062dc57836001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a848381548110620062a457620062a46200a25a565b9060005260206000200154604051620062bf91815260200190565b60405180910390a280620062d3816200a270565b9150506200625b565b506001600160a01b0383166000908152604f6020526040812062006300916200975a565b505050505050565b60005b85811015620064665760008787838181106200632b576200632b6200a25a565b90506020020135905060005b838110156200644e57818582815481106200635657620063566200a25a565b906000526020600020015403620064395784620063756001866200a28c565b815481106200638857620063886200a25a565b9060005260206000200154858281548110620063a857620063a86200a25a565b906000526020600020018190555084805480620063c957620063c96200a6a1565b600190038181906000526020600020016000905590558380620063ec906200a6b7565b945050856001600160a01b03167f08e60c1b84aab23d99a7262015e647d5ffd6c6e08f78205e1df6774c48e1427a836040516200642b91815260200190565b60405180910390a26200644e565b8062006445816200a270565b91505062006337565b505080806200645d906200a270565b9150506200630b565b50815460000362006300576001600160a01b0383166000908152604f6020526040812062006300916200975a565b505050565b620064c56040518060800160405280606081526020016060815260200160608152602001606081525090565b81620064d3603f8262008ced565b620064f15760405163056e881160e01b815260040160405180910390fd5b6001600160a01b0383166000908152604160205260409081902081516080810190925260050180548290829062006528906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462006556906200a156565b8015620065a75780601f106200657b57610100808354040283529160200191620065a7565b820191906000526020600020905b8154815290600101906020018083116200658957829003601f168201915b50505050508152602001600182018054620065c2906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620065f0906200a156565b8015620066415780601f10620066155761010080835404028352916020019162006641565b820191906000526020600020905b8154815290600101906020018083116200662357829003601f168201915b505050505081526020016002820180546200665c906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200668a906200a156565b8015620066db5780601f10620066af57610100808354040283529160200191620066db565b820191906000526020600020905b815481529060010190602001808311620066bd57829003601f168201915b50505050508152602001600382018054620066f6906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462006724906200a156565b8015620067755780601f10620067495761010080835404028352916020019162006775565b820191906000526020600020905b8154815290600101906020018083116200675757829003601f168201915b505050505081525050915050919050565b60005462010000900460ff1615620067b157604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620067e35760405163b1d02c3d60e01b815260040160405180910390fd5b620067ef828262009501565b5050565b33611007146200681b57604051630f22c43960e41b81526110076004820152602401620012e3565b620068886040518060400160405280601081526020016f1d1c985b9cd9995c91d85cd31a5b5a5d60821b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b15620069435760208114620068ba5783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f8401819004810282018101909252828152600091620068fd9185858083850183828082843760009201919091525092939250506200966a9050565b90506108fc81108062006911575061271081115b156200693a5784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b60355562007760565b620069b46040518060400160405280601481526020017336b4b729b2b6332232b632b3b0ba34b7b721272160611b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b1562006a7e5760208114620069e65783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f840181900481028201810190925282815260009162006a299185858083850183828082843760009201919091525092939250506200966a9050565b9050683635c9adc5dea0000081108062006a4c575069152d02c7e14af680000081115b1562006a755784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b60365562007760565b62006af1604051806040016040528060168152602001756d696e44656c65676174696f6e424e424368616e676560501b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b1562006bb8576020811462006b235783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f840181900481028201810190925282815260009162006b669185858083850183828082843760009201919091525092939250506200966a9050565b905067016345785d8a000081108062006b865750678ac7230489e8000081115b1562006baf5784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b60375562007760565b62006c29604051806040016040528060148152602001736d6178456c656374656456616c696461746f727360601b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b1562006ce1576020811462006c5b5783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f840181900481028201810190925282815260009162006c9e9185858083850183828082843760009201919091525092939250506200966a9050565b905080158062006caf57506101f481115b1562006cd85784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b60385562007760565b62006d4a6040518060400160405280600c81526020016b1d5b989bdb9914195c9a5bd960a21b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b1562006e07576020811462006d7c5783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f840181900481028201810190925282815260009162006dbf9185858083850183828082843760009201919091525092939250506200966a9050565b90506203f48081108062006dd5575062278d0081115b1562006dfe5784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b60395562007760565b62006e7560405180604001604052806011815260200170726564656c65676174654665655261746560781b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b1562006f22576020811462006ea75783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f840181900481028201810190925282815260009162006eea9185858083850183828082843760009201919091525092939250506200966a9050565b9050606481111562006f195784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b603a5562007760565b62006f9260405180604001604052806013815260200172191bdddb9d1a5b5954db185cda105b5bdd5b9d606a1b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b1562007054576020811462006fc45783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f8401819004810282018101909252828152600091620070079185858083850183828082843760009201919091525092939250506200966a9050565b9050670de0b6b3a7640000811080620070225750603c548110155b156200704b5784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b603b5562007760565b620070c26040518060400160405280601181526020017019995b1bdb9e54db185cda105b5bdd5b9d607a1b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b15620071845760208114620070f45783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f8401819004810282018101909252828152600091620071379185858083850183828082843760009201919091525092939250506200966a9050565b9050678ac7230489e80000811080620071525750603b548111155b156200717b5784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b603c5562007760565b620071f16040518060400160405280601081526020016f646f776e74696d654a61696c54696d6560801b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b15620072ae5760208114620072235783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f8401819004810282018101909252828152600091620072669185858083850183828082843760009201919091525092939250506200966a9050565b9050620151808110806200727c5750603e548110155b15620072a55784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b603d5562007760565b620073196040518060400160405280600e81526020016d66656c6f6e794a61696c54696d6560901b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b15620073d657602081146200734b5783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f84018190048102820181019092528281526000916200738e9185858083850183828082843760009201919091525092939250506200966a9050565b90506203f480811080620073a45750603d548111155b15620073cd5784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b603e5562007760565b620074506040518060400160405280601c81526020017f6d617846656c6f6e794265747765656e42726561746865426c6f636b0000000081525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b15620074fc5760208114620074825783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f8401819004810282018101909252828152600091620074c59185858083850183828082843760009201919091525092939250506200966a9050565b905080600003620074f35784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604a5562007760565b6200756a6040518060400160405280601181526020017039ba30b5b2a43ab1283937ba32b1ba37b960791b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b156200762a57601481146200759c5783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b6000620075e4601484848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200966a9050565b90506001600160a01b038116620076185784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b62007623816200966f565b5062007760565b620076916040518060400160405280600a8152602001696d61784e6f646549447360b01b81525085858080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525092939250506200960d9050565b156200773d5760208114620076c35783838383604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604080516020601f8401819004810282018101909252828152600091620077069185858083850183828082843760009201919091525092939250506200966a9050565b905080600003620077345784848484604051630a5a604160e01b8152600401620012e394939291906200a6d1565b604e5562007760565b838383836040516325ee20d560e21b8152600401620012e394939291906200a6d1565b7ff1ce9b2cbf50eeb05769a29e2543fd350cab46894a7dd9978a12d534bb20e633848484846040516200779794939291906200a6d1565b60405180910390a150505050565b60005462010000900460ff1615620077d057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620078025760405163b1d02c3d60e01b815260040160405180910390fd5b816000816001600160401b038111156200782057620078206200992f565b6040519080825280602002602001820160405280156200784a578160200160208202803683370190505b5090506000805b838110156200794857620078938787838181106200787357620078736200a25a565b90506020020160208101906200788a9190620097c0565b603f9062008ced565b620078b15760405163056e881160e01b815260040160405180910390fd5b60416000888884818110620078ca57620078ca6200a25a565b9050602002016020810190620078e19190620097c0565b6001600160a01b03908116825260208201929092526040016000206002015484519116925082908490839081106200791d576200791d6200a25a565b6001600160a01b039092166020928302919091019091015262007940816200a270565b905062007851565b50604051634484077560e01b8152612005906344840775906200337990859088906004016200a2bc565b606080600062007983603f62009065565b90508085101562007b475783156200799c57836200799e565b805b9350600084620079af87846200a28c565b11620079c757620079c186836200a28c565b620079c9565b845b9050806001600160401b03811115620079e657620079e66200992f565b60405190808252806020026020018201604052801562007a10578160200160208202803683370190505b509350806001600160401b0381111562007a2e5762007a2e6200992f565b60405190808252806020026020018201604052801562007a58578160200160208202803683370190505b50925060005b8181101562007b445762007a776200453382896200a1ef565b85828151811062007a8c5762007a8c6200a25a565b60200260200101906001600160a01b031690816001600160a01b0316815250506041600086838151811062007ac55762007ac56200a25a565b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060020160009054906101000a90046001600160a01b031684828151811062007b195762007b196200a25a565b6001600160a01b039092166020928302919091019091015262007b3c816200a270565b905062007a5e565b50505b9250925092565b60008162007b5e603f8262008ced565b62007b7c5760405163056e881160e01b815260040160405180910390fd5b50506001600160a01b03166000908152604160205260409020600c015490565b336110011462007bc457604051630f22c43960e41b81526110016004820152602401620012e3565b60005462010000900460ff161562007bef57604051631785c68160e01b815260040160405180910390fd5b6001600160a01b038082166000908152604360205260409020541662007c17603f8262008ced565b62007c355760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03811660009081526041602052604081209062007c5c610258426200a1cc565b604a546000828152604b60205260409020549192501162007c905760405163bd52fcdb60e01b815260040160405180910390fd5b6000818152604b6020526040812080546001929062007cb19084906200a1ef565b90915550506001600160a01b0384166000908152604460205260409020541580159062007d0557506001600160a01b038416600090815260446020526040902054429062007d0390610258906200a1ef565b105b1562007d24576040516330abb81d60e21b815260040160405180910390fd5b60008062007d3485600062008d10565b915091508162007d5757604051631b919bb160e11b815260040160405180910390fd5b6002840154603c5460405163045bc4d160e41b815260048101919091526000916001600160a01b0316906345bc4d10906024016020604051808303816000875af115801562007daa573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062007dd091906200a205565b905062007dde858362008d98565b84546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b15801562007e2557600080fd5b505af115801562007e3a573d6000803e3d6000fd5b50505050856001600160a01b03167f6e9a2ee7aee95665e3a774a212eb11441b217e3e4656ab9563793094689aabb28383600060405162007e7e939291906200a21f565b60405180910390a26002850154604051633041949b60e01b815261200591633041949b9162006156916001600160a01b0316908a906004016200a18c565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384938493849390929160808401919062007f2d906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462007f5b906200a156565b801562007fac5780601f1062007f805761010080835404028352916020019162007fac565b820191906000526020600020905b81548152906001019060200180831162007f8e57829003601f168201915b505050505081526020016005820160405180608001604052908160008201805462007fd7906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462008005906200a156565b8015620080565780601f106200802a5761010080835404028352916020019162008056565b820191906000526020600020905b8154815290600101906020018083116200803857829003601f168201915b5050505050815260200160018201805462008071906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200809f906200a156565b8015620080f05780601f10620080c457610100808354040283529160200191620080f0565b820191906000526020600020905b815481529060010190602001808311620080d257829003601f168201915b505050505081526020016002820180546200810b906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462008139906200a156565b80156200818a5780601f106200815e576101008083540402835291602001916200818a565b820191906000526020600020905b8154815290600101906020018083116200816c57829003601f168201915b50505050508152602001600382018054620081a5906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620081d3906200a156565b8015620082245780601f10620081f85761010080835404028352916020019162008224565b820191906000526020600020905b8154815290600101906020018083116200820657829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b815481526020019060010190808311620082c35750505091909252505050606081015160e0820151610100909201519097919650945092505050565b60005462010000900460ff16156200832a57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff16156200835c5760405163b1d02c3d60e01b815260040160405180910390fd5b6200836662008f06565b62008373603f8262008ced565b620083915760405163056e881160e01b815260040160405180910390fd5b60006200839d62008f06565b6001600160a01b0381166000908152604160205260409020600c810154919250904290620083cf90610258906200a1ef565b1115620083ef57604051631f92cdbd60e11b815260040160405180910390fd5b60058101805462008400906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200842e906200a156565b80156200847f5780601f1062008453576101008083540402835291602001916200847f565b820191906000526020600020905b8154815290600101906020018083116200846157829003601f168201915b50505082875250859160058401915081906200849c90826200a707565b5060208201516001820190620084b390826200a707565b5060408201516002820190620084ca90826200a707565b5060608201516003820190620084e190826200a707565b505042600c830155506040516001600160a01b038316907f85d6366b336ade7f106987ec7a8eac1e8799e508aeab045a39d2f63e0dc969d990600090a250505050565b60005462010000900460ff16156200854f57604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff1615620085815760405163b1d02c3d60e01b815260040160405180910390fd5b828114620085a2576040516341abc80160e01b815260040160405180910390fd5b60005b83811015620086135762008600858583818110620085c757620085c76200a25a565b9050602002016020810190620085de9190620097c0565b848484818110620085f357620085f36200a25a565b9050602002013562009501565b6200860b816200a270565b9050620085a5565b5050505050565b6001600160a01b038082166000908152604160209081526040808320815161018081018352815486168152600182015486169381019390935260028101549094169082015260038301546060820152600483018054929384939091608084019162008685906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620086b3906200a156565b8015620087045780601f10620086d85761010080835404028352916020019162008704565b820191906000526020600020905b815481529060010190602001808311620086e657829003601f168201915b50505050508152602001600582016040518060800160405290816000820180546200872f906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200875d906200a156565b8015620087ae5780601f106200878257610100808354040283529160200191620087ae565b820191906000526020600020905b8154815290600101906020018083116200879057829003601f168201915b50505050508152602001600182018054620087c9906200a156565b80601f0160208091040260200160405190810160405280929190818152602001828054620087f7906200a156565b8015620088485780601f106200881c5761010080835404028352916020019162008848565b820191906000526020600020905b8154815290600101906020018083116200882a57829003601f168201915b5050505050815260200160028201805462008863906200a156565b80601f016020809104026020016040519081016040528092919081815260200182805462008891906200a156565b8015620088e25780601f10620088b657610100808354040283529160200191620088e2565b820191906000526020600020905b815481529060010190602001808311620088c457829003601f168201915b50505050508152602001600382018054620088fd906200a156565b80601f01602080910402602001604051908101604052809291908181526020018280546200892b906200a156565b80156200897c5780601f1062008950576101008083540402835291602001916200897c565b820191906000526020600020905b8154815290600101906020018083116200895e57829003601f168201915b505050919092525050508152604080516060808201835260098501546001600160401b038082168452600160401b82048116602080860191909152600160801b9092041683850152840191909152600a84015460ff16151582840152600b84015490830152600c8301546080830152600d8301546001600160a01b031660a0830152805161026081019182905260c09092019190600e84019060139082845b81548152602001906001019080831162008a1b5750505091909252505050604001519392505050565b600062008a53603f8462008ced565b62008a715760405163056e881160e01b815260040160405180910390fd5b6001600160a01b038381166000908152604160205260409081902060020154905163aa1966cd60e01b81526004810185905291169063aa1966cd9060240162005a98565b60005462010000900460ff161562008ae057604051631785c68160e01b815260040160405180910390fd5b3360009081526001602052604090205460ff161562008b125760405163b1d02c3d60e01b815260040160405180910390fd5b62008b1c62008f06565b62008b29603f8262008ced565b62008b475760405163056e881160e01b815260040160405180910390fd5b600062008b5362008f06565b905062008b64818787878762009220565b62008b8257604051631647e3cb60e11b815260040160405180910390fd5b60006001600160a01b03166045878760405162008ba19291906200a1a6565b908152604051908190036020019020546001600160a01b03161462008bd9576040516311fdb94760e01b815260040160405180910390fd5b6001600160a01b0381166000908152604160205260409020600c810154429062008c0790610258906200a1ef565b111562008c2757604051631f92cdbd60e11b815260040160405180910390fd5b4260468260040160405162008c3d91906200a7cf565b908152604051908190036020019020556004810162008c5e8789836200a3ba565b5042600c820155604051829060459062008c7c908a908a906200a1a6565b90815260405190819003602001812080546001600160a01b039384166001600160a01b0319909116179055908316907f783156582145bd0ff7924fae6953ba054cf1233eb60739a200ddb10de068ff0d9062008cdc908a908a906200a68b565b60405180910390a250505050505050565b6001600160a01b0381166000908152600183016020526040812054151562005adc565b6000806000848460405160200162008d2a9291906200a84d565b60408051601f1981840301815291815281516020928301206000818152604c9093529120549091504281111562008d6a57600080935093505050620026a7565b603e5462008d7990426200a1ef565b6000928352604c60205260409092208290555060019590945092505050565b6000600162008da8603f62009065565b62008db491906200a28c565b604954108015915062008e005760018301546040516001600160a01b03909116907f2afdc18061ac21cff7d9f11527ab9c8dec6fabd4edf6f894ed634bebd6a20d4590600090a2505050565b82600b015482111562008e1557600b83018290555b600a83015460ff166200649457600a8301805460ff191660019081179091556049805460009062008e489084906200a1ef565b909155505060018301546040516001600160a01b03909116907f4905ac32602da3fb8b4b7b00c285e5fc4c6c2308cc908b4a1e4e9625a29c90a390600090a2505050565b336000908152604360205260408120546001600160a01b03161580159062008ec1575033600090815260446020526040902054155b1562008ee45750336000908152604360205260409020546001600160a01b031690565b62008eee62008f06565b905090565b604e5460000362008f04576005604e555b565b336000908152604d60205260408120546001600160a01b03161562008f425750336000908152604d60205260409020546001600160a01b031690565b503390565b6001600160a01b0381166000908152604160205260409020600a81015460ff161562008f71575050565b6036546002820154604051630913db4760e01b81526001600160a01b03858116600483015290911690630913db4790602401602060405180830381865afa15801562008fc1573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062008fe791906200a205565b1015620067ef576200900981603d54426200900391906200a1ef565b62008d98565b80546040516335409f7f60e01b81526001600160a01b039091166004820152611000906335409f7f90602401600060405180830381600087803b1580156200905057600080fd5b505af115801562006300573d6000803e3d6000fd5b600062005adf825490565b600062005adc8383620096db565b60008082905060038151108062009096575060098151115b15620090a55750600092915050565b604181600081518110620090bd57620090bd6200a25a565b016020015160f81c1080620090ef5750605a81600081518110620090e557620090e56200a25a565b016020015160f81c115b15620090fe5750600092915050565b60015b8151811015620092165760308282815181106200912257620091226200a25a565b016020015160f81c108062009153575060398282815181106200914957620091496200a25a565b016020015160f81c115b8015620091a3575060418282815181106200917257620091726200a25a565b016020015160f81c1080620091a35750605a8282815181106200919957620091996200a25a565b016020015160f81c115b8015620091f357506061828281518110620091c257620091c26200a25a565b016020015160f81c1080620091f35750607a828281518110620091e957620091e96200a25a565b016020015160f81c115b1562009203575060009392505050565b6200920e816200a270565b905062009101565b5060019392505050565b600060308414158062009234575060608214155b15620092435750600062009347565b6000868686466040516020016200925e94939291906200a897565b60408051808303601f1901815282825280516020918201208184528383019092529092506000919060208201818036833701905050905081602082015260008186868a8a604051602001620092b89594939291906200a8c4565b60408051808303601f190181526001808452838301909252925060009190602082018180368337019050509050815160016020830182602086016066600019fa6200930257600080fd5b506000816000815181106200931b576200931b6200a25a565b016020015160f81c9050600181146200933d5760009550505050505062009347565b6001955050505050505b95945050505050565b60008061200361dead60405162009367906200977a565b6001600160a01b03928316815291166020820152606060408201819052600090820152608001604051809103906000f080158015620093aa573d6000803e3d6000fd5b509050806001600160a01b031663f399e22e3486866040518463ffffffff1660e01b8152600401620093de9291906200a8fc565b6000604051808303818588803b158015620093f857600080fd5b505af11580156200940d573d6000803e3d6000fd5b50506040516001600160a01b038086169450881692507fd481492e4e93bb36b4c12a5af93f03be3bf04b454dfbc35dd2663fa26f44d5b09150600090a39392505050565b600062005adc836001600160a01b03841662009708565b600054610100900460ff16620094d55760405162461bcd60e51b815260206004820152602b60248201527f496e697469616c697a61626c653a20636f6e7472616374206973206e6f74206960448201526a6e697469616c697a696e6760a81b6064820152608401620012e3565b600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b816200950f603f8262008ced565b6200952d5760405163056e881160e01b815260040160405180910390fd5b6001600160a01b03838116600090815260416020526040808220600201549051635569f64b60e11b8152336004820152602481018690529192169063aad3ec96906044016020604051808303816000875af115801562009591573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620095b791906200a205565b9050336001600160a01b0316846001600160a01b03167ff7a40077ff7a04c7e61f6f26fb13774259ddf1b6bce9ecf26a8276cdd399268383604051620095ff91815260200190565b60405180910390a350505050565b6000816040516020016200962291906200a922565b60405160208183030381529060405280519060200120836040516020016200964b91906200a922565b6040516020818303038152906040528051906020012014905092915050565b015190565b600080546040516001600160a01b0380851693630100000090930416917f44fc1b38a4abaa91ebd1b628a5b259a698f86238c8217d68f516e87769c60c0b91a3600080546001600160a01b039092166301000000026301000000600160b81b0319909216919091179055565b6000826000018281548110620096f557620096f56200a25a565b9060005260206000200154905092915050565b6000818152600183016020526040812054620097515750815460018181018455600084815260208082209093018490558454848252828601909352604090209190915562005adf565b50600062005adf565b50805460008255906000526020600020908101906200190e919062009788565b610e96806200a94183390190565b5b808211156200979f576000815560010162009789565b5090565b80356001600160a01b0381168114620097bb57600080fd5b919050565b600060208284031215620097d357600080fd5b62005adc82620097a3565b60008083601f840112620097f157600080fd5b5081356001600160401b038111156200980957600080fd5b602083019150836020828501011115620026a757600080fd5b600080602083850312156200983657600080fd5b82356001600160401b038111156200984d57600080fd5b6200985b85828601620097de565b90969095509350505050565b6000806000604084860312156200987d57600080fd5b833560ff811681146200988f57600080fd5b925060208401356001600160401b03811115620098ab57600080fd5b620098b986828701620097de565b9497909650939450505050565b60005b83811015620098e3578181015183820152602001620098c9565b50506000910152565b6000815180845262009906816020860160208601620098c6565b601f01601f19169290920160200192915050565b60208152600062005adc6020830184620098ec565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200996a576200996a6200992f565b60405290565b60006001600160401b03808411156200998d576200998d6200992f565b604051601f8501601f19908116603f01168101908282118183101715620099b857620099b86200992f565b81604052809350858152868686011115620099d257600080fd5b858560208301376000602087830101525050509392505050565b600060208284031215620099ff57600080fd5b81356001600160401b0381111562009a1657600080fd5b8201601f8101841362009a2857600080fd5b62009a398482356020840162009970565b949350505050565b60008083601f84011262009a5457600080fd5b5081356001600160401b0381111562009a6c57600080fd5b6020830191508360208260051b8501011115620026a757600080fd5b6000806020838503121562009a9c57600080fd5b82356001600160401b0381111562009ab357600080fd5b6200985b8582860162009a41565b600081518084526020808501945080840160005b8381101562009afc5781516001600160a01b03168752958201959082019060010162009ad5565b509495945050505050565b60408152600062009b1c604083018562009ac1565b6020838203818501528185518084528284019150828160051b8501018388016000805b8481101562009b9657878403601f19018652825180518086529088019088860190845b8181101562009b805783518352928a0192918a019160010162009b62565b5050968801969450509186019160010162009b3f565b50919a9950505050505050505050565b6000806040838503121562009bba57600080fd5b62009bc583620097a3565b946020939093013593505050565b80358015158114620097bb57600080fd5b6000806000806080858703121562009bfb57600080fd5b62009c0685620097a3565b935062009c1660208601620097a3565b92506040850135915062009c2d6060860162009bd3565b905092959194509250565b6001600160401b03811681146200190e57600080fd5b60006020828403121562009c6157600080fd5b813562009c6e8162009c38565b9392505050565b6000806040838503121562009c8957600080fd5b50508035926020909101359150565b60808152600062009cad608083018762009ac1565b82810360208481019190915286518083528782019282019060005b8181101562009ce65784518352938301939183019160010162009cc8565b5050848103604086015286518082528282019350600581901b8201830183890160005b8381101562009d3b57601f1985840301875262009d28838351620098ec565b9686019692509085019060010162009d09565b5050809550505050505082606083015295945050505050565b600080600080600080600087890360e081121562009d7157600080fd5b62009d7c89620097a3565b975060208901356001600160401b038082111562009d9957600080fd5b62009da78c838d01620097de565b909950975060408b013591508082111562009dc157600080fd5b62009dcf8c838d01620097de565b90975095508591506060605f198401121562009dea57600080fd5b60608b01945060c08b013592508083111562009e0557600080fd5b505088016080818b03121562009e1a57600080fd5b8091505092959891949750929550565b6000806040838503121562009e3e57600080fd5b62009e4983620097a3565b915062009e596020840162009bd3565b90509250929050565b60208152600082516080602084015262009e8060a0840182620098ec565b90506020840151601f198085840301604086015262009ea08383620098ec565b9250604086015191508085840301606086015262009ebf8383620098ec565b9250606086015191508085840301608086015250620093478282620098ec565b6000806000806040858703121562009ef657600080fd5b84356001600160401b038082111562009f0e57600080fd5b62009f1c88838901620097de565b9096509450602087013591508082111562009f3657600080fd5b5062009f4587828801620097de565b95989497509550505050565b60008060006040848603121562009f6757600080fd5b83356001600160401b0381111562009f7e57600080fd5b62009f8c8682870162009a41565b909450925062009fa1905060208501620097a3565b90509250925092565b60608152600062009fbf606083018662009ac1565b828103602084015262009fd3818662009ac1565b915050826040830152949350505050565b600082601f83011262009ff657600080fd5b62005adc8383356020850162009970565b6000602082840312156200a01a57600080fd5b81356001600160401b03808211156200a03257600080fd5b90830190608082860312156200a04757600080fd5b6200a05162009945565b8235828111156200a06157600080fd5b6200a06f8782860162009fe4565b8252506020830135828111156200a08557600080fd5b6200a0938782860162009fe4565b6020830152506040830135828111156200a0ac57600080fd5b6200a0ba8782860162009fe4565b6040830152506060830135828111156200a0d357600080fd5b6200a0e18782860162009fe4565b60608301525095945050505050565b600080600080604085870312156200a10757600080fd5b84356001600160401b03808211156200a11f57600080fd5b6200a12d8883890162009a41565b909650945060208701359150808211156200a14757600080fd5b5062009f458782880162009a41565b600181811c908216806200a16b57607f821691505b602082108103620020d957634e487b7160e01b600052602260045260246000fd5b6001600160a01b0392831681529116602082015260400190565b8183823760009101908152919050565b634e487b7160e01b600052601160045260246000fd5b6000826200a1ea57634e487b7160e01b600052601260045260246000fd5b500490565b8082018082111562005adf5762005adf6200a1b6565b6000602082840312156200a21857600080fd5b5051919050565b8381526020810183905260608101600383106200a24c57634e487b7160e01b600052602160045260246000fd5b826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b6000600182016200a285576200a2856200a1b6565b5060010190565b8181038181111562005adf5762005adf6200a1b6565b808202811582820484141762005adf5762005adf6200a1b6565b6040815260006200a2d1604083018562009ac1565b905060018060a01b03831660208301529392505050565b6001600160401b038281168282160390808211156200a30b576200a30b6200a1b6565b5092915050565b6000808335601e198436030181126200a32a57600080fd5b8301803591506001600160401b038211156200a34557600080fd5b602001915036819003821315620026a757600080fd5b601f8211156200649457600081815260208120601f850160051c810160208610156200a3845750805b601f850160051c820191505b8181101562006300578281556001016200a390565b600019600383901b1c191660019190911b1790565b6001600160401b038311156200a3d4576200a3d46200992f565b6200a3ec836200a3e583546200a156565b836200a35b565b6000601f8411600181146200a41f57600085156200a40a5750838201355b6200a41686826200a3a5565b84555062008613565b600083815260209020601f19861690835b828110156200a45257868501358255602094850194600190920191016200a430565b50868210156200a4705760001960f88860031b161c19848701351681555b505060018560011b0183555050505050565b6200a48e82836200a312565b6001600160401b038111156200a4a8576200a4a86200992f565b6200a4c0816200a4b985546200a156565b856200a35b565b6000601f8211600181146200a4f357600083156200a4de5750838201355b6200a4ea84826200a3a5565b8655506200a550565b600085815260209020601f19841690835b828110156200a52657868501358255602094850194600190920191016200a504565b50848210156200a5445760001960f88660031b161c19848701351681555b505060018360011b0185555b505050506200a56360208301836200a312565b6200a5738183600186016200a3ba565b50506200a58460408301836200a312565b6200a5948183600286016200a3ba565b50506200a5a560608301836200a312565b6200a5b58183600386016200a3ba565b50505050565b81356200a5c88162009c38565b6001600160401b03811690508154816001600160401b0319821617835560208401356200a5f58162009c38565b6fffffffffffffffff0000000000000000604091821b166fffffffffffffffffffffffffffffffff198316841781178555908501356200a6358162009c38565b6001600160c01b0319929092169092179190911760809190911b67ffffffffffffffff60801b1617905550565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b60208152600062009a396020830184866200a662565b634e487b7160e01b600052603160045260246000fd5b6000816200a6c9576200a6c96200a1b6565b506000190190565b6040815260006200a6e76040830186886200a662565b82810360208401526200a6fc8185876200a662565b979650505050505050565b81516001600160401b038111156200a723576200a7236200992f565b6200a73b816200a73484546200a156565b846200a35b565b602080601f8311600181146200a76f57600084156200a75a5750858301515b6200a76685826200a3a5565b86555062006300565b600085815260208120601f198616915b828110156200a7a0578886015182559484019460019091019084016200a77f565b50858210156200a7bf5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60008083546200a7df816200a156565b600182811680156200a7fa57600181146200a810576200a841565b60ff19841687528215158302870194506200a841565b8760005260208060002060005b858110156200a8385781548a8201529084019082016200a81d565b50505082870194505b50929695505050505050565b6bffffffffffffffffffffffff198360601b1681526000600383106200a88357634e487b7160e01b600052602160045260246000fd5b5060f89190911b6014820152601501919050565b6bffffffffffffffffffffffff198560601b16815282846014830137601492019182015260340192915050565b600086516200a8d8818460208b01620098c6565b82018587823760009086019081528385823760009301928352509095945050505050565b6001600160a01b038316815260406020820181905260009062009a3990830184620098ec565b600082516200a936818460208701620098c6565b919091019291505056fe608060405260405162000e9638038062000e96833981016040819052620000269162000497565b828162000036828260006200004d565b50620000449050826200008a565b505050620005ca565b6200005883620000e5565b600082511180620000665750805b1562000085576200008383836200012760201b620001691760201c565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f620000b562000156565b604080516001600160a01b03928316815291841660208301520160405180910390a1620000e2816200018f565b50565b620000f08162000244565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b60606200014f838360405180606001604052806027815260200162000e6f60279139620002f8565b9392505050565b60006200018060008051602062000e4f83398151915260001b6200037760201b620001951760201c565b546001600160a01b0316919050565b6001600160a01b038116620001fa5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b806200022360008051602062000e4f83398151915260001b6200037760201b620001951760201c565b80546001600160a01b0319166001600160a01b039290921691909117905550565b6200025a816200037a60201b620001981760201c565b620002be5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b6064820152608401620001f1565b80620002237f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc60001b6200037760201b620001951760201c565b6060600080856001600160a01b03168560405162000317919062000577565b600060405180830381855af49150503d806000811462000354576040519150601f19603f3d011682016040523d82523d6000602084013e62000359565b606091505b5090925090506200036d8683838762000389565b9695505050505050565b90565b6001600160a01b03163b151590565b60608315620003fd578251600003620003f5576001600160a01b0385163b620003f55760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e74726163740000006044820152606401620001f1565b508162000409565b62000409838362000411565b949350505050565b815115620004225781518083602001fd5b8060405162461bcd60e51b8152600401620001f1919062000595565b80516001600160a01b03811681146200045657600080fd5b919050565b634e487b7160e01b600052604160045260246000fd5b60005b838110156200048e57818101518382015260200162000474565b50506000910152565b600080600060608486031215620004ad57600080fd5b620004b8846200043e565b9250620004c8602085016200043e565b60408501519092506001600160401b0380821115620004e657600080fd5b818601915086601f830112620004fb57600080fd5b8151818111156200051057620005106200045b565b604051601f8201601f19908116603f011681019083821181831017156200053b576200053b6200045b565b816040528281528960208487010111156200055557600080fd5b6200056883602083016020880162000471565b80955050505050509250925092565b600082516200058b81846020870162000471565b9190910192915050565b6020815260008251806020840152620005b681604085016020870162000471565b601f01601f19169190910160400192915050565b61087580620005da6000396000f3fe60806040523661001357610011610017565b005b6100115b61001f6101a7565b6001600160a01b0316330361015f5760606001600160e01b0319600035166364d3180d60e11b810161005a576100536101da565b9150610157565b63587086bd60e11b6001600160e01b031982160161007a57610053610231565b63070d7c6960e41b6001600160e01b031982160161009a57610053610277565b621eb96f60e61b6001600160e01b03198216016100b9576100536102a8565b63a39f25e560e01b6001600160e01b03198216016100d9576100536102e8565b60405162461bcd60e51b815260206004820152604260248201527f5472616e73706172656e745570677261646561626c6550726f78793a2061646d60448201527f696e2063616e6e6f742066616c6c6261636b20746f2070726f78792074617267606482015261195d60f21b608482015260a4015b60405180910390fd5b815160208301f35b6101676102fc565b565b606061018e83836040518060600160405280602781526020016108426027913961030c565b9392505050565b90565b6001600160a01b03163b151590565b60007fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b546001600160a01b0316919050565b60606101e4610384565b60006101f33660048184610695565b81019061020091906106db565b905061021d8160405180602001604052806000815250600061038f565b505060408051602081019091526000815290565b60606000806102433660048184610695565b810190610250919061070c565b915091506102608282600161038f565b604051806020016040528060008152509250505090565b6060610281610384565b60006102903660048184610695565b81019061029d91906106db565b905061021d816103bb565b60606102b2610384565b60006102bc6101a7565b604080516001600160a01b03831660208201529192500160405160208183030381529060405291505090565b60606102f2610384565b60006102bc610412565b610167610307610412565b610421565b6060600080856001600160a01b03168560405161032991906107f2565b600060405180830381855af49150503d8060008114610364576040519150601f19603f3d011682016040523d82523d6000602084013e610369565b606091505b509150915061037a86838387610445565b9695505050505050565b341561016757600080fd5b610398836104c6565b6000825111806103a55750805b156103b6576103b48383610169565b505b505050565b7f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f6103e46101a7565b604080516001600160a01b03928316815291841660208301520160405180910390a161040f81610506565b50565b600061041c6105af565b905090565b3660008037600080366000845af43d6000803e808015610440573d6000f35b3d6000fd5b606083156104b45782516000036104ad576001600160a01b0385163b6104ad5760405162461bcd60e51b815260206004820152601d60248201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604482015260640161014e565b50816104be565b6104be83836105d7565b949350505050565b6104cf81610601565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b6001600160a01b03811661056b5760405162461bcd60e51b815260206004820152602660248201527f455243313936373a206e65772061646d696e20697320746865207a65726f206160448201526564647265737360d01b606482015260840161014e565b807fb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d61035b80546001600160a01b0319166001600160a01b039290921691909117905550565b60007f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc6101cb565b8151156105e75781518083602001fd5b8060405162461bcd60e51b815260040161014e919061080e565b6001600160a01b0381163b61066e5760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b606482015260840161014e565b807f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc61058e565b600080858511156106a557600080fd5b838611156106b257600080fd5b5050820193919092039150565b80356001600160a01b03811681146106d657600080fd5b919050565b6000602082840312156106ed57600080fd5b61018e826106bf565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561071f57600080fd5b610728836106bf565b9150602083013567ffffffffffffffff8082111561074557600080fd5b818501915085601f83011261075957600080fd5b81358181111561076b5761076b6106f6565b604051601f8201601f19908116603f01168101908382118183101715610793576107936106f6565b816040528281528860208487010111156107ac57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b60005b838110156107e95781810151838201526020016107d1565b50506000910152565b600082516108048184602087016107ce565b9190910192915050565b602081526000825180602084015261082d8160408501602087016107ce565b601f01601f1916919091016040019291505056fe416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000ab53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564a164736f6c6343000811000a \ No newline at end of file diff --git a/core/systemcontracts/pasteur/types.go b/core/systemcontracts/pasteur/types.go new file mode 100644 index 0000000000..34c2b67cb2 --- /dev/null +++ b/core/systemcontracts/pasteur/types.go @@ -0,0 +1,30 @@ +package pasteur + +import _ "embed" + +// contract codes for Mainnet upgrade +var ( + //go:embed mainnet/StakeHubContract + MainnetStakeHubContract string + + //go:embed mainnet/GovernorContract + MainnetGovernorContract string +) + +// contract codes for Chapel upgrade +var ( + //go:embed chapel/StakeHubContract + ChapelStakeHubContract string + + //go:embed chapel/GovernorContract + ChapelGovernorContract string +) + +// contract codes for Rialto upgrade +var ( + //go:embed rialto/StakeHubContract + RialtoStakeHubContract string + + //go:embed rialto/GovernorContract + RialtoGovernorContract string +) diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go index 0ef6eef11c..49f1dd645b 100644 --- a/core/systemcontracts/upgrade.go +++ b/core/systemcontracts/upgrade.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/core/systemcontracts/moran" "github.com/ethereum/go-ethereum/core/systemcontracts/niels" "github.com/ethereum/go-ethereum/core/systemcontracts/pascal" + "github.com/ethereum/go-ethereum/core/systemcontracts/pasteur" "github.com/ethereum/go-ethereum/core/systemcontracts/planck" "github.com/ethereum/go-ethereum/core/systemcontracts/plato" "github.com/ethereum/go-ethereum/core/systemcontracts/ramanujan" @@ -95,6 +96,8 @@ var ( maxwellUpgrade = make(map[string]*Upgrade) fermiUpgrade = make(map[string]*Upgrade) + + pasteurUpgrade = make(map[string]*Upgrade) ) func init() { @@ -1055,6 +1058,54 @@ func init() { }, }, } + + pasteurUpgrade[mainNet] = &Upgrade{ + UpgradeName: "pasteur", + Configs: []*UpgradeConfig{ + { + ContractAddr: common.HexToAddress(StakeHubContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + Code: pasteur.MainnetStakeHubContract, + }, + { + ContractAddr: common.HexToAddress(GovernorContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + Code: pasteur.MainnetGovernorContract, + }, + }, + } + + pasteurUpgrade[chapelNet] = &Upgrade{ + UpgradeName: "pasteur", + Configs: []*UpgradeConfig{ + { + ContractAddr: common.HexToAddress(StakeHubContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + Code: pasteur.ChapelStakeHubContract, + }, + { + ContractAddr: common.HexToAddress(GovernorContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + Code: pasteur.ChapelGovernorContract, + }, + }, + } + + pasteurUpgrade[rialtoNet] = &Upgrade{ + UpgradeName: "pasteur", + Configs: []*UpgradeConfig{ + { + ContractAddr: common.HexToAddress(StakeHubContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + Code: pasteur.RialtoStakeHubContract, + }, + { + ContractAddr: common.HexToAddress(GovernorContract), + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + Code: pasteur.RialtoGovernorContract, + }, + }, + } } func TryUpdateBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, lastBlockTime uint64, blockTime uint64, statedb vm.StateDB, atBlockBegin bool) { @@ -1174,6 +1225,10 @@ func upgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I applySystemContractUpgrade(fermiUpgrade[network], blockNumber, statedb, logger) } + if config.IsOnPasteur(blockNumber, lastBlockTime, blockTime) { + applySystemContractUpgrade(pasteurUpgrade[network], blockNumber, statedb, logger) + } + /* apply other upgrades */ From 3c7eef036261ee78ebcc81a161989c7a04a64963 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Mon, 15 Jun 2026 15:07:19 +0800 Subject: [PATCH 37/48] core/txpool/legacypool: remove overflowpool for txs (#3722) * core/txpool/legacypool: remove overflowpool for txs * cmd/geth: mark OverflowPoolSlots deprecated --- cmd/geth/config.go | 1 + cmd/geth/main.go | 2 +- cmd/utils/flags.go | 29 +- cmd/utils/flags_legacy.go | 8 + core/txpool/legacypool/legacypool.go | 95 +---- core/txpool/legacypool/legacypool_test.go | 51 --- core/txpool/legacypool/tx_overflowpool.go | 190 ---------- .../txpool/legacypool/tx_overflowpool_test.go | 343 ------------------ go.mod | 1 - go.sum | 2 - 10 files changed, 32 insertions(+), 690 deletions(-) delete mode 100644 core/txpool/legacypool/tx_overflowpool.go delete mode 100644 core/txpool/legacypool/tx_overflowpool_test.go diff --git a/cmd/geth/config.go b/cmd/geth/config.go index ab5fe3fdd4..ccb42022ca 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -102,6 +102,7 @@ var deprecatedConfigFields = map[string]bool{ "ethconfig.Config.LightPeers": true, "ethconfig.Config.LightNoPrune": true, "ethconfig.Config.LightNoSyncServe": true, + "legacypool.Config.OverflowPoolSlots": true, } type ethstatsConfig struct { diff --git a/cmd/geth/main.go b/cmd/geth/main.go index d0880407e2..ee58f8245c 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -97,7 +97,7 @@ var ( utils.TxPoolGlobalSlotsFlag, utils.TxPoolAccountQueueFlag, utils.TxPoolGlobalQueueFlag, - utils.TxPoolOverflowPoolSlotsFlag, + utils.TxPoolOverflowPoolSlotsFlag, // deprecated utils.TxPoolLifetimeFlag, utils.TxPoolReannounceTimeFlag, utils.MinerTxGasLimitFlag, diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 310ad44d22..fc8230785f 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -555,12 +555,6 @@ var ( Value: ethconfig.Defaults.TxPool.GlobalQueue, Category: flags.TxPoolCategory, } - TxPoolOverflowPoolSlotsFlag = &cli.Uint64Flag{ - Name: "txpool.overflowpoolslots", - Usage: "Maximum number of transaction slots in overflow pool", - Value: ethconfig.Defaults.TxPool.OverflowPoolSlots, - Category: flags.TxPoolCategory, - } TxPoolLifetimeFlag = &cli.DurationFlag{ Name: "txpool.lifetime", Usage: "Maximum amount of time non-executable transaction are queued", @@ -1973,7 +1967,7 @@ func setTxPool(ctx *cli.Context, cfg *legacypool.Config) { cfg.GlobalQueue = ctx.Uint64(TxPoolGlobalQueueFlag.Name) } if ctx.IsSet(TxPoolOverflowPoolSlotsFlag.Name) { - cfg.OverflowPoolSlots = ctx.Uint64(TxPoolOverflowPoolSlotsFlag.Name) + log.Warn("The flag --txpool.overflowpoolslots is deprecated and has no effect") } if ctx.IsSet(TxPoolLifetimeFlag.Name) { cfg.Lifetime = ctx.Duration(TxPoolLifetimeFlag.Name) @@ -2574,17 +2568,16 @@ func EnableNodeInfo(poolConfig *legacypool.Config, nodeInfo *p2p.NodeInfo) Setup return func() { // register node info into metrics metrics.GetOrRegisterLabel("node-info", nil).Mark(map[string]interface{}{ - "Enode": nodeInfo.Enode, - "ENR": nodeInfo.ENR, - "ID": nodeInfo.ID, - "PriceLimit": poolConfig.PriceLimit, - "PriceBump": poolConfig.PriceBump, - "AccountSlots": poolConfig.AccountSlots, - "GlobalSlots": poolConfig.GlobalSlots, - "AccountQueue": poolConfig.AccountQueue, - "GlobalQueue": poolConfig.GlobalQueue, - "OverflowPoolSlots": poolConfig.OverflowPoolSlots, - "Lifetime": poolConfig.Lifetime, + "Enode": nodeInfo.Enode, + "ENR": nodeInfo.ENR, + "ID": nodeInfo.ID, + "PriceLimit": poolConfig.PriceLimit, + "PriceBump": poolConfig.PriceBump, + "AccountSlots": poolConfig.AccountSlots, + "GlobalSlots": poolConfig.GlobalSlots, + "AccountQueue": poolConfig.AccountQueue, + "GlobalQueue": poolConfig.GlobalQueue, + "Lifetime": poolConfig.Lifetime, }) } } diff --git a/cmd/utils/flags_legacy.go b/cmd/utils/flags_legacy.go index 45ab6a31b8..f07e6979a4 100644 --- a/cmd/utils/flags_legacy.go +++ b/cmd/utils/flags_legacy.go @@ -48,6 +48,7 @@ var DeprecatedFlags = []cli.Flag{ JournalFileFlag, LogExportCheckpointsFlag, EnableBALFlag, + TxPoolOverflowPoolSlotsFlag, } var ( @@ -155,6 +156,13 @@ var ( Usage: "Deprecated: BEP-592 block access list has been removed; this flag has no effect", Category: flags.DeprecatedCategory, } + TxPoolOverflowPoolSlotsFlag = &cli.Uint64Flag{ + Name: "txpool.overflowpoolslots", + Hidden: true, + Usage: "Deprecated: Maximum number of transaction slots in overflow pool; this flag has no effect", + Value: 0, + Category: flags.DeprecatedCategory, + } ) // showDeprecated displays deprecated flags that will be soon removed from the codebase. diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index e064fc9c12..7f77e62004 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -19,7 +19,6 @@ package legacypool import ( "errors" - "fmt" "maps" "math" "math/big" @@ -115,10 +114,9 @@ var ( // that this number is pretty low, since txpool reorgs happen very frequently. dropBetweenReorgHistogram = metrics.NewRegisteredHistogram("txpool/dropbetweenreorg", nil, metrics.NewExpDecaySample(1028, 0.015)) - pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil) - queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil) - slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil) - OverflowPoolGauge = metrics.NewRegisteredGauge("txpool/overflowpool", nil) + pendingGauge = metrics.NewRegisteredGauge("txpool/pending", nil) + queuedGauge = metrics.NewRegisteredGauge("txpool/queued", nil) + slotsGauge = metrics.NewRegisteredGauge("txpool/slots", nil) reheapTimer = metrics.NewRegisteredTimer("txpool/reheap", nil) ) @@ -149,11 +147,10 @@ type Config struct { PriceLimit uint64 // Minimum gas price to enforce for acceptance into the pool PriceBump uint64 // Minimum price bump percentage to replace an already existing transaction (nonce) - AccountSlots uint64 // Number of executable transaction slots guaranteed per account - GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts - AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account - GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts - OverflowPoolSlots uint64 // Maximum number of transaction slots in overflow pool + AccountSlots uint64 // Number of executable transaction slots guaranteed per account + GlobalSlots uint64 // Maximum number of executable transaction slots for all accounts + AccountQueue uint64 // Maximum number of non-executable transaction slots permitted per account + GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts Lifetime time.Duration // Maximum amount of time non-executable transaction are queued ReannounceTime time.Duration // Duration for announcing local pending transactions again @@ -167,11 +164,10 @@ var DefaultConfig = Config{ PriceLimit: 1, PriceBump: 10, - AccountSlots: 200, - GlobalSlots: 8000, - AccountQueue: 200, - GlobalQueue: 4000, - OverflowPoolSlots: 0, + AccountSlots: 200, + GlobalSlots: 8000, + AccountQueue: 200, + GlobalQueue: 4000, Lifetime: 3 * time.Hour, ReannounceTime: 10 * 365 * 24 * time.Hour, @@ -258,8 +254,6 @@ type LegacyPool struct { all *lookup // All transactions to allow lookups priced *pricedList // All transactions sorted by price - localBufferPool *TxOverflowPool // Local buffer transactions - reqResetCh chan *txpoolResetRequest reqPromoteCh chan *accountSet queueTxEventCh chan *types.Transaction @@ -297,7 +291,6 @@ func New(config Config, chain BlockChain) *LegacyPool { reorgDoneCh: make(chan chan struct{}), reorgShutdownCh: make(chan struct{}), initDoneCh: make(chan struct{}), - localBufferPool: NewTxOverflowPoolHeap(config.OverflowPoolSlots), } pool.priced = newPricedList(pool.all) @@ -493,17 +486,6 @@ func (pool *LegacyPool) Stats() (int, int) { return pool.stats() } -func (pool *LegacyPool) statsOverflowPool() uint64 { - pool.mu.RLock() - defer pool.mu.RUnlock() - - if pool.localBufferPool == nil { - return 0 - } - - return pool.localBufferPool.Size() -} - // stats retrieves the current pool stats, namely the number of pending and the // number of queued (non-executable) transactions. func (pool *LegacyPool) stats() (int, int) { @@ -822,8 +804,6 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { } } - pool.addToOverflowPool(drop) - // Kick out the underpriced remote transactions. for _, tx := range drop { log.Trace("Discarding freshly underpriced transaction", "hash", tx.Hash(), "gasTipCap", tx.GasTipCap(), "gasFeeCap", tx.GasFeeCap()) @@ -869,18 +849,6 @@ func (pool *LegacyPool) add(tx *types.Transaction) (replaced bool, err error) { return replaced, nil } -func (pool *LegacyPool) addToOverflowPool(drop types.Transactions) { - for _, tx := range drop { - added := pool.localBufferPool.Add(tx) - if added { - from, _ := types.Sender(pool.signer, tx) - log.Debug("Added to OverflowPool", "transaction", tx.Hash().String(), "from", from.String()) - } else { - log.Debug("Failed to add transaction to OverflowPool", "transaction", tx.Hash().String()) - } - } -} - // isGapped reports whether the given transaction is immediately executable. func (pool *LegacyPool) isGapped(from common.Address, tx *types.Transaction) bool { // Short circuit if transaction falls within the scope of the pending list @@ -1370,9 +1338,6 @@ func (pool *LegacyPool) runReorg(done chan struct{}, reset *txpoolResetRequest, pool.changesSinceReorg = 0 // Reset change counter pool.mu.Unlock() - // Transfer transactions from OverflowPool to MainPool for new block import - pool.transferTransactions() - // Notify subsystems for newly added transactions for _, tx := range promoted { addr, _ := types.Sender(pool.signer, tx) @@ -1897,44 +1862,6 @@ func numSlots(tx *types.Transaction) int { return int((tx.Size() + txSlotSize - 1) / txSlotSize) } -// transferTransactions moves transactions from OverflowPool to MainPool -func (pool *LegacyPool) transferTransactions() { - // Fail fast if the overflow pool is empty - if pool.localBufferPool.Size() == 0 { - return - } - - maxMainPoolSize := int(pool.config.GlobalSlots + pool.config.GlobalQueue) - // Use pool.all.Slots() to get the total slots used by all transactions - currentMainPoolSize := pool.all.Slots() - if currentMainPoolSize >= maxMainPoolSize { - return - } - - extraSlots := maxMainPoolSize - currentMainPoolSize - extraTransactions := (extraSlots + 3) / 4 // Since a transaction can take up to 4 slots - log.Debug("Will attempt to transfer from OverflowPool to MainPool", "transactions", extraTransactions) - txs := pool.localBufferPool.Flush(extraTransactions) - if len(txs) == 0 { - return - } - - pool.Add(txs, false) -} - -func (pool *LegacyPool) PrintTxStats() { - for _, l := range pool.pending { - for _, transaction := range l.txs.items { - from, _ := types.Sender(pool.signer, transaction) - fmt.Println("from: ", from, " Pending:", transaction.Hash().String(), transaction.GasFeeCap(), transaction.GasTipCap()) - } - } - - pool.localBufferPool.PrintTxStats() - fmt.Println("length of all: ", pool.all.Slots()) - fmt.Println("----------------------------------------------------") -} - // Clear implements txpool.SubPool, removing all tracked txs from the pool // and rotating the journal. // diff --git a/core/txpool/legacypool/legacypool_test.go b/core/txpool/legacypool/legacypool_test.go index ddae5d441b..51796b565d 100644 --- a/core/txpool/legacypool/legacypool_test.go +++ b/core/txpool/legacypool/legacypool_test.go @@ -41,7 +41,6 @@ import ( "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" - "gotest.tools/assert" ) var ( @@ -1634,7 +1633,6 @@ func TestRepricingDynamicFee(t *testing.T) { // Note, local transactions are never allowed to be dropped. func TestUnderpricing(t *testing.T) { t.Parallel() - testTxPoolConfig.OverflowPoolSlots = 5 // Create the pool to test the pricing enforcement with statedb, _ := state.New(types.EmptyRootHash, state.NewDatabaseForTesting()) @@ -1800,8 +1798,6 @@ func TestUnderpricingDynamicFee(t *testing.T) { pool.config.GlobalSlots = 2 pool.config.GlobalQueue = 2 - pool.config.OverflowPoolSlots = 0 - // Keep track of transaction events to ensure all executables get announced events := make(chan core.NewTxsEvent, 32) sub := pool.txFeed.Subscribe(events) @@ -1879,7 +1875,6 @@ func TestUnderpricingDynamicFee(t *testing.T) { func TestDualHeapEviction(t *testing.T) { t.Parallel() - testTxPoolConfig.OverflowPoolSlots = 1 pool, _ := setupPoolWithConfig(eip1559Config) defer pool.Close() @@ -1889,7 +1884,6 @@ func TestDualHeapEviction(t *testing.T) { // With pool size = 20, floatingCount = 20 * 1 / 5 = 4, which is sufficient. pool.config.GlobalSlots = 10 pool.config.GlobalQueue = 10 - pool.config.OverflowPoolSlots = 1 var ( highTip, highCap *types.Transaction @@ -2092,51 +2086,6 @@ func TestReplacement(t *testing.T) { } } -func TestTransferTransactions(t *testing.T) { - t.Parallel() - testTxPoolConfig.OverflowPoolSlots = 1 - pool, _ := setupPoolWithConfig(eip1559Config) - defer pool.Close() - - pool.config.GlobalSlots = 1 - pool.config.GlobalQueue = 2 - - // Create a number of test accounts and fund them - keys := make([]*ecdsa.PrivateKey, 5) - for i := 0; i < len(keys); i++ { - keys[i], _ = crypto.GenerateKey() - testAddBalance(pool, crypto.PubkeyToAddress(keys[i].PublicKey), big.NewInt(1000000)) - } - - tx := dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[0]) - from, _ := types.Sender(pool.signer, tx) - pool.addToOverflowPool([]*types.Transaction{tx}) - pending, queue := pool.Stats() - - assert.Equal(t, 0, pending, "pending transactions mismatched") - assert.Equal(t, 0, queue, "queued transactions mismatched") - assert.Equal(t, uint64(1), pool.statsOverflowPool(), "OverflowPool size unexpected") - - tx2 := dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[1]) - pool.addToOverflowPool([]*types.Transaction{tx2}) - assert.Equal(t, uint64(1), pool.statsOverflowPool(), "OverflowPool size unexpected") - <-pool.requestPromoteExecutables(newAccountSet(pool.signer, from)) - time.Sleep(1 * time.Second) - pending, queue = pool.Stats() - - assert.Equal(t, 1, pending, "pending transactions mismatched") - assert.Equal(t, 0, queue, "queued transactions mismatched") - assert.Equal(t, uint64(0), pool.statsOverflowPool(), "OverflowPool size unexpected") - - tx3 := dynamicFeeTx(0, 100000, big.NewInt(3), big.NewInt(2), keys[2]) - pool.addToOverflowPool([]*types.Transaction{tx3}) - pending, queue = pool.Stats() - - assert.Equal(t, 1, pending, "pending transactions mismatched") - assert.Equal(t, 0, queue, "queued transactions mismatched") - assert.Equal(t, uint64(1), pool.statsOverflowPool(), "OverflowPool size unexpected") -} - // Tests that the pool rejects replacement dynamic fee transactions that don't // meet the minimum price bump required. func TestReplacementDynamicFee(t *testing.T) { diff --git a/core/txpool/legacypool/tx_overflowpool.go b/core/txpool/legacypool/tx_overflowpool.go deleted file mode 100644 index ee6a924e03..0000000000 --- a/core/txpool/legacypool/tx_overflowpool.go +++ /dev/null @@ -1,190 +0,0 @@ -package legacypool - -import ( - "container/heap" - "fmt" - "sync" - "time" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/log" -) - -// txHeapItem implements the Interface interface (https://pkg.go.dev/container/heap#Interface) of heap so that it can be heapified -type txHeapItem struct { - tx *types.Transaction - timestamp int64 // Unix timestamp (nanoseconds) of when the transaction was added - index int -} - -type txHeap []*txHeapItem - -func (h txHeap) Len() int { return len(h) } -func (h txHeap) Less(i, j int) bool { - return h[i].timestamp < h[j].timestamp -} -func (h txHeap) Swap(i, j int) { - if i < 0 || j < 0 || i >= len(h) || j >= len(h) { - return // Silently fail if indices are out of bounds - } - h[i], h[j] = h[j], h[i] - if h[i] != nil { - h[i].index = i - } - if h[j] != nil { - h[j].index = j - } -} - -func (h *txHeap) Push(x interface{}) { - item, ok := x.(*txHeapItem) - if !ok { - return - } - n := len(*h) - item.index = n - *h = append(*h, item) -} - -func (h *txHeap) Pop() interface{} { - old := *h - n := len(old) - if n == 0 { - return nil // Return nil if the heap is empty - } - item := old[n-1] - old[n-1] = nil // avoid memory leak - *h = old[0 : n-1] - if item != nil { - item.index = -1 // for safety - } - return item -} - -type TxOverflowPool struct { - txHeap txHeap - index map[common.Hash]*txHeapItem - mu sync.RWMutex - maxSize uint64 // Maximum slots - totalSize uint64 // Total number of slots currently -} - -func NewTxOverflowPoolHeap(estimatedMaxSize uint64) *TxOverflowPool { - return &TxOverflowPool{ - txHeap: make(txHeap, 0, estimatedMaxSize), - index: make(map[common.Hash]*txHeapItem, estimatedMaxSize), - maxSize: estimatedMaxSize, - } -} - -func (tp *TxOverflowPool) Add(tx *types.Transaction) bool { - tp.mu.Lock() - defer tp.mu.Unlock() - - if _, exists := tp.index[tx.Hash()]; exists { - // Transaction already in pool, ignore - return false - } - - txSlots := uint64(numSlots(tx)) - - // If the transaction is too big to ever fit (and the pool isn't empty right now), reject it - if (txSlots > tp.maxSize) || (txSlots == tp.maxSize && tp.totalSize != 0) { - log.Debug("Transaction too large to fit in OverflowPool", "transaction", tx.Hash().String(), "requiredSlots", txSlots, "maxSlots", tp.maxSize) - return false - } - - // Remove transactions until there is room for the new transaction - for tp.totalSize+txSlots > tp.maxSize { - if tp.txHeap.Len() == 0 { - // No transactions left to remove, cannot make room - log.Warn("Not enough space in OverflowPool even after clearing", "transaction", tx.Hash().String()) - return false - } - // Remove the oldest transaction - oldestItem, ok := heap.Pop(&tp.txHeap).(*txHeapItem) - if !ok || oldestItem == nil { - log.Error("Failed to pop from txHeap during Add") - return false - } - delete(tp.index, oldestItem.tx.Hash()) - tp.totalSize -= uint64(numSlots(oldestItem.tx)) - OverflowPoolGauge.Dec(1) - } - - // Add the new transaction - item := &txHeapItem{ - tx: tx, - timestamp: time.Now().UnixNano(), - } - heap.Push(&tp.txHeap, item) - tp.index[tx.Hash()] = item - tp.totalSize += txSlots - OverflowPoolGauge.Inc(1) - - return true -} - -func (tp *TxOverflowPool) Get(hash common.Hash) (*types.Transaction, bool) { - tp.mu.RLock() - defer tp.mu.RUnlock() - if item, ok := tp.index[hash]; ok { - return item.tx, true - } - return nil, false -} - -func (tp *TxOverflowPool) Remove(hash common.Hash) { - tp.mu.Lock() - defer tp.mu.Unlock() - if item, ok := tp.index[hash]; ok { - heap.Remove(&tp.txHeap, item.index) - delete(tp.index, hash) - tp.totalSize -= uint64(numSlots(item.tx)) - OverflowPoolGauge.Dec(1) - } -} - -func (tp *TxOverflowPool) Flush(n int) []*types.Transaction { - tp.mu.Lock() - defer tp.mu.Unlock() - if n > tp.txHeap.Len() { - n = tp.txHeap.Len() - } - txs := make([]*types.Transaction, n) - for i := 0; i < n; i++ { - item, ok := heap.Pop(&tp.txHeap).(*txHeapItem) - if !ok || item == nil { - continue - } - txs[i] = item.tx - delete(tp.index, item.tx.Hash()) - tp.totalSize -= uint64(numSlots(item.tx)) - } - - OverflowPoolGauge.Dec(int64(n)) - return txs -} - -func (tp *TxOverflowPool) Len() int { - tp.mu.RLock() - defer tp.mu.RUnlock() - return tp.txHeap.Len() -} - -func (tp *TxOverflowPool) Size() uint64 { - tp.mu.RLock() - defer tp.mu.RUnlock() - return tp.totalSize -} - -func (tp *TxOverflowPool) PrintTxStats() { - tp.mu.RLock() - defer tp.mu.RUnlock() - for _, item := range tp.txHeap { - tx := item.tx - fmt.Printf("Hash: %s, Timestamp: %d, GasFeeCap: %s, GasTipCap: %s\n", - tx.Hash().String(), item.timestamp, tx.GasFeeCap().String(), tx.GasTipCap().String()) - } -} diff --git a/core/txpool/legacypool/tx_overflowpool_test.go b/core/txpool/legacypool/tx_overflowpool_test.go deleted file mode 100644 index ca8b6635f4..0000000000 --- a/core/txpool/legacypool/tx_overflowpool_test.go +++ /dev/null @@ -1,343 +0,0 @@ -package legacypool - -import ( - rand3 "crypto/rand" - "math/big" - rand2 "math/rand" - "testing" - "time" - - "github.com/cometbft/cometbft/libs/rand" - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" - "github.com/stretchr/testify/assert" -) - -// Helper function to create a test transaction -func createTestTx(nonce uint64, gasPrice *big.Int) *types.Transaction { - to := common.HexToAddress("0x1234567890123456789012345678901234567890") - return types.NewTransaction(nonce, to, big.NewInt(1000), 21000, gasPrice, nil) -} - -func TestNewTxOverflowPoolHeap(t *testing.T) { - pool := NewTxOverflowPoolHeap(0) - if pool == nil { - t.Fatal("NewTxOverflowPoolHeap returned nil") - } - if pool.Len() != 0 { - t.Errorf("New pool should be empty, got length %d", pool.Len()) - } -} - -func TestTxOverflowPoolHeapAdd(t *testing.T) { - pool := NewTxOverflowPoolHeap(1) - tx := createTestTx(1, big.NewInt(1000)) - - pool.Add(tx) - if pool.Len() != 1 { - t.Errorf("Pool should have 1 transaction, got %d", pool.Len()) - } - - // Add the same transaction again - pool.Add(tx) - if pool.Len() != 1 { - t.Errorf("Pool should still have 1 transaction after adding duplicate, got %d", pool.Len()) - } -} - -func TestTxOverflowPoolHeapGet(t *testing.T) { - pool := NewTxOverflowPoolHeap(1) - tx := createTestTx(1, big.NewInt(1000)) - pool.Add(tx) - - gotTx, exists := pool.Get(tx.Hash()) - if !exists { - t.Fatal("Get returned false for existing transaction") - } - if gotTx.Hash() != tx.Hash() { - t.Errorf("Get returned wrong transaction. Want %v, got %v", tx.Hash(), gotTx.Hash()) - } - - _, exists = pool.Get(common.Hash{}) - if exists { - t.Error("Get returned true for non-existent transaction") - } -} - -func TestTxOverflowPoolHeapRemove(t *testing.T) { - pool := NewTxOverflowPoolHeap(1) - tx := createTestTx(1, big.NewInt(1000)) - pool.Add(tx) - - pool.Remove(tx.Hash()) - if pool.Len() != 0 { - t.Errorf("Pool should be empty after removing the only transaction, got length %d", pool.Len()) - } - - // Try to remove non-existent transaction - pool.Remove(common.Hash{}) - if pool.Len() != 0 { - t.Error("Removing non-existent transaction should not affect pool size") - } -} - -func TestTxOverflowPoolHeapPopN(t *testing.T) { - pool := NewTxOverflowPoolHeap(3) - tx1 := createTestTx(1, big.NewInt(1000)) - tx2 := createTestTx(2, big.NewInt(2000)) - tx3 := createTestTx(3, big.NewInt(3000)) - - pool.Add(tx1) - time.Sleep(time.Millisecond) // Ensure different timestamps - pool.Add(tx2) - time.Sleep(time.Millisecond) - pool.Add(tx3) - - popped := pool.Flush(2) - if len(popped) != 2 { - t.Fatalf("PopN(2) should return 2 transactions, got %d", len(popped)) - } - if popped[0].Hash() != tx1.Hash() || popped[1].Hash() != tx2.Hash() { - t.Error("PopN returned transactions in wrong order") - } - if pool.Len() != 1 { - t.Errorf("Pool should have 1 transaction left, got %d", pool.Len()) - } - - // Pop more than available - popped = pool.Flush(2) - if len(popped) != 1 { - t.Fatalf("PopN(2) should return 1 transaction when only 1 is left, got %d", len(popped)) - } - if popped[0].Hash() != tx3.Hash() { - t.Error("PopN returned wrong transaction") - } - if pool.Len() != 0 { - t.Errorf("Pool should be empty, got length %d", pool.Len()) - } -} - -func TestTxOverflowPoolHeapOrdering(t *testing.T) { - pool := NewTxOverflowPoolHeap(3) - tx1 := createTestTx(1, big.NewInt(1000)) - tx2 := createTestTx(2, big.NewInt(2000)) - tx3 := createTestTx(3, big.NewInt(3000)) - - pool.Add(tx2) - time.Sleep(time.Millisecond) // Ensure different timestamps - pool.Add(tx1) - pool.Add(tx3) // Added immediately after tx1, should have same timestamp but higher sequence - - popped := pool.Flush(3) - if len(popped) != 3 { - t.Fatalf("PopN(3) should return 3 transactions, got %d", len(popped)) - } - if popped[0].Hash() != tx2.Hash() || popped[1].Hash() != tx1.Hash() || popped[2].Hash() != tx3.Hash() { - t.Error("Transactions not popped in correct order (earliest timestamp first, then by sequence)") - } -} - -func TestTxOverflowPoolHeapLen(t *testing.T) { - pool := NewTxOverflowPoolHeap(2) - if pool.Len() != 0 { - t.Errorf("New pool should have length 0, got %d", pool.Len()) - } - - pool.Add(createTestTx(1, big.NewInt(1000))) - if pool.Len() != 1 { - t.Errorf("Pool should have length 1 after adding a transaction, got %d", pool.Len()) - } - - pool.Add(createTestTx(2, big.NewInt(2000))) - if pool.Len() != 2 { - t.Errorf("Pool should have length 2 after adding another transaction, got %d", pool.Len()) - } - - pool.Flush(1) - if pool.Len() != 1 { - t.Errorf("Pool should have length 1 after popping a transaction, got %d", pool.Len()) - } -} - -func TestTxOverflowPoolSlotCalculation(t *testing.T) { - // Initialize the pool with a maximum size of 2 - pool := NewTxOverflowPoolHeap(2) - - // Create two transactions with different slot requirements - tx1 := createTestTx(1, big.NewInt(1000)) // tx1 takes 1 slot - tx2 := createTestTx(2, big.NewInt(2000)) // tx2 takes 1 slot - - // Add both transactions to fill the pool - pool.Add(tx1) - pool.Add(tx2) - - if pool.Len() != 2 { - t.Fatalf("Expected pool size 2, but got %d", pool.Len()) - } - - dataSize := 40000 - tx3 := createLargeTestTx( - 3, // nonce - big.NewInt(100000000000), // gasPrice: 100 Gwei - dataSize, - ) // takes 2 slots - - // Create a third transaction with more slots than tx1 - tx3Added := pool.Add(tx3) - assert.Equal(t, false, tx3Added) - assert.Equal(t, uint64(2), pool.totalSize) - - // Verify that the pool length remains at 2 - assert.Equal(t, 2, pool.Len(), "Expected pool size 2 after overflow") - - tx4 := createTestTx(4, big.NewInt(3000)) // tx4 takes 1 slot - // Add tx4 to the pool - assert.True(t, pool.Add(tx4), "Failed to add tx4") - - // The pool should evict the oldest transaction (tx1) to make room for tx4 - // Verify that tx1 is no longer in the pool - _, exists := pool.Get(tx1.Hash()) - assert.False(t, exists, "Expected tx1 to be evicted from the pool") -} - -func TestBiggerTx(t *testing.T) { - // Create a transaction with 40KB of data (which should take 2 slots) - dataSize := 40000 - tx := createLargeTestTx( - 0, // nonce - big.NewInt(100000000000), // gasPrice: 100 Gwei - dataSize, - ) - numberOfSlots := numSlots(tx) - assert.Equal(t, 2, numberOfSlots) -} - -// Helper function to create a random test transaction -func createRandomTestTx() *types.Transaction { - nonce := uint64(rand.Intn(1000000)) - to := common.BytesToAddress(rand.Bytes(20)) - amount := new(big.Int).Rand(rand2.New(rand2.NewSource(rand.Int63())), big.NewInt(1e18)) - gasLimit := uint64(21000) - gasPrice := new(big.Int).Rand(rand2.New(rand2.NewSource(rand.Int63())), big.NewInt(1e9)) - data := rand.Bytes(100) - return types.NewTransaction(nonce, to, amount, gasLimit, gasPrice, data) -} - -func createRandomTestTxs(n int) []*types.Transaction { - txs := make([]*types.Transaction, n) - for i := 0; i < n; i++ { - txs[i] = createRandomTestTx() - } - return txs -} - -// createLargeTestTx creates a transaction with a large data payload -func createLargeTestTx(nonce uint64, gasPrice *big.Int, dataSize int) *types.Transaction { - // Generate random data of specified size - data := make([]byte, dataSize) - rand3.Read(data) - - to := common.HexToAddress("0x1234567890123456789012345678901234567890") - - // Calculate gas needed for the data - // Gas costs: 21000 (base) + 16 (per non-zero byte) or 4 (per zero byte) - gasLimit := uint64(21000 + (16 * len(data))) - - return types.NewTransaction( - nonce, - to, - big.NewInt(1000), - gasLimit, - gasPrice, - data, - ) -} - -// goos: darwin -// goarch: arm64 -// pkg: github.com/ethereum/go-ethereum/core/txpool/legacypool -// BenchmarkTxOverflowPoolHeapAdd-8 813326 2858 ns/op -func BenchmarkTxOverflowPoolHeapAdd(b *testing.B) { - pool := NewTxOverflowPoolHeap(uint64(b.N)) - txs := createRandomTestTxs(b.N) - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool.Add(txs[i]) - } -} - -// BenchmarkTxOverflowPoolHeapGet-8 32613938 35.63 ns/op -func BenchmarkTxOverflowPoolHeapGet(b *testing.B) { - pool := NewTxOverflowPoolHeap(1000) - txs := createRandomTestTxs(1000) - for _, tx := range txs { - pool.Add(tx) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool.Get(txs[i%1000].Hash()) - } -} - -// BenchmarkTxOverflowPoolHeapRemove-8 3020841 417.8 ns/op -func BenchmarkTxOverflowPoolHeapRemove(b *testing.B) { - pool := NewTxOverflowPoolHeap(uint64(b.N)) - txs := createRandomTestTxs(b.N) - for _, tx := range txs { - pool.Add(tx) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool.Remove(txs[i].Hash()) - } -} - -// BenchmarkTxOverflowPoolHeapFlush-8 42963656 29.90 ns/op -func BenchmarkTxOverflowPoolHeapFlush(b *testing.B) { - pool := NewTxOverflowPoolHeap(1000) - txs := createRandomTestTxs(1000) - for _, tx := range txs { - pool.Add(tx) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool.Flush(10) - } -} - -// BenchmarkTxOverflowPoolHeapLen-8 79147188 20.07 ns/op -func BenchmarkTxOverflowPoolHeapLen(b *testing.B) { - pool := NewTxOverflowPoolHeap(1000) - txs := createRandomTestTxs(1000) - for _, tx := range txs { - pool.Add(tx) - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool.Len() - } -} - -// BenchmarkTxOverflowPoolHeapAddRemove-8 902896 1546 ns/op -func BenchmarkTxOverflowPoolHeapAddRemove(b *testing.B) { - pool := NewTxOverflowPoolHeap(uint64(b.N)) - txs := createRandomTestTxs(b.N) - b.ResetTimer() - for i := 0; i < b.N; i++ { - pool.Add(txs[i]) - pool.Remove(txs[i].Hash()) - } -} - -// BenchmarkTxOverflowPoolHeapAddFlush-8 84417 14899 ns/op -func BenchmarkTxOverflowPoolHeapAddFlush(b *testing.B) { - pool := NewTxOverflowPoolHeap(uint64(b.N * 10)) - txs := createRandomTestTxs(b.N * 10) - b.ResetTimer() - for i := 0; i < b.N; i++ { - for j := 0; j < 10; j++ { - pool.Add(txs[i*10+j]) - } - pool.Flush(10) - } -} diff --git a/go.mod b/go.mod index d39346b320..ef9300801b 100644 --- a/go.mod +++ b/go.mod @@ -91,7 +91,6 @@ require ( google.golang.org/protobuf v1.36.11 gopkg.in/natefinch/lumberjack.v2 v2.2.1 gopkg.in/yaml.v3 v3.0.1 - gotest.tools v2.2.0+incompatible ) require ( diff --git a/go.sum b/go.sum index d623e52d0d..ace9c6596e 100644 --- a/go.sum +++ b/go.sum @@ -1742,8 +1742,6 @@ gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= -gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o= honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 02122b64f0fc698abfb408f90f147ef23040e27f Mon Sep 17 00:00:00 2001 From: Matus Kysel Date: Wed, 17 Jun 2026 04:10:24 +0200 Subject: [PATCH 38/48] core/vm: reject duplicate bridge validators at Pasteur (#3623) * core/vm: reject duplicate bridge validators at Mendel * core/vm: enforce duplicate bridge validator checks at Pasteur * core/vm: reject duplicate bridge validators at Pasteur * core/vm: reject duplicate bridge validators at Pasteur * core/vm: reject duplicate bridge validators at Pasteur * contracts.go: update precompile --------- Co-authored-by: qybdyx --- core/vm/contracts.go | 43 +++++++ core/vm/contracts_lightclient.go | 25 +++- core/vm/contracts_lightclient_test.go | 37 ++++++ core/vm/contracts_test.go | 20 ++++ core/vm/lightclient/v2/lightclient.go | 91 ++++++++++++++- core/vm/lightclient/v2/lightclient_test.go | 127 ++++++++++++++++++++- 6 files changed, 334 insertions(+), 9 deletions(-) diff --git a/core/vm/contracts.go b/core/vm/contracts.go index f8b2d0856d..0730876fff 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -350,6 +350,37 @@ var PrecompiledContractsOsaka = PrecompiledContracts{ common.BytesToAddress([]byte{0x1, 0x00}): &p256Verify{eip7951: true}, } +// PrecompiledContractsPasteur contains the set of pre-compiled Ethereum +// contracts used in the Pasteur release. +var PrecompiledContractsPasteur = PrecompiledContracts{ + common.BytesToAddress([]byte{0x01}): &ecrecover{}, + common.BytesToAddress([]byte{0x02}): &sha256hash{}, + common.BytesToAddress([]byte{0x03}): &ripemd160hash{}, + common.BytesToAddress([]byte{0x04}): &dataCopy{}, + common.BytesToAddress([]byte{0x05}): &bigModExp{eip2565: true, eip7823: true, eip7883: true}, + common.BytesToAddress([]byte{0x06}): &bn256AddIstanbul{}, + common.BytesToAddress([]byte{0x07}): &bn256ScalarMulIstanbul{}, + common.BytesToAddress([]byte{0x08}): &bn256PairingIstanbul{}, + common.BytesToAddress([]byte{0x09}): &blake2F{}, + common.BytesToAddress([]byte{0x0a}): &kzgPointEvaluation{}, + common.BytesToAddress([]byte{0x0b}): &bls12381G1Add{}, + common.BytesToAddress([]byte{0x0c}): &bls12381G1MultiExp{}, + common.BytesToAddress([]byte{0x0d}): &bls12381G2Add{}, + common.BytesToAddress([]byte{0x0e}): &bls12381G2MultiExp{}, + common.BytesToAddress([]byte{0x0f}): &bls12381Pairing{}, + common.BytesToAddress([]byte{0x10}): &bls12381MapG1{}, + common.BytesToAddress([]byte{0x11}): &bls12381MapG2{}, + + common.BytesToAddress([]byte{0x64}): &tmHeaderValidate{}, + common.BytesToAddress([]byte{0x65}): &iavlMerkleProofValidatePlato{}, + common.BytesToAddress([]byte{0x66}): &blsSignatureVerify{}, + common.BytesToAddress([]byte{0x67}): &cometBFTLightBlockValidatePasteur{}, + common.BytesToAddress([]byte{0x68}): &verifyDoubleSignEvidence{}, + common.BytesToAddress([]byte{0x69}): &secp256k1SignatureRecover{}, + + common.BytesToAddress([]byte{0x1, 0x00}): &p256Verify{eip7951: true}, +} + // PrecompiledContractsP256Verify contains the precompiled Ethereum // contract specified in EIP-7212. This is exported for testing purposes. var PrecompiledContractsP256Verify = PrecompiledContracts{ @@ -357,6 +388,7 @@ var PrecompiledContractsP256Verify = PrecompiledContracts{ } var ( + PrecompiledAddressesPasteur []common.Address PrecompiledAddressesOsaka []common.Address PrecompiledAddressesPrague []common.Address PrecompiledAddressesHaber []common.Address @@ -420,12 +452,17 @@ func init() { for k := range PrecompiledContractsOsaka { PrecompiledAddressesOsaka = append(PrecompiledAddressesOsaka, k) } + for k := range PrecompiledContractsPasteur { + PrecompiledAddressesPasteur = append(PrecompiledAddressesPasteur, k) + } } func activePrecompiledContracts(rules params.Rules) PrecompiledContracts { switch { case rules.IsVerkle: return PrecompiledContractsVerkle + case rules.IsPasteur: + return PrecompiledContractsPasteur case rules.IsOsaka: return PrecompiledContractsOsaka case rules.IsPrague: @@ -467,6 +504,8 @@ func ActivePrecompiledContracts(rules params.Rules) PrecompiledContracts { // ActivePrecompiles returns the precompile addresses enabled with the current configuration. func ActivePrecompiles(rules params.Rules) []common.Address { switch { + case rules.IsPasteur: + return PrecompiledAddressesPasteur case rules.IsOsaka: return PrecompiledAddressesOsaka case rules.IsPrague: @@ -1623,6 +1662,10 @@ func (c *blsSignatureVerify) RequiredGas(input []byte) uint64 { // Run input: // msg | signature | [{bls pubkey}] | // 32 bytes | 96 bytes | [{48 bytes}] | +// +// Note: as a generic BLS signature verification primitive, this precompile +// does not require public keys to be unique. Callers that need uniqueness +// (e.g. validator set decoding) must enforce it themselves. func (c *blsSignatureVerify) Run(input []byte) ([]byte, error) { msgAndSigLength := msgHashLength + signatureLength inputLen := uint64(len(input)) diff --git a/core/vm/contracts_lightclient.go b/core/vm/contracts_lightclient.go index d83c537644..4eefcf6731 100644 --- a/core/vm/contracts_lightclient.go +++ b/core/vm/contracts_lightclient.go @@ -7,6 +7,7 @@ import ( "net/url" "strings" + "github.com/cometbft/cometbft/types" "github.com/cosmos/iavl" "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/crypto/secp256k1" @@ -391,14 +392,18 @@ func (c *cometBFTLightBlockValidate) RequiredGas(input []byte) uint64 { return params.CometBFTLightBlockValidateGas } -func (c *cometBFTLightBlockValidate) run(input []byte, isHertz bool) (result []byte, err error) { +func (c *cometBFTLightBlockValidate) run(input []byte, isHertz bool, requireUniqueValidators bool) (result []byte, err error) { defer func() { if r := recover(); r != nil { err = fmt.Errorf("internal error: %v\n", r) } }() - cs, block, err := v2.DecodeLightBlockValidationInput(input) + var ( + cs *v2.ConsensusState + block *types.LightBlock + ) + cs, block, err = v2.DecodeLightBlockValidationInput(input, requireUniqueValidators) if err != nil { return nil, err } @@ -418,7 +423,7 @@ func (c *cometBFTLightBlockValidate) run(input []byte, isHertz bool) (result []b } func (c *cometBFTLightBlockValidate) Run(input []byte) (result []byte, err error) { - return c.run(input, false) + return c.run(input, false, false) } func (c *cometBFTLightBlockValidate) Name() string { @@ -430,13 +435,25 @@ type cometBFTLightBlockValidateHertz struct { } func (c *cometBFTLightBlockValidateHertz) Run(input []byte) (result []byte, err error) { - return c.run(input, true) + return c.run(input, true, false) } func (c *cometBFTLightBlockValidateHertz) Name() string { return "COMET_BFT_LIGHT_BLOCK_VALIDATE_HERTZ" } +type cometBFTLightBlockValidatePasteur struct { + cometBFTLightBlockValidate +} + +func (c *cometBFTLightBlockValidatePasteur) Run(input []byte) (result []byte, err error) { + return c.run(input, true, true) +} + +func (c *cometBFTLightBlockValidatePasteur) Name() string { + return "COMET_BFT_LIGHT_BLOCK_VALIDATE_PASTEUR" +} + // secp256k1SignatureRecover implemented as a native contract. type secp256k1SignatureRecover struct{} diff --git a/core/vm/contracts_lightclient_test.go b/core/vm/contracts_lightclient_test.go index e3211b07da..ceb8bbe0c9 100644 --- a/core/vm/contracts_lightclient_test.go +++ b/core/vm/contracts_lightclient_test.go @@ -5,13 +5,17 @@ import ( "encoding/hex" "testing" + "github.com/cometbft/cometbft/types" "github.com/cosmos/iavl" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/crypto/merkle" cmn "github.com/tendermint/tendermint/libs/common" v1 "github.com/ethereum/go-ethereum/core/vm/lightclient/v1" + v2 "github.com/ethereum/go-ethereum/core/vm/lightclient/v2" ) const ( @@ -374,6 +378,39 @@ func TestCometBFTLightBlockValidateHertz(t *testing.T) { require.Equal(t, expectOutputStr, hex.EncodeToString(res)) } +func TestCometBFTLightBlockValidateRejectsDuplicateTrustedValidatorsAtPasteur(t *testing.T) { + inputStr := "000000000000000000000000000000000000000000000000000000000000018c677265656e6669656c645f393030302d3132310000000000000000000000000000000000000000013c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb40e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e8423000000000098968015154514f68ce65a0d9eecc578c0ab12da0a2a28a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86451c5363d89052fde8351895eeea166ce5373c36e31b518ed191d0c599aa0f5b0000000000989680432f6c4908a9aa5f3444421f466b11645235c99b831b2a2de9e504d7ea299e52a202ce529808618eb3bfc0addf13d8c5f2df821d81e18f9bc61583510b322d067d46323b0a572635c06a049c0a2a929e3c8184a50cf6a8b95708c25834ade456f399015a0000000000989680864cb9828254d712f8e59b164fc6a9402dc4e6c59065e38cff24f5323c8c5da888a0f97e5ee4ba1e11b0674b0a0d06204c1dfa247c370cd4be3e799fc4f6f48d977ac7ca0aeb060adb030a02080b1213677265656e6669656c645f393030302d3132311802220c08b2d7f3a10610e8d2adb3032a480a20ec6ecb5db4ffb17fabe40c60ca7b8441e9c5d77585d0831186f3c37aa16e9c15122408011220a2ab9e1eb9ea52812f413526e424b326aff2f258a56e00d690db9f805b60fe7e32200f40aeff672e8309b7b0aefbb9a1ae3d4299b5c445b7d54e8ff398488467f0053a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85542203c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb404a203c350cd55b99dc6c2b7da9bef5410fbfb869fede858e7b95bf7ca294e228bb405220294d8fbd0b94b767a7eba9840f299a3586da7fe6b5dead3b7eecba193c400f935a20bc50557c12d7392b0d07d75df0b61232d48f86a74fdea6d1485d9be6317d268c6220e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b8556a20e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b85572146699336aa109d1beab3946198c8e59f3b2cbd92f7a4065e3cd89e315ca39d87dee92835b98f8b8ec0861d6d9bb2c60156df5d375b3ceb1fbe71af6a244907d62548a694165caa660fec7a9b4e7b9198191361c71be0b128a0308021a480a20726abd0fdbfb6f779b0483e6e4b4b6f12241f6ea2bf374233ab1a316692b6415122408011220159f10ff15a8b58fc67a92ffd7f33c8cd407d4ce81b04ca79177dfd00ca19a67226808021214050cff76cc632760ba9db796c046004c900967361a0c08b3d7f3a10610808cadba03224080713027ffb776a702d78fd0406205c629ba473e1f8d6af646190f6eb9262cd67d69be90d10e597b91e06d7298eb6fa4b8f1eb7752ebf352a1f51560294548042268080212146699336aa109d1beab3946198c8e59f3b2cbd92f1a0c08b3d7f3a10610b087c1c00322405e2ddb70acfe4904438be3d9f4206c0ace905ac4fc306a42cfc9e86268950a0fbfd6ec5f526d3e41a3ef52bf9f9f358e3cb4c3feac76c762fa3651c1244fe004226808021214c55765fd2d0570e869f6ac22e7f2916a35ea300d1a0c08b3d7f3a10610f0b3d492032240ca17898bd22232fc9374e1188636ee321a396444a5b1a79f7628e4a11f265734b2ab50caf21e8092c55d701248e82b2f011426cb35ba22043b497a6b4661930612a0050aa8010a14050cff76cc632760ba9db796c046004c9009673612220a20e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e84231880ade2042080a6bbf6ffffffffff012a30a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86321415154514f68ce65a0d9eecc578c0ab12da0a2a283a14ee7a2a6a44d427f6949eeb8f12ea9fbb2501da880aa2010a146699336aa109d1beab3946198c8e59f3b2cbd92f12220a20451c5363d89052fde8351895eeea166ce5373c36e31b518ed191d0c599aa0f5b1880ade2042080ade2042a30831b2a2de9e504d7ea299e52a202ce529808618eb3bfc0addf13d8c5f2df821d81e18f9bc61583510b322d067d46323b3214432f6c4908a9aa5f3444421f466b11645235c99b3a14a0a7769429468054e19059af4867da0a495567e50aa2010a14c55765fd2d0570e869f6ac22e7f2916a35ea300d12220a200a572635c06a049c0a2a929e3c8184a50cf6a8b95708c25834ade456f399015a1880ade2042080ade2042a309065e38cff24f5323c8c5da888a0f97e5ee4ba1e11b0674b0a0d06204c1dfa247c370cd4be3e799fc4f6f48d977ac7ca3214864cb9828254d712f8e59b164fc6a9402dc4e6c53a143139916d97df0c589312b89950b6ab9795f34d1a12a8010a14050cff76cc632760ba9db796c046004c9009673612220a20e33f6e876d63791ebd05ff617a1b4f4ad1aa2ce65e3c3a9cdfb33e0ffa7e84231880ade2042080a6bbf6ffffffffff012a30a0805521b5b7ae56eb3fb24555efbfe59e1622bfe9f7be8c9022e9b3f2442739c1ce870b9adee169afe60f674edd7c86321415154514f68ce65a0d9eecc578c0ab12da0a2a283a14ee7a2a6a44d427f6949eeb8f12ea9fbb2501da88" + + input, err := hex.DecodeString(inputStr) + require.NoError(t, err) + + cs, block, err := v2.DecodeLightBlockValidationInput(input, false) + require.NoError(t, err) + + duplicate := cs.ValidatorSet.Validators[0].Copy() + cs.ValidatorSet = &types.ValidatorSet{Validators: []*types.Validator{duplicate.Copy(), duplicate.Copy(), duplicate.Copy()}} + csBytes, err := cs.EncodeConsensusState() + require.NoError(t, err) + + blockProto, err := block.ToProto() + require.NoError(t, err) + blockBytes, err := blockProto.Marshal() + require.NoError(t, err) + + mutatedInput := make([]byte, 32) + binary.BigEndian.PutUint64(mutatedInput[24:], uint64(len(csBytes))) + mutatedInput = append(mutatedInput, csBytes...) + mutatedInput = append(mutatedInput, blockBytes...) + + pasteurPrecompile := ActivePrecompiledContracts(params.Rules{IsOsaka: true, IsMendel: true, IsPasteur: true})[common.BytesToAddress([]byte{0x67})] + _, err = pasteurPrecompile.Run(mutatedInput) + require.ErrorContains(t, err, "duplicate validator") + + legacyPrecompile := ActivePrecompiledContracts(params.Rules{IsOsaka: true})[common.BytesToAddress([]byte{0x67})] + _, err = legacyPrecompile.Run(mutatedInput) + require.NoError(t, err) +} + func TestSecp256k1SignatureRecover(t *testing.T) { // local key { diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go index 684a51080a..4e182425d1 100644 --- a/core/vm/contracts_test.go +++ b/core/vm/contracts_test.go @@ -25,6 +25,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/params" ) // precompiledTest defines the input/output pairs for precompiled contract tests. @@ -353,6 +354,25 @@ func TestPrecompiledBLS12381MapG2(t *testing.T) { testJson("blsMapG2", "f10 func TestPrecompiledBlsSignatureVerify(t *testing.T) { testJson("blsSignatureVerify", "66", t) } +func TestActivePrecompiledContractsUsesPasteurVariants(t *testing.T) { + rules := params.Rules{IsOsaka: true, IsMendel: true, IsPasteur: true} + precompiles := ActivePrecompiledContracts(rules) + + requirePrecompile := func(addr byte) PrecompiledContract { + t.Helper() + + precompile, ok := precompiles[common.BytesToAddress([]byte{addr})] + if !ok { + t.Fatalf("missing precompile 0x%02x", addr) + } + return precompile + } + + if got := requirePrecompile(0x67).Name(); got != "COMET_BFT_LIGHT_BLOCK_VALIDATE_PASTEUR" { + t.Fatalf("unexpected Pasteur 0x67 precompile: %s", got) + } +} + func TestPrecompiledPointEvaluation(t *testing.T) { testJson("pointEvaluation", "0a", t) } func BenchmarkPrecompiledPointEvaluation(b *testing.B) { benchJson("pointEvaluation", "0a", b) } diff --git a/core/vm/lightclient/v2/lightclient.go b/core/vm/lightclient/v2/lightclient.go index b531e29111..9ab4b7d0c5 100644 --- a/core/vm/lightclient/v2/lightclient.go +++ b/core/vm/lightclient/v2/lightclient.go @@ -36,6 +36,81 @@ type ConsensusState struct { ValidatorSet *types.ValidatorSet } +type validatorDuplicateTracker struct { + field string + seen map[string]int + ignoreZero bool +} + +func newValidatorDuplicateTracker(field string, size int, ignoreZero bool) *validatorDuplicateTracker { + return &validatorDuplicateTracker{ + field: field, + seen: make(map[string]int, size), + ignoreZero: ignoreZero, + } +} + +func (t *validatorDuplicateTracker) check(idx int, value []byte) error { + if t.ignoreZero { + // Optional bridge fields may be omitted in source validators or zero-filled by + // fixed-width decoding. Both forms mean "unset" and should not count as duplicates. + if len(value) == 0 || isZeroBytes(value) { + return nil + } + } + + key := string(value) + if firstIdx, ok := t.seen[key]; ok { + return fmt.Errorf("duplicate validator %s #%d and #%d: %X", t.field, firstIdx, idx, value) + } + t.seen[key] = idx + return nil +} + +func isZeroBytes(value []byte) bool { + if len(value) == 0 { + return false + } + for _, b := range value { + if b != 0 { + return false + } + } + return true +} + +func validateUniqueValidatorSet(validatorSet *types.ValidatorSet) error { + if validatorSet == nil { + return nil + } + + size := len(validatorSet.Validators) + addresses := newValidatorDuplicateTracker("address", size, false) + pubKeys := newValidatorDuplicateTracker("pubkey", size, false) + blsKeys := newValidatorDuplicateTracker("bls key", size, true) + relayerAddresses := newValidatorDuplicateTracker("relayer address", size, true) + + for idx, validator := range validatorSet.Validators { + if validator == nil || validator.PubKey == nil { + return fmt.Errorf("invalid validator #%d", idx) + } + if err := addresses.check(idx, validator.Address); err != nil { + return err + } + if err := pubKeys.check(idx, validator.PubKey.Bytes()); err != nil { + return err + } + if err := blsKeys.check(idx, validator.BlsKey); err != nil { + return err + } + if err := relayerAddresses.check(idx, validator.RelayerAddress); err != nil { + return err + } + } + + return nil +} + // output: // | chainID | height | nextValidatorSetHash | [{validator pubkey, voting power, relayer address, relayer bls pubkey}] | // | 32 bytes | 8 bytes | 32 bytes | [{32 bytes, 8 bytes, 20 bytes, 48 bytes}] | @@ -137,7 +212,7 @@ func (cs *ConsensusState) ApplyLightBlock(block *types.LightBlock, isHertz bool) // input: // | chainID | height | nextValidatorSetHash | [{validator pubkey, voting power, relayer address, relayer bls pubkey}] | // | 32 bytes | 8 bytes | 32 bytes | [{32 bytes, 8 bytes, 20 bytes, 48 bytes}] | -func DecodeConsensusState(input []byte) (ConsensusState, error) { +func DecodeConsensusState(input []byte, requireUniqueValidators bool) (ConsensusState, error) { minimumLength := chainIDLength + heightLength + validatorSetHashLength inputLen := uint64(len(input)) if inputLen <= minimumLength || (inputLen-minimumLength)%singleValidatorBytesLength != 0 { @@ -192,6 +267,11 @@ func DecodeConsensusState(input []byte) (ConsensusState, error) { Validators: validatorSet, }, } + if requireUniqueValidators { + if err := validateUniqueValidatorSet(consensusState.ValidatorSet); err != nil { + return ConsensusState{}, err + } + } return consensusState, nil } @@ -199,7 +279,7 @@ func DecodeConsensusState(input []byte) (ConsensusState, error) { // input: // consensus state length | consensus state | light block | // 32 bytes | | | -func DecodeLightBlockValidationInput(input []byte) (*ConsensusState, *types.LightBlock, error) { +func DecodeLightBlockValidationInput(input []byte, requireUniqueValidators bool) (*ConsensusState, *types.LightBlock, error) { if uint64(len(input)) <= consensusStateLengthBytesLength { return nil, nil, errors.New("invalid input") } @@ -214,7 +294,7 @@ func DecodeLightBlockValidationInput(input []byte) (*ConsensusState, *types.Ligh return nil, nil, fmt.Errorf("expected payload size %d, actual size: %d", consensusStateLengthBytesLength+csLen, len(input)) } - cs, err := DecodeConsensusState(input[consensusStateLengthBytesLength : consensusStateLengthBytesLength+csLen]) + cs, err := DecodeConsensusState(input[consensusStateLengthBytesLength:consensusStateLengthBytesLength+csLen], requireUniqueValidators) if err != nil { return nil, nil, err } @@ -228,6 +308,11 @@ func DecodeLightBlockValidationInput(input []byte) (*ConsensusState, *types.Ligh if err != nil { return nil, nil, err } + if requireUniqueValidators { + if err := validateUniqueValidatorSet(block.ValidatorSet); err != nil { + return nil, nil, err + } + } return &cs, block, nil } diff --git a/core/vm/lightclient/v2/lightclient_test.go b/core/vm/lightclient/v2/lightclient_test.go index 0a7d43f525..9c7bfae833 100644 --- a/core/vm/lightclient/v2/lightclient_test.go +++ b/core/vm/lightclient/v2/lightclient_test.go @@ -3,6 +3,7 @@ package v2 import ( "bytes" + "encoding/binary" "encoding/hex" "testing" @@ -144,7 +145,7 @@ func TestDecodeConsensusState(t *testing.T) { csBytes, err := hex.DecodeString(testcase.consensusStateBytes) require.NoError(t, err) - cs, err := DecodeConsensusState(csBytes) + cs, err := DecodeConsensusState(csBytes, false) require.NoError(t, err) if cs.ChainID != testcase.chainID { @@ -182,7 +183,7 @@ func TestConsensusStateApplyLightBlock(t *testing.T) { block, err := types.LightBlockFromProto(&lbpb) require.NoError(t, err) - cs, err := DecodeConsensusState(csBytes) + cs, err := DecodeConsensusState(csBytes, false) require.NoError(t, err) validatorSetChanged, err := cs.ApplyLightBlock(block, true) require.NoError(t, err) @@ -196,3 +197,125 @@ func TestConsensusStateApplyLightBlock(t *testing.T) { } } } + +func TestDecodeConsensusStateWithValidationRejectsDuplicateValidators(t *testing.T) { + csBytes, err := hex.DecodeString(testcases[0].consensusStateBytes) + require.NoError(t, err) + + validatorBytes := csBytes[chainIDLength+heightLength+validatorSetHashLength:] + duplicateConsensusState := append([]byte{}, csBytes[:chainIDLength+heightLength+validatorSetHashLength]...) + duplicateConsensusState = append(duplicateConsensusState, validatorBytes...) + duplicateConsensusState = append(duplicateConsensusState, validatorBytes...) + + _, err = DecodeConsensusState(duplicateConsensusState, true) + require.ErrorContains(t, err, "duplicate validator") +} + +func TestValidateUniqueValidatorSetRejectsDuplicateBridgeKeys(t *testing.T) { + makeValidator := func(info validatorInfo) *types.Validator { + t.Helper() + + pubKeyBytes, err := hex.DecodeString(info.pubKey) + require.NoError(t, err) + relayerAddress, err := hex.DecodeString(info.relayerAddress) + require.NoError(t, err) + relayerBlsKey, err := hex.DecodeString(info.relayerBlsKey) + require.NoError(t, err) + + pubkey := ed25519.PubKey(make([]byte, ed25519.PubKeySize)) + copy(pubkey[:], pubKeyBytes) + validator := types.NewValidator(pubkey, info.votingPower) + validator.SetRelayerAddress(relayerAddress) + validator.SetBlsKey(relayerBlsKey) + return validator + } + + t.Run("duplicate bls key", func(t *testing.T) { + first := makeValidator(testcases[1].vals[0]) + second := makeValidator(testcases[1].vals[1]) + second.SetBlsKey(append([]byte{}, first.BlsKey...)) + + err := validateUniqueValidatorSet(&types.ValidatorSet{Validators: []*types.Validator{first, second}}) + require.ErrorContains(t, err, "duplicate validator bls key") + }) + + t.Run("duplicate relayer address", func(t *testing.T) { + first := makeValidator(testcases[1].vals[0]) + second := makeValidator(testcases[1].vals[1]) + second.SetRelayerAddress(append([]byte{}, first.RelayerAddress...)) + + err := validateUniqueValidatorSet(&types.ValidatorSet{Validators: []*types.Validator{first, second}}) + require.ErrorContains(t, err, "duplicate validator relayer address") + }) +} + +func TestDecodeConsensusStateWithValidationAllowsUnsetBridgeKeys(t *testing.T) { + makeValidator := func(seed byte) *types.Validator { + t.Helper() + + pubkey := ed25519.PubKey(make([]byte, ed25519.PubKeySize)) + for i := range pubkey { + pubkey[i] = seed + byte(i) + 1 + } + + return types.NewValidator(pubkey, 100) + } + + consensusState := ConsensusState{ + ChainID: "chain_9000-121", + Height: 1, + NextValidatorSetHash: bytes.Repeat([]byte{0xAB}, int(validatorSetHashLength)), + ValidatorSet: &types.ValidatorSet{ + Validators: []*types.Validator{ + makeValidator(0x01), + makeValidator(0x02), + }, + }, + } + + csBytes, err := consensusState.EncodeConsensusState() + require.NoError(t, err) + + _, err = DecodeConsensusState(csBytes, true) + require.NoError(t, err) +} + +func TestIsZeroBytesRequiresNonEmptyInput(t *testing.T) { + require.False(t, isZeroBytes(nil)) + require.False(t, isZeroBytes([]byte{})) + require.True(t, isZeroBytes([]byte{0x00, 0x00})) + require.False(t, isZeroBytes([]byte{0x00, 0x01})) +} + +func TestDecodeLightBlockValidationInputAllowsUnsetBlockBridgeKeys(t *testing.T) { + csBytes, err := hex.DecodeString(applyBlocksTestcases[0].consensusStateBytes) + require.NoError(t, err) + + blockBytes, err := hex.DecodeString(applyBlocksTestcases[0].lightBlockBytes) + require.NoError(t, err) + + var lbpb tmproto.LightBlock + err = lbpb.Unmarshal(blockBytes) + require.NoError(t, err) + + block, err := types.LightBlockFromProto(&lbpb) + require.NoError(t, err) + + for _, validator := range block.ValidatorSet.Validators { + validator.SetBlsKey(nil) + validator.SetRelayerAddress(nil) + } + + blockProto, err := block.ToProto() + require.NoError(t, err) + blockBytes, err = blockProto.Marshal() + require.NoError(t, err) + + input := make([]byte, consensusStateLengthBytesLength) + binary.BigEndian.PutUint64(input[consensusStateLengthBytesLength-uint64TypeLength:], uint64(len(csBytes))) + input = append(input, csBytes...) + input = append(input, blockBytes...) + + _, _, err = DecodeLightBlockValidationInput(input, true) + require.NoError(t, err) +} From 3150087245b12b3de8f11a7274ac3fe341b13589 Mon Sep 17 00:00:00 2001 From: wayen <19421226+flywukong@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:35:56 +0800 Subject: [PATCH 39/48] miner: support builder-proposed block with validator blind signing (#3691) * miner: implement zero-simulate MEV * miner: implement validator-side BidBlock handling * fix: refine enable bidblock config * miner: switch BidBlock vs simBid to two-stage selection * fix: use builder timestamp when committing BidBlock * miner: split BidBlock verify and sign * miner: verify BidBlock GasFee after InsertChain * miner: add BidBlock permission admission * miner: revoke BidBlock permission on insert or gas-fee failure * miner: add BidBlock permission RPC * miner: expose BidBlock permission block number * miner: skip revoked cached BidBlock * miner: revoke malformed BidBlock winners * miner: use must-before cutoff for BidBlock * miner: preserve builder header for BidBlock commit * miner: retry BidBlock candidates after failure * parlia: add bindSign system tx mode * parlia: expose builder finalize path * parlia: clarify BidBlock system tx signing * miner: support builder header preparation * miner: preserve BidBlock execution header * miner: align BidBlock system tx shape * miner: reject disabled BidBlock submissions * docs: drop BidBlock draft notes * miner: align bid simulator constructor * parlia: clarify generated tx signing flag * parlia: align generated tx signing flag * ethclient: add BidBlock RPC helpers * parlia: align builder block time validator * miner: reject BidBlock with unknown parent * miner: align BidBlock selection gate * miner: refine BidBlock helper names * miner: address BidBlock review feedback * miner: use deterministic BidBlock timestamp * miner: address BidBlock review comments * miner: simplify BidBlock fork checks * miner: address BidBlock review nits * parlia: use mode for system tx processing * miner: prepare BidBlock before enqueue * miner: log BidBlock bid comparison * miner: simplify BidBlock candidate cache * miner: keep one best BidBlock * miner: return BidBlock cache feedback * miner: share double-sign check * miner: refine BidBlock validation flow * miner: simplify BidBlock selection state * miner: resolve develop rebase conflict * miner: simplify BidBlock task state * miner: validate BidBlock system tx ABI * miner: clean up BidBlock review fixes * miner: use fixed BidBlock system selectors * miner: align BidBlock assembly return values * miner: simplify BidBlock decoded payload * miner: simplify BidBlock selection comments * miner: add admin BidBlock permission control * miner: defer BidBlock revoke until post-insert * miner: simplify BidBlock permission checks * miner: simplify BidBlock permission manager * miner: simplify BidBlock preseal checks * miner: avoid retaining work for BidBlock * miner: simplify BidBlock validation flow * miner: derive BidBlock gas fee from deposit * miner: require BidBlock deposit tx * miner: simplify BidBlock tx shape * miner: simplify BidBlock config prep * miner: check BidBlock parent header * miner: organize BidBlock helpers * miner: verify BidBlock at admission * miner: gofmt BidBlock metrics * miner: preserve builder vanity in BidBlock extra-data * miner: dedupe BidBlock system-tx scan, expose BidBlockEnabled * consensus/parlia: check upperlimit for header.Time when blockTimeVerify (#26) * consensus/parlia: share Prepare core with BidBlock builder * consensus/parlia: unexport BidBlock system-tx helpers * consensus/parlia: simplify ExtractBidBlockDepositValue scan * miner: have validator own BidBlock extra-data * miner: address BidBlock review feedback * types: normalize empty BidBlock sidecars * miner: preserve empty BidBlock withdrawals body * miner: trim redundant BidBlock entry guards * miner: mini improve (#27) * miner: surface revoke error detail to builders * miner: use rolling BidBlock revoke window * miner: encode block builder info in requests hash * fix: infer local mev blocks from empty builder * docs: clarify block mev info versions * miner: harden BidBlock checks and track revoked builders * miner: validate BidBlock blob sidecars before seal * check bidblock blob eligibility * miner: check BidBlock bid tx gas price * miner: check BidBlock non-system gas price * miner: use BidBlock gas fee for price check * miner: address BidBlock review comments. * miner: improve BidBlock blob validation error. * miner: enforce validator BidBlock gas limit. * Revert "consensus/parlia: check upperlimit for header.Time when blockTimeVerify (#26)" This reverts commit a8a9685cae6d650d8640711b1fee17c94408e9bf. * parlia: check upperlimit of block time * miner: simplify BidBlock revoke duration. * miner: add BidBlock RPC error codes. * mev: add bid block hash tracing * test: cover BidBlock consensus edge cases * miner: add BidBlock migration metrics * miner: gate BidBlock on Pasteur fork and default-enable * miner: fold Pasteur gate into BidBlock enablement --------- Co-authored-by: formless <213398294+allformless@users.noreply.github.com> --- cmd/jsutils/getchainstatus.js | 130 +++++-- consensus/parlia/bid_block.go | 224 ++++++++++++ consensus/parlia/bid_block_test.go | 84 +++++ consensus/parlia/feynmanfork.go | 10 +- consensus/parlia/parlia.go | 112 ++++-- consensus/parlia/parlia_test.go | 430 ++++++++++++++++++++++- consensus/parlia/ramanujanfork.go | 2 +- core/types/bid.go | 97 +++++ core/types/bid_block_permission.go | 16 + core/types/bid_error.go | 25 +- core/types/bid_test.go | 64 ++++ core/types/block_mev_info.go | 59 ++++ core/types/block_mev_info_test.go | 50 +++ eth/api_admin.go | 5 + eth/api_backend.go | 8 + ethclient/ethclient.go | 30 ++ internal/ethapi/api.go | 43 +++ internal/ethapi/api_mev.go | 76 ++++ internal/ethapi/api_test.go | 45 +++ internal/ethapi/backend.go | 4 + internal/ethapi/transaction_args_test.go | 6 + internal/web3ext/web3ext.go | 6 + miner/bid_block.go | 319 +++++++++++++++++ miner/bid_block_permission.go | 153 ++++++++ miner/bid_block_permission_test.go | 413 ++++++++++++++++++++++ miner/bid_gas_price.go | 41 +++ miner/bid_gas_price_test.go | 48 +++ miner/bid_simulator.go | 291 ++++++++++++++- miner/miner.go | 3 +- miner/miner_mev.go | 106 ++++++ miner/miner_mev_test.go | 21 ++ miner/minerconfig/config.go | 9 + miner/worker.go | 161 ++++++--- miner/worker_test.go | 90 ++++- 34 files changed, 3032 insertions(+), 149 deletions(-) create mode 100644 consensus/parlia/bid_block.go create mode 100644 consensus/parlia/bid_block_test.go create mode 100644 core/types/bid_block_permission.go create mode 100644 core/types/bid_test.go create mode 100644 core/types/block_mev_info.go create mode 100644 core/types/block_mev_info_test.go create mode 100644 miner/bid_block.go create mode 100644 miner/bid_block_permission.go create mode 100644 miner/bid_block_permission_test.go create mode 100644 miner/bid_gas_price.go create mode 100644 miner/bid_gas_price_test.go diff --git a/cmd/jsutils/getchainstatus.js b/cmd/jsutils/getchainstatus.js index b74864047c..c00e704354 100644 --- a/cmd/jsutils/getchainstatus.js +++ b/cmd/jsutils/getchainstatus.js @@ -290,6 +290,58 @@ const builderMap = new Map([ ["0xA8caEc0D68a90Ac971EA1aDEFA1747447e1f9871", "blockroute"], ]); +function getMappedAddressName(addressMap, address) { + if (!address) return undefined; + try { + const normalized = ethers.getAddress(address); + return addressMap.get(normalized) || addressMap.get(normalized.toLowerCase()); + } catch (_) { + return addressMap.get(address); + } +} + +async function getBlockMevInfo(blockNumber) { + let rpcInfo; + try { + rpcInfo = await provider.send("eth_getBlockMevInfo", ["0x" + blockNumber.toString(16)]); + if (rpcInfo) { + if (!rpcInfo.builder) { + return { ...rpcInfo, source: "local" }; + } + const source = rpcInfo.version === "v2" ? "bidblock" : "bid"; + return { ...rpcInfo, source }; + } + } catch (_) { + // Older validators do not expose eth_getBlockMevInfo; fall back to the + // pre-BEP-675 payment-tx heuristic below. + } + + const block = await provider.getBlock(blockNumber); + if (!block) return rpcInfo || { blockNumber, source: "local" }; + + const txHashes = block.transactions.slice(-4); + const txResults = await Promise.all(txHashes.map(txHash => provider.getTransaction(txHash))); + for (const txData of txResults) { + if (!txData || !txData.to || !getMappedAddressName(builderMap, txData.to)) continue; + return { + blockNumber: block.number, + blockHash: block.hash, + miner: block.miner, + source: "bid", + builder: txData.to, + fallback: true, + }; + } + + return { + ...(rpcInfo || {}), + blockNumber: rpcInfo ? (rpcInfo.blockNumber || block.number) : block.number, + blockHash: rpcInfo ? (rpcInfo.blockHash || block.hash) : block.hash, + miner: rpcInfo ? (rpcInfo.miner || block.miner) : block.miner, + source: "local", + }; +} + // 1.cmd: "GetMaxTxCountInBlockRange", usage: // node getchainstatus.js GetMaxTxCountInBlockRange --rpc https://bsc-testnet-dataseed.bnbchain.org \ // --startNum 40000001 --endNum 40000005 \ @@ -856,6 +908,8 @@ async function getMevStatus() { local: 0, ...Object.fromEntries([...new Set(builderMap.values())].map(builder => [builder, 0])) }; + // Per-type tallies for the MEV path breakdown (v1 = legacy SendBid, v2 = bidblock). + let typeCounts = { mev_v1: 0, mev_v2: 0, local: 0 }; // Get the latest block number const latestBlock = await provider.getBlockNumber(); @@ -877,12 +931,18 @@ async function getMevStatus() { return; } - const blockPromises = []; + const blockNumbers = []; for (let i = startBlock; i <= endBlock; i++) { - blockPromises.push(provider.getBlock(i)); + blockNumbers.push(i); } - const blocks = await Promise.all(blockPromises); + let mevInfos; + try { + mevInfos = await Promise.all(blockNumbers.map(getBlockMevInfo)); + } catch (err) { + console.error("GetMevStatus failed:", err.shortMessage || err.message || err); + return; + } // Calculate max lengths for alignment with default values let maxMinerLength = 10; // Default length @@ -898,38 +958,39 @@ async function getMevStatus() { maxBuilderLength = Math.max(...builderLengths); } - for (const blockData of blocks) { - const minerInfo = validatorMap.get(blockData.miner); + for (const mevInfo of mevInfos) { + const blockNumber = typeof mevInfo.blockNumber === "string" + ? BigInt(mevInfo.blockNumber).toString() + : mevInfo.blockNumber.toString(); + const minerInfo = getMappedAddressName(validatorMap, mevInfo.miner); const miner = minerInfo ? minerInfo[0] : "Unknown"; - const transactions = blockData.transactions.slice(-4); // Last 4 transactions - const txPromises = transactions.map(txHash => provider.getTransaction(txHash)); - - const txResults = await Promise.all(txPromises); - let mevBlock = false; - - for (const txData of txResults) { - if (builderMap.has(txData.to)) { - const builder = builderMap.get(txData.to); - counts[builder]++; - - mevBlock = true; - console.log( - `blockNum: ${blockData.number.toString().padStart(8)} ` + - `miner: ${miner.padEnd(maxMinerLength)} ` + - `builder: (${builder.padEnd(maxBuilderLength)}) ${txData.to}` - ); - break; - } - } - if (!mevBlock) { - counts.local++; + if (mevInfo.source !== "local") { + const builderName = getMappedAddressName(builderMap, mevInfo.builder); + const friendlyName = builderName || mevInfo.builder; + const bucket = builderName || mevInfo.builder; + // v2 = bidblock (tagged), everything else on the MEV path = v1 + // (tagged legacy bid, or heuristic-detected payBidTx which is v1-only). + const typeLabel = (mevInfo.source === "bidblock" || mevInfo.version === "v2") ? "mev_v2" : "mev_v1"; + counts[bucket] = (counts[bucket] || 0) + 1; + typeCounts[typeLabel]++; console.log( - `blockNum: ${blockData.number.toString().padStart(8)} ` + + `blockNum: ${blockNumber.padStart(8)} ` + + `type: ${typeLabel.padEnd(6)} ` + `miner: ${miner.padEnd(maxMinerLength)} ` + - `builder: local` + `builder: (${friendlyName.padEnd(maxBuilderLength)}) ${mevInfo.builder}` ); + continue; } + + counts.local++; + typeCounts.local++; + console.log( + `blockNum: ${blockNumber.padStart(8)} ` + + `type: ${"local".padEnd(6)} ` + + `miner: ${miner.padEnd(maxMinerLength)} ` + + `builder: local` + ); } const total = endBlock - startBlock + 1; @@ -947,6 +1008,17 @@ async function getMevStatus() { const ratio = (value * 100 / total).toFixed(2); console.log(`${key.padEnd(maxBuilderLength)}: ${value.toString().padStart(3)} blocks (${ratio}%)`); }); + + // MEV path breakdown: v1 (legacy SendBid) vs v2 (bidblock), as a share of MEV blocks. + const mevTotal = typeCounts.mev_v1 + typeCounts.mev_v2; + console.log("\nMEV Path Distribution:"); + console.log(`MEV blocks: ${mevTotal} (${(mevTotal * 100 / total).toFixed(2)}% of total)`); + if (mevTotal > 0) { + const v1Ratio = (typeCounts.mev_v1 * 100 / mevTotal).toFixed(2); + const v2Ratio = (typeCounts.mev_v2 * 100 / mevTotal).toFixed(2); + console.log(`${"mev_v1".padEnd(8)}: ${typeCounts.mev_v1.toString().padStart(3)} blocks (${v1Ratio}% of MEV)`); + console.log(`${"mev_v2".padEnd(8)}: ${typeCounts.mev_v2.toString().padStart(3)} blocks (${v2Ratio}% of MEV)`); + } } // 11.cmd: "getLargeTxs", usage: diff --git a/consensus/parlia/bid_block.go b/consensus/parlia/bid_block.go new file mode 100644 index 0000000000..7f6b3dcf62 --- /dev/null +++ b/consensus/parlia/bid_block.go @@ -0,0 +1,224 @@ +package parlia + +import ( + "bytes" + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/accounts" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus" + "github.com/ethereum/go-ethereum/core/state" + "github.com/ethereum/go-ethereum/core/systemcontracts" + "github.com/ethereum/go-ethereum/core/tracing" + "github.com/ethereum/go-ethereum/core/types" +) + +var signableSystemTxSelectors = map[string][4]byte{ + "deposit": {0xf3, 0x40, 0xfa, 0x01}, + "distributeFinalityReward": {0x30, 0x0c, 0x35, 0x67}, + "updateValidatorSetV2": {0x1e, 0x4c, 0x15, 0x24}, +} + +type expectedSystemTxEntry struct { + method string + selector [4]byte +} + +// PrepareForBidBlock is Prepare with Coinbase set to the in-turn validator instead of p.val. +func (p *Parlia) PrepareForBidBlock(chain consensus.ChainHeaderReader, header *types.Header) error { + // Coinbase must be set before prepare(): backOffTime and calcDifficulty depend on it. + number := header.Number.Uint64() + snap, err := p.snapshot(chain, number-1, header.ParentHash, nil) + if err != nil { + return err + } + header.Coinbase = snap.inturnValidator() + return p.prepare(chain, header) +} + +// FinalizeAndAssembleBidBlock assembles a BidBlock with unsigned system txs. +func (p *Parlia) FinalizeAndAssembleBidBlock(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, + body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, []*types.Receipt, error) { + block, receipts, err := p.finalizeAndAssemble(chain, header, state, body, receipts, tracer, systemTxPacking) + if err != nil { + return nil, nil, err + } + return block, receipts, nil +} + +// SignSystemTx signs a BidBlock system tx with the validator key. +func (p *Parlia) SignSystemTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + p.lock.RLock() + defer p.lock.RUnlock() + if p.signTxFn == nil { + return nil, errors.New("signTxFn not set") + } + return p.signTxFn(accounts.Account{Address: p.val}, tx, chainID) +} + +// isUnsignedSystemTxCandidate reports whether tx looks like an unsigned +// BidBlock system tx. It does not recover the sender. +func (p *Parlia) isUnsignedSystemTxCandidate(tx *types.Transaction) bool { + if tx == nil || tx.To() == nil || !isToSystemContract(*tx.To()) { + return false + } + if tx.GasPrice() == nil || tx.GasPrice().Sign() != 0 { + return false + } + v, r, s := tx.RawSignatureValues() + return isZeroSig(v, r, s) +} + +// isSignableSystemTx reports whether tx can be bind-signed for BidBlock. +func (p *Parlia) isSignableSystemTx(tx *types.Transaction) bool { + if !p.isUnsignedSystemTxCandidate(tx) { + return false + } + if *tx.To() != common.HexToAddress(systemcontracts.ValidatorContract) { + return false + } + return p.hasSignableSelector(tx.Data()) +} + +// expectedSystemTxShape returns the expected trailing system-tx order for accepted BidBlocks: +// +// deposit -> distributeFinalityReward (cond.) -> updateValidatorSetV2 (cond.) +// +// Precondition: BidBlock admission has already enforced a non-zero deposit value. +func (p *Parlia) expectedSystemTxShape(header, parent *types.Header) []expectedSystemTxEntry { + shape := make([]expectedSystemTxEntry, 0, 3) + + shape = append(shape, expectedSystemTxEntry{ + method: "deposit", + selector: p.selectorFor("deposit"), + }) + + if header.Number.Uint64()%finalityRewardInterval == 0 { + shape = append(shape, expectedSystemTxEntry{ + method: "distributeFinalityReward", + selector: p.selectorFor("distributeFinalityReward"), + }) + } + + if isBreatheBlock(parent.Time, header.Time) { + shape = append(shape, expectedSystemTxEntry{ + method: "updateValidatorSetV2", + selector: p.selectorFor("updateValidatorSetV2"), + }) + } + + return shape +} + +func (p *Parlia) verifySystemTxShape(txs []*types.Transaction, shape []expectedSystemTxEntry) error { + if len(txs) < len(shape) { + return fmt.Errorf("missing required system tx %q", shape[len(txs)].method) + } + if len(txs) > len(shape) { + return fmt.Errorf("unexpected extra system tx at position %d (selector 0x%x)", + len(shape), txSelector(txs[len(shape)])) + } + for i, exp := range shape { + if !bytes.HasPrefix(txs[i].Data(), exp.selector[:]) { + return fmt.Errorf("expected system tx %q at position %d, got selector 0x%x", + exp.method, i, txSelector(txs[i])) + } + } + return nil +} + +// ExtractBidBlockDepositValue locates the trailing unsigned system-tx region and +// returns its start index along with the value of the deposit tx (zero if absent). +func (p *Parlia) ExtractBidBlockDepositValue(txs []*types.Transaction) (int, *big.Int) { + systemTxStart := len(txs) + for i := len(txs) - 1; i >= 0; i-- { + if !p.isUnsignedSystemTxCandidate(txs[i]) { + break + } + systemTxStart = i + } + // Deposit is the first trailing unsigned system tx (see expectedSystemTxShape). + // systemTxStart == 0 means there are no preceding user txs to collect fees from, + // which is invalid by design — return zero GasFee so admission rejects it. + if systemTxStart > 0 && systemTxStart < len(txs) { + depositSel := p.selectorFor("deposit") + if bytes.HasPrefix(txs[systemTxStart].Data(), depositSel[:]) { + return systemTxStart, new(big.Int).Set(txs[systemTxStart].Value()) + } + } + return systemTxStart, new(big.Int) +} + +// VerifyBidBlockSystemTxs validates the trailing unsigned system-tx region starting at systemTxStart. +// +// Stage 1 — each trailing unsigned tx must be on the BEP-675 signable whitelist. +// Stage 2 — selectors & order must match expectedSystemTxShape for this header. +func (p *Parlia) VerifyBidBlockSystemTxs(decoded *types.DecodedBidBlock, parent *types.Header, systemTxStart int) error { + for i := systemTxStart; i < len(decoded.Txs); i++ { + if !p.isSignableSystemTx(decoded.Txs[i]) { + toAddr := "" + if decoded.Txs[i].To() != nil { + toAddr = decoded.Txs[i].To().Hex() + } + return fmt.Errorf("unsigned system tx at position %d (to=%s) is not on the signable whitelist", i, toAddr) + } + } + shape := p.expectedSystemTxShape(decoded.Header, parent) + return p.verifySystemTxShape(decoded.Txs[systemTxStart:], shape) +} + +func (p *Parlia) hasSignableSelector(data []byte) bool { + if len(data) < 4 { + return false + } + selector := data[:4] + for _, methodSelector := range signableSystemTxSelectors { + if bytes.Equal(selector, methodSelector[:]) { + return true + } + } + return false +} + +func (p *Parlia) selectorFor(methodName string) [4]byte { + selector, ok := signableSystemTxSelectors[methodName] + if !ok { + panic(fmt.Sprintf("missing fixed system tx selector %s", methodName)) + } + return selector +} + +func (p *Parlia) BlockTimeUpperCheck(chain consensus.ChainHeaderReader, header *types.Header) error { + number := header.Number.Uint64() + snap, err := p.snapshot(chain, number-1, header.ParentHash, nil) + if err != nil { + return err + } + + parent := chain.GetHeader(header.ParentHash, number-1) + if parent == nil { + return consensus.ErrUnknownAncestor + } + + maxAllowed := p.blockTimeForRamanujanFork(snap, header, parent) + if header.MilliTimestamp() > maxAllowed { + return fmt.Errorf("BidBlock time too far in future: headerTime=%d, maxAllowed=%d", + header.MilliTimestamp(), maxAllowed) + } + return nil +} + +func txSelector(tx *types.Transaction) []byte { + data := tx.Data() + if len(data) < 4 { + return data + } + return data[:4] +} + +func isZeroSig(v, r, s *big.Int) bool { + isZero := func(x *big.Int) bool { return x == nil || x.Sign() == 0 } + return isZero(v) && isZero(r) && isZero(s) +} diff --git a/consensus/parlia/bid_block_test.go b/consensus/parlia/bid_block_test.go new file mode 100644 index 0000000000..1899fc8cc3 --- /dev/null +++ b/consensus/parlia/bid_block_test.go @@ -0,0 +1,84 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. + +package parlia + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/systemcontracts" + "github.com/ethereum/go-ethereum/core/types" +) + +// sysTx builds an unsigned system-tx candidate: to=ValidatorContract, gasPrice=0, +// zero signature, data prefixed with the given selector. +func sysTx(selector []byte, value *big.Int) *types.Transaction { + to := common.HexToAddress(systemcontracts.ValidatorContract) + return types.NewTx(&types.LegacyTx{ + GasPrice: big.NewInt(0), + Gas: 100000, + To: &to, + Value: value, + Data: selector, + }) +} + +// userTx is a normal user tx (nonzero gasPrice, non-system recipient): never a +// system-tx candidate, so it stops the trailing-region scan. +func userTx() *types.Transaction { + to := common.HexToAddress("0x1111111111111111111111111111111111111111") + return types.NewTx(&types.LegacyTx{GasPrice: big.NewInt(1), Gas: 21000, To: &to, Value: big.NewInt(0)}) +} + +func TestVerifyBidBlockSystemTxs(t *testing.T) { + p := &Parlia{} + // Number 100 (not a multiple of finalityRewardInterval=200) + same-UTC-day + // timestamps (not a breathe block) => expected shape is exactly [deposit]. + header := &types.Header{Number: big.NewInt(100), Time: 1003} + parent := &types.Header{Number: big.NewInt(99), Time: 1000} + + depositSel := signableSystemTxSelectors["deposit"] + finalitySel := signableSystemTxSelectors["distributeFinalityReward"] + deposit := func(v int64) *types.Transaction { return sysTx(depositSel[:], big.NewInt(v)) } + + tests := []struct { + name string + txs types.Transactions + sysStart int + wantErr bool + }{ + {"valid [deposit]", types.Transactions{userTx(), deposit(5)}, 1, false}, + {"non-whitelist selector", types.Transactions{userTx(), sysTx([]byte{0xde, 0xad, 0xbe, 0xef}, big.NewInt(5))}, 1, true}, + {"wrong order (finalityReward where deposit expected)", types.Transactions{userTx(), sysTx(finalitySel[:], big.NewInt(0))}, 1, true}, + {"missing deposit (empty trailing region)", types.Transactions{userTx()}, 1, true}, + {"extra system tx", types.Transactions{userTx(), deposit(5), deposit(6)}, 1, true}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + decoded := &types.DecodedBidBlock{Header: header, Txs: tc.txs} + err := p.VerifyBidBlockSystemTxs(decoded, parent, tc.sysStart) + if (err != nil) != tc.wantErr { + t.Fatalf("VerifyBidBlockSystemTxs err=%v, wantErr=%v", err, tc.wantErr) + } + }) + } +} + +func TestExtractBidBlockDepositValue(t *testing.T) { + p := &Parlia{} + depositSel := signableSystemTxSelectors["deposit"] + + // systemTxStart > 0: deposit value is returned as GasFee. + start, fee := p.ExtractBidBlockDepositValue(types.Transactions{userTx(), sysTx(depositSel[:], big.NewInt(7))}) + if start != 1 || fee.Cmp(big.NewInt(7)) != 0 { + t.Fatalf("with user tx: got (start=%d, fee=%v), want (1, 7)", start, fee) + } + + // systemTxStart == 0 (no preceding user tx): GasFee must be zero so admission rejects it. + start, fee = p.ExtractBidBlockDepositValue(types.Transactions{sysTx(depositSel[:], big.NewInt(7))}) + if start != 0 || fee.Sign() != 0 { + t.Fatalf("no user tx: got (start=%d, fee=%v), want (0, 0)", start, fee) + } +} diff --git a/consensus/parlia/feynmanfork.go b/consensus/parlia/feynmanfork.go index 48bdf0ace9..832abfb262 100644 --- a/consensus/parlia/feynmanfork.go +++ b/consensus/parlia/feynmanfork.go @@ -29,9 +29,9 @@ func isBreatheBlock(lastBlockTime, blockTime uint64) bool { return lastBlockTime != 0 && !sameDayInUTC(lastBlockTime, blockTime) } -// initializeFeynmanContract initialize new contracts of Feynman fork +// initializeFeynmanContract initialize new contracts of Feynman fork. func (p *Parlia) initializeFeynmanContract(state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks, + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks, ) error { // method method := "initialize" @@ -54,7 +54,7 @@ func (p *Parlia) initializeFeynmanContract(state vm.StateDB, header *types.Heade msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0) // apply message log.Info("initialize feynman contract", "block number", header.Number.Uint64(), "contract", c) - err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) + err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mode, tracer) if err != nil { return err } @@ -97,7 +97,7 @@ func (h *ValidatorHeap) Pop() interface{} { } func (p *Parlia) updateValidatorSetV2(state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks, + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks, ) error { // 1. get all validators and its voting power blockNr := rpc.BlockNumberOrHashWithHash(header.ParentHash, false) @@ -124,7 +124,7 @@ func (p *Parlia) updateValidatorSetV2(state vm.StateDB, header *types.Header, ch // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mode, tracer) } func (p *Parlia) getValidatorElectionInfo(blockNr rpc.BlockNumberOrHash) ([]ValidatorItem, error) { diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go index a3e9db48b2..b2999a333a 100644 --- a/consensus/parlia/parlia.go +++ b/consensus/parlia/parlia.go @@ -285,6 +285,12 @@ func New( if err != nil { panic(err) } + for methodName, selector := range signableSystemTxSelectors { + method, ok := vABI.Methods[methodName] + if !ok || !bytes.Equal(method.ID, selector[:]) { + panic(fmt.Sprintf("invalid validator set ABI selector for %s", methodName)) + } + } sABI, err := abi.JSON(strings.NewReader(slashABI)) if err != nil { panic(err) @@ -1143,6 +1149,11 @@ func (p *Parlia) NextInTurnValidator(chain consensus.ChainHeaderReader, header * // header for running the transactions on top. func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error { header.Coinbase = p.val + return p.prepare(chain, header) +} + +// prepare is shared by Prepare and PrepareForBidBlock; caller sets Coinbase/Number/ParentHash. +func (p *Parlia) prepare(chain consensus.ChainHeaderReader, header *types.Header) error { header.Nonce = types.BlockNonce{} number := header.Number.Uint64() @@ -1151,29 +1162,34 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header return err } - // Set the correct difficulty - header.Difficulty = calcDifficulty(snap, p.val) + header.Difficulty = calcDifficulty(snap, header.Coinbase) - // Ensure the extra data has all it's components - if len(header.Extra) < extraVanity-nextForkHashSize { - header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-nextForkHashSize-len(header.Extra))...) - } - - // Ensure the timestamp has the correct delay parent := chain.GetHeader(header.ParentHash, number-1) if parent == nil { return consensus.ErrUnknownAncestor } blockTime := p.blockTimeForRamanujanFork(snap, header, parent) + header.Time = blockTime / 1000 // get seconds if p.chainConfig.IsLorentz(header.Number, header.Time) { header.SetMilliseconds(blockTime % 1000) } else { header.MixDigest = common.Hash{} } + return p.SetExtraData(chain, header) +} +// SetExtraData rebuilds the validator-controlled extra-data section: +// 28-byte vanity (caller-supplied, zero-padded) + 4-byte nextForkHash + +// validators bytes (epoch only) + turnLength (epoch only, post-Bohr) + 65 reserved seal bytes. +// Caller supplies the desired vanity in header.Extra; this function pads/truncates it. +func (p *Parlia) SetExtraData(chain consensus.ChainHeaderReader, header *types.Header) error { + // 32-byte vanity prefix: pad/truncate caller's vanity bytes, then append nextForkHash. + if len(header.Extra) < extraVanity-nextForkHashSize { + header.Extra = append(header.Extra, bytes.Repeat([]byte{0x00}, extraVanity-nextForkHashSize-len(header.Extra))...) + } header.Extra = header.Extra[:extraVanity-nextForkHashSize] - nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, chain.GenesisHeader().Time, number, header.Time) + nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, chain.GenesisHeader().Time, header.Number.Uint64(), header.Time) header.Extra = append(header.Extra, nextForkHash[:]...) if err := p.prepareValidators(chain, header); err != nil { @@ -1264,7 +1280,7 @@ func (p *Parlia) verifyTurnLength(chain consensus.ChainHeaderReader, header *typ func (p *Parlia) distributeFinalityReward(chain consensus.ChainHeaderReader, state vm.StateDB, header *types.Header, cx core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction, - usedGas *uint64, mining bool, tracer *tracing.Hooks) error { + usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks) error { currentHeight := header.Number.Uint64() if currentHeight%finalityRewardInterval != 0 { return nil @@ -1335,7 +1351,7 @@ func (p *Parlia) distributeFinalityReward(chain consensus.ChainHeaderReader, sta return err } msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0) - return p.applyTransaction(msg, state, header, cx, txs, receipts, systemTxs, usedGas, mining, tracer) + return p.applyTransaction(msg, state, header, cx, txs, receipts, systemTxs, usedGas, mode, tracer) } func (p *Parlia) EstimateGasReservedForSystemTxs(chain consensus.ChainHeaderReader, header *types.Header) uint64 { @@ -1403,7 +1419,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade systemcontracts.TryUpdateBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state, false) if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer) + err := p.initializeFeynmanContract(state, header, cx, txs, receipts, systemTxs, usedGas, systemTxImporting, tracer) if err != nil { return fmt.Errorf("init feynman contract failed: %v", err) } @@ -1411,7 +1427,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade // No block rewards in PoA, so the state remains as is and uncles are dropped if header.Number.Cmp(common.Big1) == 0 { - err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer) + err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, systemTxImporting, tracer) if err != nil { return errors.New("init contract failed") } @@ -1436,7 +1452,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade if !signedRecently { log.Trace("slash validator", "block hash", header.Hash(), "address", spoiledVal) - err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer) + err = p.slash(spoiledVal, state, header, cx, txs, receipts, systemTxs, usedGas, systemTxImporting, tracer) if err != nil { log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal, "err", err) } @@ -1452,13 +1468,13 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade intentionalDelayMiningCounter.Inc(1) log.Warn("intentional delay mining detected", "validator", val, "number", header.Number, "hash", header.Hash()) } - err = p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer) + err = p.distributeIncoming(val, state, header, cx, txs, receipts, systemTxs, usedGas, systemTxImporting, tracer) if err != nil { return err } if p.chainConfig.IsPlato(header.Number) { - if err := p.distributeFinalityReward(chain, state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer); err != nil { + if err := p.distributeFinalityReward(chain, state, header, cx, txs, receipts, systemTxs, usedGas, systemTxImporting, tracer); err != nil { return err } } @@ -1467,7 +1483,7 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) { // we should avoid update validators in the Feynman upgrade block if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, false, tracer); err != nil { + if err := p.updateValidatorSetV2(state, header, cx, txs, receipts, systemTxs, usedGas, systemTxImporting, tracer); err != nil { return err } } @@ -1479,10 +1495,21 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade return nil } -// FinalizeAndAssemble implements consensus.Engine, ensuring no uncles are set, -// nor block rewards given, and returns the final block. +type systemTxMode uint8 + +const ( + systemTxImporting systemTxMode = iota + systemTxMining + systemTxPacking +) + func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks) (*types.Block, []*types.Receipt, error) { + return p.finalizeAndAssemble(chain, header, state, body, receipts, tracer, systemTxMining) +} + +func (p *Parlia) finalizeAndAssemble(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, + body *types.Body, receipts []*types.Receipt, tracer *tracing.Hooks, mode systemTxMode) (*types.Block, []*types.Receipt, error) { // No block rewards in PoA, so the state remains as is and uncles are dropped cx := chainContext{ChainHeaderReader: chain, parlia: p} @@ -1501,14 +1528,14 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * systemcontracts.TryUpdateBuildInSystemContract(p.chainConfig, header.Number, parent.Time, header.Time, state, false) if p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - err := p.initializeFeynmanContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer) + err := p.initializeFeynmanContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, mode, tracer) if err != nil { return nil, nil, fmt.Errorf("init feynman contract failed: %v", err) } } if header.Number.Cmp(common.Big1) == 0 { - err := p.initContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer) + err := p.initContract(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, mode, tracer) if err != nil { return nil, nil, errors.New("init contract failed") } @@ -1532,20 +1559,20 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * } } if !signedRecently { - err = p.slash(spoiledVal, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer) + err = p.slash(spoiledVal, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, mode, tracer) if err != nil { log.Error("slash validator failed", "block hash", header.Hash(), "address", spoiledVal) } } } - err := p.distributeIncoming(p.val, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer) + err := p.distributeIncoming(header.Coinbase, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, mode, tracer) if err != nil { return nil, nil, err } if p.chainConfig.IsPlato(header.Number) { - if err := p.distributeFinalityReward(chain, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer); err != nil { + if err := p.distributeFinalityReward(chain, state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, mode, tracer); err != nil { return nil, nil, err } } @@ -1554,7 +1581,7 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header * if p.chainConfig.IsFeynman(header.Number, header.Time) && isBreatheBlock(parent.Time, header.Time) { // we should avoid update validators in the Feynman upgrade block if !p.chainConfig.IsOnFeynman(header.Number, parent.Time, header.Time) { - if err := p.updateValidatorSetV2(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, true, tracer); err != nil { + if err := p.updateValidatorSetV2(state, header, cx, &body.Transactions, &receipts, nil, &header.GasUsed, mode, tracer); err != nil { return nil, nil, err } } @@ -1952,7 +1979,7 @@ func (p *Parlia) isIntentionalDelayMining(chain consensus.ChainHeaderReader, hea // distributeIncoming distributes system incoming of the block func (p *Parlia) distributeIncoming(val common.Address, state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks) error { coinbase := header.Coinbase doDistributeSysReward := !p.chainConfig.IsKepler(header.Number, header.Time) && @@ -1964,7 +1991,7 @@ func (p *Parlia) distributeIncoming(val common.Address, state vm.StateDB, header if rewards.Cmp(common.U2560) > 0 { state.SetBalance(consensus.SystemAddress, balance.Sub(balance, rewards), tracing.BalanceChangeUnspecified) state.AddBalance(coinbase, rewards, tracing.BalanceChangeUnspecified) - err := p.distributeToSystem(rewards.ToBig(), state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) + err := p.distributeToSystem(rewards.ToBig(), state, header, chain, txs, receipts, receivedTxs, usedGas, mode, tracer) if err != nil { return err } @@ -1980,12 +2007,12 @@ func (p *Parlia) distributeIncoming(val common.Address, state vm.StateDB, header state.SetBalance(consensus.SystemAddress, common.U2560, tracing.BalanceDecreaseBSCDistributeReward) state.AddBalance(coinbase, balance, tracing.BalanceIncreaseBSCDistributeReward) log.Trace("distribute to validator contract", "block hash", header.Hash(), "amount", balance) - return p.distributeToValidator(balance.ToBig(), val, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) + return p.distributeToValidator(balance.ToBig(), val, state, header, chain, txs, receipts, receivedTxs, usedGas, mode, tracer) } // slash spoiled validators func (p *Parlia) slash(spoiledVal common.Address, state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks) error { // method method := "slash" @@ -2000,12 +2027,12 @@ func (p *Parlia) slash(spoiledVal common.Address, state vm.StateDB, header *type // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.SlashContract), data, common.Big0) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mode, tracer) } // init contract func (p *Parlia) initContract(state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks) error { // method method := "init" // contracts @@ -2028,7 +2055,7 @@ func (p *Parlia) initContract(state vm.StateDB, header *types.Header, chain core msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(c), data, common.Big0) // apply message log.Trace("init contract", "block hash", header.Hash(), "contract", c) - err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) + err = p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mode, tracer) if err != nil { return err } @@ -2037,17 +2064,17 @@ func (p *Parlia) initContract(state vm.StateDB, header *types.Header, chain core } func (p *Parlia) distributeToSystem(amount *big.Int, state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks) error { // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.SystemRewardContract), nil, amount) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mode, tracer) } // distributeToValidator deposits validator reward to validator contract func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address, state vm.StateDB, header *types.Header, chain core.ChainContext, - txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, tracer *tracing.Hooks) error { + txs *[]*types.Transaction, receipts *[]*types.Receipt, receivedTxs *[]*types.Transaction, usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks) error { // method method := "deposit" @@ -2062,7 +2089,7 @@ func (p *Parlia) distributeToValidator(amount *big.Int, validator common.Address // get system message msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, amount) // apply message - return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mining, tracer) + return p.applyTransaction(msg, state, header, chain, txs, receipts, receivedTxs, usedGas, mode, tracer) } // get system message @@ -2083,20 +2110,25 @@ func (p *Parlia) applyTransaction( header *types.Header, chainContext core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, - receivedTxs *[]*types.Transaction, usedGas *uint64, mining bool, + receivedTxs *[]*types.Transaction, usedGas *uint64, mode systemTxMode, tracer *tracing.Hooks, ) (applyErr error) { nonce := state.GetNonce(msg.From) expectedTx := types.NewTransaction(nonce, *msg.To, msg.Value, msg.GasLimit, msg.GasPrice, msg.Data) expectedHash := p.signer.Hash(expectedTx) - if msg.From == p.val && mining { + switch mode { + case systemTxMining: var err error + if msg.From != p.val { + return fmt.Errorf("cannot sign system tx from %s with validator %s", msg.From, p.val) + } expectedTx, err = p.signTxFn(accounts.Account{Address: msg.From}, expectedTx, p.chainConfig.ChainID) if err != nil { return err } - } else { + case systemTxPacking: + case systemTxImporting: if receivedTxs == nil || len(*receivedTxs) == 0 || (*receivedTxs)[0] == nil { return errors.New("supposed to get a actual transaction, but get none") } @@ -2114,6 +2146,8 @@ func (p *Parlia) applyTransaction( expectedTx = actualTx // move to next *receivedTxs = (*receivedTxs)[1:] + default: + return fmt.Errorf("unknown system tx mode %d", mode) } state.SetTxContext(expectedTx.Hash(), len(*txs)) diff --git a/consensus/parlia/parlia_test.go b/consensus/parlia/parlia_test.go index 7b7b50a6ea..c1fad5e51b 100644 --- a/consensus/parlia/parlia_test.go +++ b/consensus/parlia/parlia_test.go @@ -1,6 +1,7 @@ package parlia import ( + "bytes" "crypto/ecdsa" "crypto/rand" "fmt" @@ -9,12 +10,15 @@ import ( "slices" "strings" "testing" + "time" + "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/common" cmath "github.com/ethereum/go-ethereum/common/math" "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/misc/eip4844" "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/forkid" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/systemcontracts" @@ -703,7 +707,7 @@ func TestParlia_applyTransactionTracing(t *testing.T) { hooks := recording.hooks() cx := chainContext{ChainHeaderReader: chain, parlia: engine} - applyErr := engine.applyTransaction(msg, state.NewHookedState(stateDB, hooks), bs[0].Header(), cx, &txs, &receipts, &receivedTxs, &usedGas, false, hooks) + applyErr := engine.applyTransaction(msg, state.NewHookedState(stateDB, hooks), bs[0].Header(), cx, &txs, &receipts, &receivedTxs, &usedGas, systemTxImporting, hooks) if applyErr != nil { t.Fatalf("failed to apply system contract transaction: %v", applyErr) } @@ -723,6 +727,430 @@ func TestParlia_applyTransactionTracing(t *testing.T) { } } +func TestParlia_applyTransactionModes(t *testing.T) { + frdir := t.TempDir() + db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false) + if err != nil { + t.Fatalf("failed to create database with ancient backend: %v", err) + } + + trieDB := triedb.NewDatabase(db, nil) + defer trieDB.Close() + + config := params.ParliaTestChainConfig + gspec := &core.Genesis{ + Config: config, + Alloc: types.GenesisAlloc{testAddr: {Balance: new(big.Int).SetUint64(10 * params.Ether)}}, + } + mockEngine := &mockParlia{} + genesisBlock := gspec.MustCommit(db, trieDB) + chain, _ := core.NewBlockChain(db, gspec, mockEngine, nil) + defer chain.Stop() + parents, _ := core.GenerateChain(config, genesisBlock, mockEngine, db, 1, nil) + header := parents[0].Header() + + engine := New(config, db, nil, genesisBlock.Hash()) + validatorKey, err := crypto.GenerateKey() + if err != nil { + t.Fatalf("failed to generate validator key: %v", err) + } + validator := crypto.PubkeyToAddress(validatorKey.PublicKey) + engine.Authorize(validator, nil, func(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + if account.Address != validator { + return nil, fmt.Errorf("unexpected signing account %s", account.Address) + } + return types.SignTx(tx, types.LatestSigner(config), validatorKey) + }) + + data, err := engine.validatorSetABI.Pack("distributeFinalityReward", make([]common.Address, 0), make([]*big.Int, 0)) + if err != nil { + t.Fatalf("failed to pack system contract method: %v", err) + } + msg := engine.getSystemMessage(validator, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0) + cx := chainContext{ChainHeaderReader: chain, parlia: engine} + + newState := func(t *testing.T) *state.StateDB { + t.Helper() + stateDB, err := state.New(genesisBlock.Root(), state.NewDatabase(trieDB, nil)) + if err != nil { + t.Fatalf("failed to create stateDB: %v", err) + } + return stateDB + } + expectedTx := func(stateDB *state.StateDB) *types.Transaction { + nonce := stateDB.GetNonce(msg.From) + return types.NewTransaction(nonce, *msg.To, msg.Value, msg.GasLimit, msg.GasPrice, msg.Data) + } + apply := func(t *testing.T, stateDB *state.StateDB, receivedTxs *[]*types.Transaction, mode systemTxMode) ([]*types.Transaction, error) { + t.Helper() + txs := make([]*types.Transaction, 0, 1) + receipts := make([]*types.Receipt, 0, 1) + usedGas := uint64(0) + err := engine.applyTransaction(msg, stateDB, header, cx, &txs, &receipts, receivedTxs, &usedGas, mode, nil) + return txs, err + } + + t.Run("mining signs system tx from validator", func(t *testing.T) { + txs, err := apply(t, newState(t), nil, systemTxMining) + if err != nil { + t.Fatalf("applyTransaction mining failed: %v", err) + } + if len(txs) != 1 { + t.Fatalf("expected one tx, got %d", len(txs)) + } + if isUnsignedTx(txs[0]) { + t.Fatalf("mining mode must sign system tx") + } + }) + + t.Run("mining rejects non-validator sender", func(t *testing.T) { + original := msg.From + msg.From = common.HexToAddress("0x3000000000000000000000000000000000000003") + defer func() { msg.From = original }() + + _, err := apply(t, newState(t), nil, systemTxMining) + if err == nil || !strings.Contains(err.Error(), "cannot sign system tx") { + t.Fatalf("expected cannot sign error, got %v", err) + } + }) + + t.Run("packing keeps system tx unsigned", func(t *testing.T) { + txs, err := apply(t, newState(t), nil, systemTxPacking) + if err != nil { + t.Fatalf("applyTransaction packing failed: %v", err) + } + if len(txs) != 1 { + t.Fatalf("expected one tx, got %d", len(txs)) + } + if !isUnsignedTx(txs[0]) { + t.Fatalf("packing mode must keep system tx unsigned") + } + }) + + t.Run("importing consumes matching received tx", func(t *testing.T) { + stateDB := newState(t) + receivedTxs := []*types.Transaction{expectedTx(stateDB)} + txs, err := apply(t, stateDB, &receivedTxs, systemTxImporting) + if err != nil { + t.Fatalf("applyTransaction importing failed: %v", err) + } + if len(receivedTxs) != 0 { + t.Fatalf("expected received tx to be consumed, got %d left", len(receivedTxs)) + } + if len(txs) != 1 || txs[0] == nil { + t.Fatalf("expected imported tx to be appended") + } + }) + + t.Run("importing rejects missing received tx", func(t *testing.T) { + receivedTxs := []*types.Transaction{} + _, err := apply(t, newState(t), &receivedTxs, systemTxImporting) + if err == nil || !strings.Contains(err.Error(), "supposed to get a actual transaction") { + t.Fatalf("expected missing received tx error, got %v", err) + } + }) + + t.Run("importing rejects mismatched received tx", func(t *testing.T) { + stateDB := newState(t) + expected := expectedTx(stateDB) + wrongTx := types.NewTransaction(expected.Nonce()+1, *expected.To(), expected.Value(), expected.Gas(), expected.GasPrice(), expected.Data()) + receivedTxs := []*types.Transaction{wrongTx} + _, err := apply(t, stateDB, &receivedTxs, systemTxImporting) + if err == nil || !strings.Contains(err.Error(), "expected tx hash") { + t.Fatalf("expected tx hash mismatch error, got %v", err) + } + }) +} + +func isUnsignedTx(tx *types.Transaction) bool { + v, r, s := tx.RawSignatureValues() + return v.Sign() == 0 && r.Sign() == 0 && s.Sign() == 0 +} + +// TestParliaFinalizeAndAssembleBidBlock verifies BidBlock assembly emits unsigned system txs. +func TestParliaFinalizeAndAssembleBidBlock(t *testing.T) { + frdir := t.TempDir() + db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false) + if err != nil { + t.Fatalf("failed to create database with ancient backend: %v", err) + } + + trieDB := triedb.NewDatabase(db, nil) + defer trieDB.Close() + + config := params.ParliaTestChainConfig + gspec := &core.Genesis{ + Config: config, + Alloc: types.GenesisAlloc{testAddr: {Balance: new(big.Int).SetUint64(10 * params.Ether)}}, + } + mockEngine := &mockParlia{} + genesisBlock := gspec.MustCommit(db, trieDB) + chain, _ := core.NewBlockChain(db, gspec, mockEngine, nil) + defer chain.Stop() + parents, _ := core.GenerateChain(config, genesisBlock, mockEngine, db, 1, nil) + parent := parents[0] + rawdb.WriteBlock(db, parent) + + engine := New(config, db, nil, genesisBlock.Hash()) + validatorKey, err := crypto.GenerateKey() + if err != nil { + t.Fatalf("failed to generate key: %v", err) + } + validator := crypto.PubkeyToAddress(validatorKey.PublicKey) + engine.Authorize(validator, nil, func(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) { + if account.Address != validator { + return nil, fmt.Errorf("unexpected signing account %s", account.Address) + } + return types.SignTx(tx, types.LatestSigner(config), validatorKey) + }) + + gasFee := uint256.NewInt(12345) + newHeader := func() *types.Header { + return &types.Header{ + ParentHash: parent.Hash(), + Number: new(big.Int).Add(parent.Number(), common.Big1), + Coinbase: validator, + Difficulty: new(big.Int).Set(diffInTurn), + GasLimit: params.SystemTxsGasHardLimit, + Time: parent.Time() + 1, + } + } + newState := func() *state.StateDB { + stateDB, err := state.New(parent.Root(), state.NewDatabase(trieDB, nil)) + if err != nil { + t.Fatalf("failed to create stateDB: %v", err) + } + stateDB.SetBalance(consensus.SystemAddress, new(uint256.Int).Set(gasFee), tracing.BalanceChangeUnspecified) + return stateDB + } + + signedBlock, signedReceipts, err := engine.FinalizeAndAssemble(chain, newHeader(), newState(), &types.Body{}, nil, nil) + if err != nil { + t.Fatalf("failed to finalize signed block: %v", err) + } + unsignedBlock, unsignedReceipts, err := engine.FinalizeAndAssembleBidBlock(chain, newHeader(), newState(), &types.Body{}, nil, nil) + if err != nil { + t.Fatalf("failed to finalize BidBlock: %v", err) + } + + if signedBlock.Root() != unsignedBlock.Root() { + t.Fatalf("state root mismatch: signed=%s unsigned=%s", signedBlock.Root(), unsignedBlock.Root()) + } + if signedBlock.ReceiptHash() != unsignedBlock.ReceiptHash() { + t.Fatalf("receipt hash mismatch: signed=%s unsigned=%s", signedBlock.ReceiptHash(), unsignedBlock.ReceiptHash()) + } + if signedBlock.Bloom() != unsignedBlock.Bloom() { + t.Fatalf("receipt bloom mismatch") + } + if signedBlock.GasUsed() != unsignedBlock.GasUsed() { + t.Fatalf("gas used mismatch: signed=%d unsigned=%d", signedBlock.GasUsed(), unsignedBlock.GasUsed()) + } + if len(signedBlock.Transactions()) == 0 || len(unsignedBlock.Transactions()) == 0 { + t.Fatalf("expected system transactions in both finalized blocks") + } + if isUnsignedTx(signedBlock.Transactions()[0]) { + t.Fatalf("expected default finalize path to sign system txs") + } + if !isUnsignedTx(unsignedBlock.Transactions()[0]) { + t.Fatalf("expected BidBlock assembly to keep system txs unsigned") + } + if len(signedReceipts) != len(unsignedReceipts) { + t.Fatalf("receipt count mismatch: signed=%d unsigned=%d", len(signedReceipts), len(unsignedReceipts)) + } +} + +func TestParliaFinalizeAndAssembleBidBlockRewardsHeaderCoinbase(t *testing.T) { + frdir := t.TempDir() + db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false) + if err != nil { + t.Fatalf("failed to create database with ancient backend: %v", err) + } + + trieDB := triedb.NewDatabase(db, nil) + defer trieDB.Close() + + config := params.ParliaTestChainConfig + gspec := &core.Genesis{ + Config: config, + Alloc: types.GenesisAlloc{testAddr: {Balance: new(big.Int).SetUint64(10 * params.Ether)}}, + } + mockEngine := &mockParlia{} + genesisBlock := gspec.MustCommit(db, trieDB) + chain, _ := core.NewBlockChain(db, gspec, mockEngine, nil) + defer chain.Stop() + parents, _ := core.GenerateChain(config, genesisBlock, mockEngine, db, 1, nil) + parent := parents[0] + rawdb.WriteBlock(db, parent) + + engine := New(config, db, nil, genesisBlock.Hash()) + localValidator := common.HexToAddress("0x1000000000000000000000000000000000000001") + blockCoinbase := common.HexToAddress("0x2000000000000000000000000000000000000002") + engine.Authorize(localValidator, nil, nil) + + header := &types.Header{ + ParentHash: parent.Hash(), + Number: new(big.Int).Add(parent.Number(), common.Big1), + Coinbase: blockCoinbase, + Difficulty: new(big.Int).Set(diffInTurn), + GasLimit: params.SystemTxsGasHardLimit, + Time: parent.Time() + 1, + } + stateDB, err := state.New(parent.Root(), state.NewDatabase(trieDB, nil)) + if err != nil { + t.Fatalf("failed to create stateDB: %v", err) + } + stateDB.SetBalance(consensus.SystemAddress, uint256.NewInt(12345), tracing.BalanceChangeUnspecified) + + block, _, err := engine.FinalizeAndAssembleBidBlock(chain, header, stateDB, &types.Body{}, nil, nil) + if err != nil { + t.Fatalf("failed to finalize BidBlock: %v", err) + } + + wantDeposit, err := engine.validatorSetABI.Pack("deposit", blockCoinbase) + if err != nil { + t.Fatalf("failed to pack expected deposit: %v", err) + } + wrongDeposit, err := engine.validatorSetABI.Pack("deposit", localValidator) + if err != nil { + t.Fatalf("failed to pack wrong deposit: %v", err) + } + var found bool + for _, tx := range block.Transactions() { + if tx.To() == nil || *tx.To() != common.HexToAddress(systemcontracts.ValidatorContract) { + continue + } + if bytes.Equal(tx.Data(), wrongDeposit) { + t.Fatalf("deposit reward routed to local p.val %s, want header coinbase %s", localValidator, blockCoinbase) + } + if bytes.Equal(tx.Data(), wantDeposit) { + found = true + } + } + if !found { + t.Fatalf("missing deposit reward for header coinbase %s", blockCoinbase) + } +} + +func TestParliaPrepareForBidBlock(t *testing.T) { + frdir := t.TempDir() + db, err := rawdb.NewDatabaseWithFreezer(rawdb.NewMemoryDatabase(), frdir, "", false) + if err != nil { + t.Fatalf("failed to create database with ancient backend: %v", err) + } + + trieDB := triedb.NewDatabase(db, nil) + defer trieDB.Close() + + config := params.ParliaTestChainConfig + otherValidator := common.HexToAddress("0x2000000000000000000000000000000000000000") + extra := make([]byte, extraVanity+validatorNumberSize+2*validatorBytesLength+extraSeal) + extra[extraVanity] = 2 + copy(extra[extraVanity+validatorNumberSize:], testAddr[:]) + copy(extra[extraVanity+validatorNumberSize+validatorBytesLength:], otherValidator[:]) + gspec := &core.Genesis{ + Config: config, + ExtraData: extra, + Timestamp: uint64(time.Now().Add(-10 * time.Second).Unix()), + Alloc: types.GenesisAlloc{testAddr: {Balance: new(big.Int).SetUint64(10 * params.Ether)}}, + } + mockEngine := &mockParlia{} + genesisBlock := gspec.MustCommit(db, trieDB) + chain, _ := core.NewBlockChain(db, gspec, mockEngine, nil) + defer chain.Stop() + + validatorEngine := New(config, db, nil, genesisBlock.Hash()) + inturnValidator, err := validatorEngine.NextInTurnValidator(chain, genesisBlock.Header()) + if err != nil { + t.Fatalf("failed to get in-turn validator: %v", err) + } + validatorEngine.Authorize(inturnValidator, nil, nil) + builderEngine := New(config, db, nil, genesisBlock.Hash()) + if inturnValidator == testAddr { + builderEngine.Authorize(otherValidator, nil, nil) + } else { + builderEngine.Authorize(testAddr, nil, nil) + } + + newHeader := func() *types.Header { + return &types.Header{ + ParentHash: genesisBlock.Hash(), + Number: common.Big1, + GasLimit: params.SystemTxsGasHardLimit, + } + } + validatorHeader := newHeader() + builderHeader := newHeader() + + if err := validatorEngine.Prepare(chain, validatorHeader); err != nil { + t.Fatalf("failed to prepare validator header: %v", err) + } + if err := builderEngine.PrepareForBidBlock(chain, builderHeader); err != nil { + t.Fatalf("failed to prepare BidBlock header: %v", err) + } + + if builderHeader.Coinbase != validatorHeader.Coinbase { + t.Fatalf("coinbase mismatch: builder=%s validator=%s", builderHeader.Coinbase, validatorHeader.Coinbase) + } + if builderHeader.Coinbase != inturnValidator { + t.Fatalf("builder coinbase mismatch: have %s want %s", builderHeader.Coinbase, inturnValidator) + } + // Prepare and PrepareForBidBlock share the prepare() core, so headers + // prepared back-to-back land on the same blockTimeForRamanujanFork output. + // Allow one 50ms quantum of tolerance for the rare case where the two + // calls straddle a wall-clock alignment tick. + diff := int64(builderHeader.MilliTimestamp()) - int64(validatorHeader.MilliTimestamp()) + if diff < 0 { + diff = -diff + } + if diff > 50 { + t.Fatalf("builder/validator time diverge by %dms: builder=%d validator=%d", + diff, builderHeader.MilliTimestamp(), validatorHeader.MilliTimestamp()) + } + if builderHeader.Difficulty.Cmp(validatorHeader.Difficulty) != 0 { + t.Fatalf("difficulty mismatch: builder=%s validator=%s", builderHeader.Difficulty, validatorHeader.Difficulty) + } + // BidBlock prepare must produce a byte-identical Extra to the normal validator + // prepare (length-equal is too weak: a wrong forkhash/vanity byte would slip through). + if !bytes.Equal(builderHeader.Extra, validatorHeader.Extra) { + t.Fatalf("extra mismatch:\n builder =%x\n validator =%x", builderHeader.Extra, validatorHeader.Extra) + } + + // SetExtraData branch checks on a non-epoch header (no validator-set contract call): + // forkhash bytes, zeroed seal space, and vanity truncation/padding. The epoch + // validators / turnLength branches require a populated validator contract and are + // covered by e2e. + const vanityLen = extraVanity - nextForkHashSize // 28 + genesisTime := chain.GenesisHeader().Time + wantForkHash := forkid.NextForkHash(config, genesisBlock.Hash(), genesisTime, validatorHeader.Number.Uint64(), validatorHeader.Time) + if got := validatorHeader.Extra[vanityLen:extraVanity]; !bytes.Equal(got, wantForkHash[:]) { + t.Fatalf("forkhash mismatch: got %x want %x", got, wantForkHash[:]) + } + if seal := validatorHeader.Extra[len(validatorHeader.Extra)-extraSeal:]; !bytes.Equal(seal, make([]byte, extraSeal)) { + t.Fatalf("seal space not zeroed: %x", seal) + } + + setExtra := func(vanity []byte) []byte { + h := newHeader() + h.Time = validatorHeader.Time + h.Extra = append([]byte(nil), vanity...) + if err := validatorEngine.SetExtraData(chain, h); err != nil { + t.Fatalf("SetExtraData: %v", err) + } + return h.Extra + } + // over-long vanity is truncated to vanityLen bytes. + long := bytes.Repeat([]byte{0xAB}, extraVanity*2) + if got := setExtra(long)[:vanityLen]; !bytes.Equal(got, long[:vanityLen]) { + t.Fatalf("vanity not truncated: got %x", got) + } + // short vanity is zero-padded to vanityLen bytes. + short := []byte{0x01, 0x02} + ext := setExtra(short) + if !bytes.Equal(ext[:len(short)], short) || !bytes.Equal(ext[len(short):vanityLen], make([]byte, vanityLen-len(short))) { + t.Fatalf("vanity not zero-padded: got %x", ext[:vanityLen]) + } +} + func formatRecords(records []string) string { indented := make([]string, 0, len(records)) for _, record := range records { diff --git a/consensus/parlia/ramanujanfork.go b/consensus/parlia/ramanujanfork.go index 53473e0350..43142962d6 100644 --- a/consensus/parlia/ramanujanfork.go +++ b/consensus/parlia/ramanujanfork.go @@ -31,7 +31,7 @@ func (p *Parlia) delayForRamanujanFork(snap *Snapshot, header *types.Header) tim func (p *Parlia) blockTimeForRamanujanFork(snap *Snapshot, header, parent *types.Header) uint64 { blockTime := parent.MilliTimestamp() + snap.BlockInterval if p.chainConfig.IsRamanujan(header.Number) { - blockTime = blockTime + p.backOffTime(snap, parent, header, p.val) + blockTime = blockTime + p.backOffTime(snap, parent, header, header.Coinbase) } if now := uint64(time.Now().UnixMilli()); blockTime < now { // Just to make the millisecond part of the time look more aligned. diff --git a/core/types/bid.go b/core/types/bid.go index 4f7d52f7d5..318f7bbb77 100644 --- a/core/types/bid.go +++ b/core/types/bid.go @@ -202,6 +202,102 @@ type BidIssue struct { Message string } +// BidBlockArgs is the input for the SendBidBlock RPC. +type BidBlockArgs struct { + BidBlock *BidBlock + Signature hexutil.Bytes `json:"signature"` +} + +// EcrecoverSender recovers the builder address from the signature over BidBlock.Hash(). +func (b *BidBlockArgs) EcrecoverSender() (common.Address, error) { + pk, err := crypto.SigToPub(b.BidBlock.Hash().Bytes(), b.Signature) + if err != nil { + return common.Address{}, err + } + return crypto.PubkeyToAddress(*pk), nil +} + +// ToDecodedBidBlock converts BidBlockArgs to a decoded internal representation. +// Note: transaction sender recovery is deferred to InsertChain. +func (b *BidBlockArgs) ToDecodedBidBlock(builder common.Address) (*DecodedBidBlock, error) { + txs, err := b.DecodeTxs() + if err != nil { + return nil, err + } + + sidecars := b.BidBlock.Sidecars + if sidecars == nil { + sidecars = BlobSidecars{} + } + + return &DecodedBidBlock{ + Builder: builder, + Header: CopyHeader(b.BidBlock.Header), + Txs: txs, + Sidecars: sidecars, + bidHash: b.BidBlock.Hash(), + }, nil +} + +// DecodeTxs decodes user txs followed by unsigned system txs. +func (b *BidBlockArgs) DecodeTxs() ([]*Transaction, error) { + txs := make([]*Transaction, len(b.BidBlock.Transactions)) + for i, txBytes := range b.BidBlock.Transactions { + tx := new(Transaction) + if err := tx.UnmarshalBinary(txBytes); err != nil { + return nil, fmt.Errorf("failed to decode tx %d: %v", i, err) + } + txs[i] = tx + } + return txs, nil +} + +// BidBlock is the builder-proposed block carried by BidBlockArgs. +type BidBlock struct { + Header *Header `json:"header"` + Transactions []hexutil.Bytes `json:"transactions"` // user txs first, unsigned system txs last + Sidecars BlobSidecars `json:"sidecars,omitempty"` + + hash atomic.Value +} + +// Hash returns rlpHash over all BidBlock fields. This is what the builder signs. +func (b *BidBlock) Hash() common.Hash { + if hash := b.hash.Load(); hash != nil { + return hash.(common.Hash) + } + h := rlpHash(b) + b.hash.Store(h) + return h +} + +// DecodedBidBlock is the validator-side decoded representation of a BidBlock. +type DecodedBidBlock struct { + Builder common.Address // recovered from BidBlockArgs.Signature + Header *Header + Txs Transactions + Sidecars BlobSidecars + GasFee *big.Int + SystemTxStart int // index in Txs where the unsigned trailing system-tx region begins; set during admission. + + bidHash common.Hash +} + +// Hash returns the hash of the original BidBlock payload. +func (d *DecodedBidBlock) Hash() common.Hash { + return d.bidHash +} + +// BlockNumber returns the block number from the header. +func (d *DecodedBidBlock) BlockNumber() uint64 { + return d.Header.Number.Uint64() +} + +// ParentHash returns the parent hash from the header. +func (d *DecodedBidBlock) ParentHash() common.Hash { + return d.Header.ParentHash +} + type MevParams struct { ValidatorCommission uint64 // 100 means 1% BidSimulationLeftOver time.Duration @@ -210,5 +306,6 @@ type MevParams struct { GasCeil uint64 GasPrice *big.Int // Minimum avg gas price for bid block BuilderFeeCeil *big.Int + BidBlockEnabled bool // whether mev_sendBidBlock is accepted Version string } diff --git a/core/types/bid_block_permission.go b/core/types/bid_block_permission.go new file mode 100644 index 0000000000..8215da9449 --- /dev/null +++ b/core/types/bid_block_permission.go @@ -0,0 +1,16 @@ +package types + +import ( + "time" + + "github.com/ethereum/go-ethereum/common" +) + +type BidBlockPermissionStatus struct { + Allowed bool + Reason string // err detail for auto revokes (InsertChain failure), or "manual" for admin revokes + BlockHash common.Hash + BlockNum uint64 + RevokedAt time.Time + ResetAt time.Time +} diff --git a/core/types/bid_error.go b/core/types/bid_error.go index 6b543ae64f..32079d869d 100644 --- a/core/types/bid_error.go +++ b/core/types/bid_error.go @@ -3,11 +3,14 @@ package types import "errors" const ( - InvalidBidParamError = -38001 - InvalidPayBidTxError = -38002 - MevNotRunningError = -38003 - MevBusyError = -38004 - MevNotInTurnError = -38005 + InvalidBidParamError = -38001 + InvalidPayBidTxError = -38002 + MevNotRunningError = -38003 + MevBusyError = -38004 + MevNotInTurnError = -38005 + BidBlockPermissionRevokedError = -38006 + BidBlockPreSealVerifyError = -38007 + BidBlockTooLateError = -38008 ) var ( @@ -37,6 +40,18 @@ func NewInvalidPayBidTxError(message string) *bidError { return newBidError(errors.New(message), InvalidPayBidTxError) } +func NewBidBlockPermissionRevokedError(message string) *bidError { + return newBidError(errors.New(message), BidBlockPermissionRevokedError) +} + +func NewBidBlockPreSealVerifyError(message string) *bidError { + return newBidError(errors.New(message), BidBlockPreSealVerifyError) +} + +func NewBidBlockTooLateError(message string) *bidError { + return newBidError(errors.New(message), BidBlockTooLateError) +} + func newBidError(err error, code int) *bidError { return &bidError{ error: err, diff --git a/core/types/bid_test.go b/core/types/bid_test.go new file mode 100644 index 0000000000..93d9b7c8aa --- /dev/null +++ b/core/types/bid_test.go @@ -0,0 +1,64 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. + +package types + +import ( + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +func TestBidBlockArgsToDecodedBidBlockNormalizesNilSidecars(t *testing.T) { + args := &BidBlockArgs{ + BidBlock: &BidBlock{ + Header: &Header{ + Difficulty: big.NewInt(1), + Number: big.NewInt(1), + Extra: make([]byte, 32), + }, + }, + } + + decoded, err := args.ToDecodedBidBlock(common.Address{0x1}) + if err != nil { + t.Fatalf("ToDecodedBidBlock failed: %v", err) + } + if decoded.Sidecars == nil { + t.Fatal("nil sidecars should be normalized to an empty slice") + } + if len(decoded.Sidecars) != 0 { + t.Fatalf("sidecars length mismatch: got %d, want 0", len(decoded.Sidecars)) + } +} + +func TestBidBlockArgsToDecodedBidBlockCopiesHeader(t *testing.T) { + args := &BidBlockArgs{ + BidBlock: &BidBlock{ + Header: &Header{ + Difficulty: big.NewInt(1), + Number: big.NewInt(1), + Extra: []byte{1, 2, 3}, + }, + }, + } + + decoded, err := args.ToDecodedBidBlock(common.Address{0x1}) + if err != nil { + t.Fatalf("ToDecodedBidBlock failed: %v", err) + } + if decoded.Header == args.BidBlock.Header { + t.Fatal("decoded BidBlock header must not share the original header pointer") + } + + decoded.Header.Number.SetUint64(2) + decoded.Header.Extra[0] = 9 + + if args.BidBlock.Header.Number.Uint64() != 1 { + t.Fatalf("original header number mutated: got %d, want 1", args.BidBlock.Header.Number.Uint64()) + } + if args.BidBlock.Header.Extra[0] != 1 { + t.Fatalf("original header extra mutated: got %d, want 1", args.BidBlock.Header.Extra[0]) + } +} diff --git a/core/types/block_mev_info.go b/core/types/block_mev_info.go new file mode 100644 index 0000000000..ca1dd98b7d --- /dev/null +++ b/core/types/block_mev_info.go @@ -0,0 +1,59 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// BEP-675 block-source tagging. Validators encode the winning MEV path and +// builder address into header.RequestsHash; local blocks keep EmptyRequestsHash. + +package types + +import ( + "github.com/ethereum/go-ethereum/common" +) + +const blockMevInfoVersionOffset = common.HashLength - common.AddressLength - 1 // 11 + +// BlockMevInfoVersion identifies which submission path produced a block. +// Stored in header.RequestsHash at blockMevInfoVersionOffset. +type BlockMevInfoVersion uint8 + +const ( + // BlockMevInfoVersionBid identifies blocks produced via legacy SendBid. + BlockMevInfoVersionBid BlockMevInfoVersion = 1 + // BlockMevInfoVersionBidBlock identifies blocks produced via BEP-675 SendBidBlock. + BlockMevInfoVersionBidBlock BlockMevInfoVersion = 2 +) + +// EncodeBlockMevInfo packs (version, builder) into a 32-byte hash suitable for +// header.RequestsHash. Layout: +// +// [0:blockMevInfoVersionOffset] = 0 (leading-zero sentinel) +// [blockMevInfoVersionOffset] = version (1 = bid, 2 = bidblock) +// [blockMevInfoVersionOffset+1:] = builder (20-byte address) +// +// Local blocks must NOT use this encoding; they keep the default +// EmptyRequestsHash so callers can rely on "untagged" == local. +func EncodeBlockMevInfo(version BlockMevInfoVersion, builder common.Address) common.Hash { + var h common.Hash + h[blockMevInfoVersionOffset] = byte(version) + copy(h[blockMevInfoVersionOffset+1:], builder[:]) + return h +} + +// DecodeBlockMevInfo recovers the MEV source and builder from h. +// ok=false means callers should treat the block as local. +func DecodeBlockMevInfo(h common.Hash) (version BlockMevInfoVersion, builder common.Address, ok bool) { + for i := 0; i < blockMevInfoVersionOffset; i++ { + if h[i] != 0 { + return 0, common.Address{}, false + } + } + v := BlockMevInfoVersion(h[blockMevInfoVersionOffset]) + if v != BlockMevInfoVersionBid && v != BlockMevInfoVersionBidBlock { + return 0, common.Address{}, false + } + copy(builder[:], h[blockMevInfoVersionOffset+1:]) + if builder == (common.Address{}) { + return 0, common.Address{}, false + } + return v, builder, true +} diff --git a/core/types/block_mev_info_test.go b/core/types/block_mev_info_test.go new file mode 100644 index 0000000000..6b97d7d5a9 --- /dev/null +++ b/core/types/block_mev_info_test.go @@ -0,0 +1,50 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. + +package types + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +func TestBlockMevInfoEncodeDecode(t *testing.T) { + builder := common.HexToAddress("0x317aB60A0815F8Db2e6cb3f302C152d2A5ef4854") + + // Round-trip: both versions encode then decode back to the same (version, builder). + t.Run("round-trip", func(t *testing.T) { + for _, v := range []BlockMevInfoVersion{BlockMevInfoVersionBid, BlockMevInfoVersionBidBlock} { + gotV, gotB, ok := DecodeBlockMevInfo(EncodeBlockMevInfo(v, builder)) + if !ok || gotV != v || gotB != builder { + t.Fatalf("version %d: got (v=%d, builder=%s, ok=%v), want (%d, %s, true)", + v, gotV, gotB.Hex(), ok, v, builder.Hex()) + } + } + }) + + // Invalid encodings must decode to ok=false (caller treats as a local/untagged block). + t.Run("invalid->ok=false", func(t *testing.T) { + nonzeroSentinel := EncodeBlockMevInfo(BlockMevInfoVersionBidBlock, builder) + nonzeroSentinel[0] = 1 // leading sentinel bytes [0:11] must all be zero + + versionTooHigh := EncodeBlockMevInfo(BlockMevInfoVersionBidBlock, builder) + versionTooHigh[blockMevInfoVersionOffset] = 3 // not 1 or 2 + + versionZero := EncodeBlockMevInfo(BlockMevInfoVersionBidBlock, builder) + versionZero[blockMevInfoVersionOffset] = 0 + + cases := map[string]common.Hash{ + "nonzero sentinel": nonzeroSentinel, + "version 3": versionTooHigh, + "version 0": versionZero, + "zero builder": EncodeBlockMevInfo(BlockMevInfoVersionBidBlock, common.Address{}), + "empty hash": {}, + } + for name, h := range cases { + if _, _, ok := DecodeBlockMevInfo(h); ok { + t.Errorf("%s: ok=true, want false", name) + } + } + }) +} diff --git a/eth/api_admin.go b/eth/api_admin.go index 4a3ccb84e8..0a8be2ed33 100644 --- a/eth/api_admin.go +++ b/eth/api_admin.go @@ -24,6 +24,7 @@ import ( "os" "strings" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/rlp" @@ -141,3 +142,7 @@ func (api *AdminAPI) ImportChain(file string) (bool, error) { } return true, nil } + +func (api *AdminAPI) SetBidBlockPermission(builder common.Address, allowed bool) { + api.eth.Miner().SetBidBlockPermission(builder, allowed) +} diff --git a/eth/api_backend.go b/eth/api_backend.go index 281eb989d5..41d67d0d2e 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -566,10 +566,18 @@ func (b *EthAPIBackend) HasBuilder(builder common.Address) bool { return b.Miner().HasBuilder(builder) } +func (b *EthAPIBackend) GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus { + return b.Miner().GetBidBlockPermission(builder) +} + func (b *EthAPIBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) { return b.Miner().SendBid(ctx, bid) } +func (b *EthAPIBackend) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) { + return b.Miner().SendBidBlock(ctx, args) +} + func (b *EthAPIBackend) MinerInTurn() bool { return b.Miner().InTurn() } diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 06536ee451..8d77701275 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -870,6 +870,36 @@ func (ec *Client) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, return hash, nil } +// SendBidBlock sends a BidBlock (zero-simulate MEV path). +func (ec *Client) SendBidBlock(ctx context.Context, args types.BidBlockArgs) (common.Hash, error) { + var hash common.Hash + err := ec.c.CallContext(ctx, &hash, "mev_sendBidBlock", args) + if err != nil { + return common.Hash{}, err + } + return hash, nil +} + +// BidBlockPermission is the result of mev_getBidBlockPermission. +type BidBlockPermission struct { + Allowed bool `json:"allowed"` + Reason string `json:"reason,omitempty"` + BlockHash *common.Hash `json:"blockHash,omitempty"` + BlockNumber *hexutil.Uint64 `json:"blockNumber,omitempty"` + RevokedAt *time.Time `json:"revokedAt,omitempty"` + ResetAt time.Time `json:"resetAt"` +} + +// GetBidBlockPermission queries the builder's current BidBlock permission status. +func (ec *Client) GetBidBlockPermission(ctx context.Context, builder common.Address) (*BidBlockPermission, error) { + var result BidBlockPermission + err := ec.c.CallContext(ctx, &result, "mev_getBidBlockPermission", builder) + if err != nil { + return nil, err + } + return &result, nil +} + // BestBidGasFee returns the gas fee of the best bid for the given parent hash. func (ec *Client) BestBidGasFee(ctx context.Context, parentHash common.Hash) (*big.Int, error) { var fee *big.Int diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index c1e9f2c5b3..8a040b31b5 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -539,6 +539,49 @@ func (api *BlockChainAPI) GetBlockByHash(ctx context.Context, hash common.Hash, return nil, err } +// BlockMevInfo describes a block's MEV builder attribution. +// Version "v1" means legacy SendBid; version "v2" means BEP-675 SendBidBlock. +// Local-mined blocks omit Builder and Version. +type BlockMevInfo struct { + BlockNumber hexutil.Uint64 `json:"blockNumber"` + BlockHash common.Hash `json:"blockHash"` + Miner common.Address `json:"miner"` + Version string `json:"version,omitempty"` + Builder *common.Address `json:"builder,omitempty"` +} + +// GetBlockMevInfo returns the MEV builder attribution for the given block. +func (api *BlockChainAPI) GetBlockMevInfo(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*BlockMevInfo, error) { + header, err := api.b.HeaderByNumberOrHash(ctx, blockNrOrHash) + if err != nil { + return nil, err + } + if header == nil { + return nil, errors.New("block not found") + } + info := &BlockMevInfo{ + BlockNumber: hexutil.Uint64(header.Number.Uint64()), + BlockHash: header.Hash(), + Miner: header.Coinbase, + } + if header.RequestsHash == nil { + return info, nil + } + version, builder, ok := types.DecodeBlockMevInfo(*header.RequestsHash) + if !ok { + return info, nil + } + switch version { + case types.BlockMevInfoVersionBid: + info.Version = "v1" + case types.BlockMevInfoVersionBidBlock: + info.Version = "v2" + } + b := builder + info.Builder = &b + return info, nil +} + func (api *BlockChainAPI) Health() bool { if rpc.RpcServingTimer != nil { return rpc.RpcServingTimer.Snapshot().Percentile(0.75) < float64(UnHealthyTimeout) diff --git a/internal/ethapi/api_mev.go b/internal/ethapi/api_mev.go index c002571c4b..e76580691b 100644 --- a/internal/ethapi/api_mev.go +++ b/internal/ethapi/api_mev.go @@ -6,6 +6,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/params" ) @@ -87,6 +88,53 @@ func (m *MevAPI) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, return m.b.SendBid(ctx, &args) } +// SendBidBlock receives a BidBlock from builders. +func (m *MevAPI) SendBidBlock(ctx context.Context, args types.BidBlockArgs) (common.Hash, error) { + ctx = context.WithValue(ctx, "receiveTime", time.Now().UnixMilli()) + if !m.b.MevRunning() { + return common.Hash{}, types.ErrMevNotRunning + } + + // Basic structural validation. + if args.BidBlock == nil { + return common.Hash{}, types.NewInvalidBidError("empty BidBlock") + } + bb := args.BidBlock + if bb.Header == nil { + return common.Hash{}, types.NewInvalidBidError("empty Header") + } + + blockNumber := bb.Header.Number.Uint64() + parentHash := bb.Header.ParentHash + currentBlock := m.b.CurrentBlock() + currentNumber := currentBlock.Number.Uint64() + + if blockNumber < currentNumber+1 { + return common.Hash{}, types.NewInvalidBidError( + fmt.Sprintf("stale block number: %d, latest block: %d", blockNumber, currentNumber)) + } else if blockNumber > currentNumber+1 { + return common.Hash{}, types.NewInvalidBidError( + fmt.Sprintf("block in future: %d, latest block: %d", blockNumber, currentNumber)) + } else if !m.b.MinerInTurn() { + return common.Hash{}, types.ErrMevNotInTurn + } + + if parentHash != currentBlock.Hash() { + return common.Hash{}, types.NewInvalidBidError( + fmt.Sprintf("non-aligned parent hash: %v", currentBlock.Hash())) + } + + if bb.Header.GasUsed == 0 { + return common.Hash{}, types.NewInvalidBidError("empty gasUsed in header") + } + + if len(bb.Transactions) == 0 { + return common.Hash{}, types.NewInvalidBidError("empty transactions") + } + + return m.b.SendBidBlock(ctx, &args) +} + func (m *MevAPI) Params() *types.MevParams { return m.b.MevParams() } @@ -95,6 +143,34 @@ func (m *MevAPI) HasBuilder(builder common.Address) bool { return m.b.HasBuilder(builder) } +type BidBlockPermissionResult struct { + Allowed bool `json:"allowed"` + Reason string `json:"reason,omitempty"` + BlockHash *common.Hash `json:"blockHash,omitempty"` + BlockNumber *hexutil.Uint64 `json:"blockNumber,omitempty"` + RevokedAt *time.Time `json:"revokedAt,omitempty"` + ResetAt *time.Time `json:"resetAt,omitempty"` +} + +func (m *MevAPI) GetBidBlockPermission(builder common.Address) *BidBlockPermissionResult { + status := m.b.GetBidBlockPermission(builder) + result := &BidBlockPermissionResult{ + Allowed: status.Allowed, + } + if !status.Allowed { + blockHash := status.BlockHash + blockNum := hexutil.Uint64(status.BlockNum) + revokedAt := status.RevokedAt + resetAt := status.ResetAt + result.Reason = status.Reason + result.BlockHash = &blockHash + result.BlockNumber = &blockNum + result.RevokedAt = &revokedAt + result.ResetAt = &resetAt + } + return result +} + // Running returns true if mev is running func (m *MevAPI) Running() bool { return m.b.MevRunning() diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 89dea5ee44..8c742b031c 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -98,6 +98,43 @@ func testTransactionMarshal(t *testing.T, tests []txData, config *params.ChainCo } } +func TestMevAPIGetBidBlockPermission(t *testing.T) { + builder := common.HexToAddress("0x1") + blockHash := common.HexToHash("0xabc") + revokedAt := time.Date(2026, 5, 9, 10, 0, 0, 0, time.UTC) + resetAt := time.Date(2026, 5, 10, 0, 0, 0, 0, time.UTC) + api := NewMevAPI(&testBackend{ + bidBlockPermission: types.BidBlockPermissionStatus{ + Allowed: false, + Reason: "gasfee_overclaim", + BlockHash: blockHash, + BlockNum: 100, + RevokedAt: revokedAt, + ResetAt: resetAt, + }, + }) + + result := api.GetBidBlockPermission(builder) + if result.Allowed { + t.Fatal("permission should be revoked") + } + if result.Reason != "gasfee_overclaim" { + t.Fatalf("reason: got %s", result.Reason) + } + if result.BlockHash == nil || *result.BlockHash != blockHash { + t.Fatalf("blockHash: got %v, want %s", result.BlockHash, blockHash) + } + if result.BlockNumber == nil || *result.BlockNumber != hexutil.Uint64(100) { + t.Fatalf("blockNumber: got %v, want 100", result.BlockNumber) + } + if result.RevokedAt == nil || !result.RevokedAt.Equal(revokedAt) { + t.Fatalf("revokedAt: got %v, want %s", result.RevokedAt, revokedAt) + } + if !result.ResetAt.Equal(resetAt) { + t.Fatalf("resetAt: got %s, want %s", result.ResetAt, resetAt) + } +} + func TestTransaction_RoundTripRpcJSON(t *testing.T) { t.Parallel() @@ -450,6 +487,8 @@ type testBackend struct { syncDefaultTimeout time.Duration syncMaxTimeout time.Duration + + bidBlockPermission types.BidBlockPermissionStatus } func fakeBlockHash(txh common.Hash) common.Hash { @@ -721,6 +760,9 @@ func (b testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscripti func (b *testBackend) MevRunning() bool { return false } func (b *testBackend) HasBuilder(builder common.Address) bool { return false } +func (b *testBackend) GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus { + return b.bidBlockPermission +} func (b *testBackend) MevParams() *types.MevParams { return &types.MevParams{} } @@ -731,6 +773,9 @@ func (b *testBackend) RemoveBuilder(builder common.Address) error func (b *testBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) { panic("implement me") } +func (b *testBackend) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) { + panic("implement me") +} func (b *testBackend) MinerInTurn() bool { return false } func (b testBackend) CurrentView() *filtermaps.ChainView { diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 5f9429faea..473ce9567e 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -121,8 +121,12 @@ type Backend interface { RemoveBuilder(builder common.Address) error // HasBuilder returns true if the builder is in the builder list. HasBuilder(builder common.Address) bool + // GetBidBlockPermission returns the builder's current SendBidBlock permission. + GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus // SendBid receives bid from the builders. SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) + // SendBidBlock receives a BidBlock from builders. + SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) // MinerInTurn returns true if the validator is in turn to propose the block. MinerInTurn() bool diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 39e7d328a8..004018a3e0 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -423,6 +423,9 @@ func (b *backendMock) CurrentValidators() ([]common.Address, error) { return []c func (b *backendMock) MevRunning() bool { return false } func (b *backendMock) HasBuilder(builder common.Address) bool { return false } +func (b *backendMock) GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus { + return types.BidBlockPermissionStatus{} +} func (b *backendMock) MevParams() *types.MevParams { return &types.MevParams{} } @@ -433,6 +436,9 @@ func (b *backendMock) RemoveBuilder(builder common.Address) error func (b *backendMock) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) { panic("implement me") } +func (b *backendMock) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) { + panic("implement me") +} func (b *backendMock) MinerInTurn() bool { return false } func (b *backendMock) CurrentView() *filtermaps.ChainView { return nil } func (b *backendMock) NewMatcherBackend() filtermaps.MatcherBackend { return nil } diff --git a/internal/web3ext/web3ext.go b/internal/web3ext/web3ext.go index fb9c4e25b7..cc37bcb1f6 100644 --- a/internal/web3ext/web3ext.go +++ b/internal/web3ext/web3ext.go @@ -144,6 +144,12 @@ web3._extend({ name: 'stopWS', call: 'admin_stopWS' }), + new web3._extend.Method({ + name: 'setBidBlockPermission', + call: 'admin_setBidBlockPermission', + params: 2, + inputFormatter: [web3._extend.formatters.inputAddressFormatter, null] + }), ], properties: [ new web3._extend.Property({ diff --git a/miner/bid_block.go b/miner/bid_block.go new file mode 100644 index 0000000000..5ea72dae83 --- /dev/null +++ b/miner/bid_block.go @@ -0,0 +1,319 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// BidBlock worker helpers for BEP-675. + +package miner + +import ( + "errors" + "fmt" + "math/big" + "sync" + "time" + + "github.com/holiman/uint256" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/parlia" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/core/txpool" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/trie" +) + +type bidBlockTaskInfo struct { + builder common.Address + bidHash common.Hash + gasFee *big.Int + systemTxStart int +} + +var errInvalidBidBlockBlobTx = errors.New("BidBlock blob validation failed") + +// setBidMevInfo tags header.RequestsHash with the BEP-675 block-source info +func setBidMevInfo(header *types.Header, builder common.Address, isBidBlock bool) { + // Legacy BID: a nil RequestsHash denotes a pre-Prague block that must stay + // untagged. BIDBLOCK is post-Prague and validator-owned, so always stamped. + if !isBidBlock && header.RequestsHash == nil { + return + } + version := types.BlockMevInfoVersionBid + if isBidBlock { + version = types.BlockMevInfoVersionBidBlock + } + tag := types.EncodeBlockMevInfo(version, builder) + header.RequestsHash = &tag +} + +func (w *worker) selectBidBlock(bidBlock *types.DecodedBidBlock, simBidBlockReward, simBidValidatorReward, bestReward *uint256.Int) bool { + if bidBlock == nil { + return false + } + + bidBlockFee := bidBlock.GasFee + bidBlockValidatorReward := new(big.Int).Mul(bidBlockFee, new(big.Int).SetUint64(*w.config.Mev.ValidatorCommission)) + bidBlockValidatorReward.Div(bidBlockValidatorReward, big.NewInt(10000)) + + if simBidValidatorReward != nil && bidBlockValidatorReward.Cmp(simBidValidatorReward.ToBig()) <= 0 { + return false + } + if simBidBlockReward != nil && bidBlockFee.Cmp(simBidBlockReward.ToBig()) <= 0 { + return false + } + + simBidBR := "" + if simBidBlockReward != nil { + simBidBR = simBidBlockReward.String() + } + simBidVR := "" + if simBidValidatorReward != nil { + simBidVR = simBidValidatorReward.String() + } + blockNum := bidBlock.Header.Number.Uint64() + // TODO: switch back to Debug after BidBlock rollout stabilizes. + log.Info("BidSimulator: BidBlock win bid, compare with local", + "block", blockNum, + "bidHash", bidBlock.Hash(), + "localBlockReward", bestReward.String(), + "bidReward", bidBlockFee.String(), + "bidValidatorReward", bidBlockValidatorReward.String(), + "simBidBlockReward", simBidBR, + "simBidValidatorReward", simBidVR) + + if bidBlockFee.Cmp(bestReward.ToBig()) > 0 { + log.Info("[BID BLOCK selected]", + "block", blockNum, + "bidHash", bidBlock.Hash(), + "builder", bidBlock.Builder, + "gasFee", weiToEtherStringF6(bidBlock.GasFee), + "txs", len(bidBlock.Txs)) + return true + } + return false +} + +// bindSignBidBlockSystemTxs signs the verified unsigned system txs from a BidBlock in place. +func bindSignBidBlockSystemTxs( + systemTxs []*types.Transaction, + chainID *big.Int, + p *parlia.Parlia, +) error { + for i, tx := range systemTxs { + signed, err := p.SignSystemTx(tx, chainID) + if err != nil { + return fmt.Errorf("failed to sign system tx %d: %v", i, err) + } + systemTxs[i] = signed + } + return nil +} + +// prepareBidBlockTask signs system txs and assembles a BidBlock task. +// Extra was finalized by the validator during admission (SendBidBlock calls +// SetExtraData before preSealVerifyBidBlock); engine.Seal will later fill the +// reserved vote-attestation/seal-signature bytes. Here we only recompute TxHash +// after bind-signing the trailing system txs. Do not touch fields that enter +// the EVM BlockContext (GasLimit, Coinbase, Time, Difficulty, BaseFee, ...) — +// changing them after the builder's pre-execution would diverge the re-executed +// stateRoot and fail InsertChain. +func (w *worker) prepareBidBlockTask( + decoded *types.DecodedBidBlock, + start time.Time, +) (*task, error) { + if !w.isRunning() { + return nil, errors.New("worker is not running") + } + + p := w.engine.(*parlia.Parlia) + + // Copy the tx slice so bind-signing does not mutate the cached BidBlock. + allTxs := make([]*types.Transaction, len(decoded.Txs)) + copy(allTxs, decoded.Txs) + + header := types.CopyHeader(decoded.Header) + if err := validateBidBlockBlobTxs(header, allTxs, decoded.Sidecars, decoded.SystemTxStart); err != nil { + if errors.Is(err, errInvalidBidBlockBlobTx) { + w.revokeBidBlockBuilder(decoded.Builder, err.Error(), decoded.Hash(), decoded.BlockNumber()) + } + return nil, err + } + if err := bindSignBidBlockSystemTxs(allTxs[decoded.SystemTxStart:], w.chainConfig.ChainID, p); err != nil { + return nil, err + } + header.TxHash = types.DeriveSha(types.Transactions(allTxs), trie.NewStackTrie(nil)) + + body := &types.Body{ + Transactions: allTxs, + Withdrawals: make([]*types.Withdrawal, 0), + } + block := types.NewBlockWithHeader(header).WithBody(*body).WithSidecars(decoded.Sidecars) + + return &task{ + block: block, + bidBlockInfo: &bidBlockTaskInfo{ + builder: decoded.Builder, + bidHash: decoded.Hash(), + gasFee: decoded.GasFee, + systemTxStart: decoded.SystemTxStart, + }, + createdAt: time.Now(), + miningStartAt: start, + }, nil +} + +type bidBlockBlobValidationJob struct { + txIndex int + tx *types.Transaction +} + +// validateBidBlockBlobTxs runs expensive blob proof checks for the selected BidBlock. +func validateBidBlockBlobTxs(header *types.Header, txs []*types.Transaction, sidecars types.BlobSidecars, systemTxStart int) error { + jobs := make([]bidBlockBlobValidationJob, 0, len(sidecars)) + sidecarIndex := 0 + for txIndex, tx := range txs[:systemTxStart] { + if tx.Type() != types.BlobTxType { + continue + } + sidecar := sidecars[sidecarIndex] + jobs = append(jobs, bidBlockBlobValidationJob{ + txIndex: txIndex, + tx: tx.WithBlobTxSidecar(&sidecar.BlobTxSidecar), + }) + sidecarIndex++ + } + + workers := len(jobs) + if workers > maxBlobValConcurrency { + workers = maxBlobValConcurrency + } + jobCh := make(chan bidBlockBlobValidationJob, len(jobs)) + for _, job := range jobs { + jobCh <- job + } + close(jobCh) + + errCh := make(chan error, len(jobs)) + var wg sync.WaitGroup + wg.Add(workers) + for i := 0; i < workers; i++ { + go func() { + defer wg.Done() + for job := range jobCh { + if err := txpool.ValidateBlobTx(job.tx, header, nil); err != nil { + errCh <- fmt.Errorf("%w: %v", errInvalidBidBlockBlobTx, err) + } + } + }() + } + wg.Wait() + close(errCh) + for err := range errCh { + return err + } + return nil +} + +func (w *worker) enqueueBidBlockTask(task *task, systemTxs int) { + // assembleVoteAttestation + sign header happen inside Seal. + select { + case w.taskCh <- task: + log.Info("[BID BLOCK COMMIT]", + "number", task.block.Number(), + "bidHash", task.bidBlockInfo.bidHash, + "builder", task.bidBlockInfo.builder, + "txs", len(task.block.Transactions()), + "systemTxs", systemTxs, + "gas", task.block.GasUsed(), + "gasFee", weiToEtherStringF6(task.bidBlockInfo.gasFee)) + case <-w.exitCh: + log.Info("Worker has exited") + } +} + +func (w *worker) revokeBidBlockBuilder(builder common.Address, reason string, hash common.Hash, blockNum uint64) { + w.revokeBidBlockBuilderFor(builder, reason, hash, blockNum, bidBlockRevokeDuration) +} + +func (w *worker) revokeBidBlockBuilderFor(builder common.Address, reason string, hash common.Hash, blockNum uint64, duration time.Duration) { + w.permMgr.RevokeFor(builder, reason, hash, blockNum, duration) + bidBlockRevokeGauge.Inc(1) + bidBlockRevokedBuildersGauge.Update(int64(w.permMgr.ActiveRevokeCount())) +} + +// handleBidBlockResult handles a sealed BidBlock: broadcast, then InsertChain for verification. +func (w *worker) handleBidBlockResult(block *types.Block, task *task) { + hash := block.Hash() + + // Broadcast the block first (before verification) + stats := w.chain.GetBlockStats(hash) + stats.SendBlockTime.Store(time.Now().UnixMilli()) + stats.StartMiningTime.Store(task.miningStartAt.UnixMilli()) + + log.Info("[BID BLOCK SEALED]", + "number", block.Number(), + "hash", hash, + "bidHash", task.bidBlockInfo.bidHash, + "builder", task.bidBlockInfo.builder, + "elapsed", common.PrettyDuration(time.Since(task.createdAt))) + + w.mux.Post(core.NewSealedBlockEvent{Block: block}) + + // InsertChain re-executes all txs and validates fields the validator could + // not check at admission. Any mismatch is treated as builder dishonesty and + // revokes the builder for the default lockout window. Categories caught here: + // - Root (post-execution state root) + // - ReceiptHash (post-execution receipts trie root) + // - Bloom (post-execution logs bloom) + // - GasUsed (cumulative gas consumed) + // - Tx precheck failures (nonce, balance, signature, intrinsic gas, ...) + // - System tx value / params (e.g. deposit value vs. SystemAddress balance) + // - Blob sidecar checks (KZG proofs, blob hashes) + if _, err := w.chain.InsertChain(types.Blocks{block}); err != nil { + log.Error("[BID BLOCK VERIFY FAILED]", + "number", block.Number(), + "hash", hash, + "bidHash", task.bidBlockInfo.bidHash, + "parentHash", block.ParentHash(), + "txs", len(block.Transactions()), + "gasUsed", block.GasUsed(), + "stateRoot", block.Root(), + "receiptHash", block.ReceiptHash(), + "builder", task.bidBlockInfo.builder, + "err", err) + w.revokeBidBlockBuilder(task.bidBlockInfo.builder, fmt.Sprintf("InsertChain err: %v", err), hash, block.NumberU64()) + return + } + // Check the post-import average gas price excluding system transactions; only future BidBlock permission is revoked. + if receipts := w.chain.GetReceiptsByHash(block.Hash()); receipts != nil { + avgGasPrice, nonSystemGasUsed, err := validateBidBlockAverageGasPrice( + task.bidBlockInfo.gasFee, + receipts, + task.bidBlockInfo.systemTxStart, + w.config.GasPrice, + ) + if err != nil { + log.Error("[BID BLOCK GASPRICE LOW]", + "number", block.Number(), + "hash", block.Hash(), + "bidHash", task.bidBlockInfo.bidHash, + "builder", task.bidBlockInfo.builder, + "avgGasPrice", avgGasPrice, + "minGasPrice", w.config.GasPrice, + "nonSystemGasUsed", nonSystemGasUsed, + "nonSystemTxs", task.bidBlockInfo.systemTxStart, + "revokeDuration", bidBlockGasPriceLowRevokeDuration, + "err", err) + w.revokeBidBlockBuilderFor(task.bidBlockInfo.builder, err.Error(), block.Hash(), block.NumberU64(), bidBlockGasPriceLowRevokeDuration) + return + } + } + + log.Info("[BID BLOCK VERIFIED]", + "number", block.Number(), + "hash", hash, + "bidHash", task.bidBlockInfo.bidHash, + "builder", task.bidBlockInfo.builder, + "gasFee", weiToEtherStringF6(task.bidBlockInfo.gasFee)) +} diff --git a/miner/bid_block_permission.go b/miner/bid_block_permission.go new file mode 100644 index 0000000000..00b04e73dd --- /dev/null +++ b/miner/bid_block_permission.go @@ -0,0 +1,153 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. +// +// BidBlock permission management (BEP-675 Layer 2). + +package miner + +import ( + "sync" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" +) + +// RevokeReasonManual is the Reason value used when an operator manually revokes +// a builder via SetAllowed. Automatic revokes carry the underlying error or +// policy message as Reason directly. +const RevokeReasonManual = "manual" + +const ( + // bidBlockRevokeDuration is the default lockout window for invalid BidBlocks. + bidBlockRevokeDuration = 24 * time.Hour + // bidBlockGasPriceLowRevokeDuration is one epoch for gas-price policy revokes. + bidBlockGasPriceLowRevokeDuration = 450 * time.Second +) + +// BidBlockRevokeRecord holds one active revoke event. +type BidBlockRevokeRecord struct { + RevokedAt time.Time + Duration time.Duration + Reason string // err detail for auto revokes (InsertChain failure), or RevokeReasonManual + BlockHash common.Hash + BlockNum uint64 +} + +// BidBlockPermissionManager tracks per-builder SendBidBlock revokes. +// Revokes are kept in memory and expire lazily after their lockout window. +type BidBlockPermissionManager struct { + mu sync.RWMutex + revoked map[common.Address]BidBlockRevokeRecord + + clock func() time.Time +} + +// NewBidBlockPermissionManager returns a fresh manager with no builders revoked. +func NewBidBlockPermissionManager() *BidBlockPermissionManager { + return &BidBlockPermissionManager{ + revoked: make(map[common.Address]BidBlockRevokeRecord), + clock: time.Now, + } +} + +// IsAllowed reports whether builder may currently use SendBidBlock. +func (m *BidBlockPermissionManager) IsAllowed(builder common.Address) bool { + m.mu.RLock() + defer m.mu.RUnlock() + _, found := m.activeRecord(builder, m.clock()) + return !found +} + +// Revoke denies builder and records the reason exposed by the permission RPC. +func (m *BidBlockPermissionManager) Revoke( + builder common.Address, + reason string, + blockHash common.Hash, + blockNum uint64, +) { + m.RevokeFor(builder, reason, blockHash, blockNum, bidBlockRevokeDuration) +} + +// RevokeFor denies builder for the supplied duration and records the reason +// exposed by the permission RPC. +func (m *BidBlockPermissionManager) RevokeFor( + builder common.Address, + reason string, + blockHash common.Hash, + blockNum uint64, + duration time.Duration, +) { + if duration <= 0 { + duration = bidBlockRevokeDuration + } + m.mu.Lock() + defer m.mu.Unlock() + m.revoked[builder] = BidBlockRevokeRecord{ + RevokedAt: m.clock(), + Duration: duration, + Reason: reason, + BlockHash: blockHash, + BlockNum: blockNum, + } +} + +func (m *BidBlockPermissionManager) GetStatus(builder common.Address) types.BidBlockPermissionStatus { + m.mu.RLock() + defer m.mu.RUnlock() + status := types.BidBlockPermissionStatus{ + Allowed: true, + } + rec, found := m.activeRecord(builder, m.clock()) + if !found { + return status + } + status.Allowed = false + status.Reason = rec.Reason + status.BlockHash = rec.BlockHash + status.BlockNum = rec.BlockNum + status.RevokedAt = rec.RevokedAt + status.ResetAt = rec.RevokedAt.Add(rec.Duration) + return status +} + +// ActiveRevokeCount returns the number of currently revoked builders. +func (m *BidBlockPermissionManager) ActiveRevokeCount() int { + m.mu.RLock() + defer m.mu.RUnlock() + now := m.clock() + count := 0 + for _, rec := range m.revoked { + if isRevokeActive(rec, now) { + count++ + } + } + return count +} + +func (m *BidBlockPermissionManager) SetAllowed(builder common.Address, allowed bool) { + m.mu.Lock() + defer m.mu.Unlock() + if allowed { + delete(m.revoked, builder) + return + } + m.revoked[builder] = BidBlockRevokeRecord{ + RevokedAt: m.clock(), + Duration: bidBlockRevokeDuration, + Reason: RevokeReasonManual, + } +} + +// isRevokeActive reports whether now is before the revoke reset time. +func isRevokeActive(rec BidBlockRevokeRecord, now time.Time) bool { + return now.Before(rec.RevokedAt.Add(rec.Duration)) +} + +func (m *BidBlockPermissionManager) activeRecord(builder common.Address, now time.Time) (BidBlockRevokeRecord, bool) { + rec, found := m.revoked[builder] + if !found || !isRevokeActive(rec, now) { + return BidBlockRevokeRecord{}, false + } + return rec, true +} diff --git a/miner/bid_block_permission_test.go b/miner/bid_block_permission_test.go new file mode 100644 index 0000000000..7ab76847e2 --- /dev/null +++ b/miner/bid_block_permission_test.go @@ -0,0 +1,413 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. + +package miner + +import ( + "context" + "strings" + "sync" + "testing" + "time" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/miner/builderclient" + "github.com/ethereum/go-ethereum/miner/minerconfig" +) + +// testInsertChainReason is a placeholder used by tests where the specific +// InsertChain error text doesn't matter — production passes +// "InsertChain err: " here. +const testInsertChainReason = "InsertChain err: test" + +func getBidBlockPermissionRecord(m *BidBlockPermissionManager, builder common.Address) (BidBlockRevokeRecord, bool) { + m.mu.RLock() + defer m.mu.RUnlock() + return m.activeRecord(builder, m.clock()) +} + +func setBidBlockPermissionClock(m *BidBlockPermissionManager, f func() time.Time) { + m.mu.Lock() + defer m.mu.Unlock() + m.clock = f +} + +func TestBidBlockPermission_DefaultActive(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + if !m.IsAllowed(builder) { + t.Fatal("default state should be Active for any builder") + } + if _, ok := getBidBlockPermissionRecord(m, builder); ok { + t.Fatal("no record expected for fresh builder") + } +} + +func TestBidBlockPermission_RevokeBlocks(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + hash := common.HexToHash("0xabc") + + m.Revoke(builder, testInsertChainReason, hash, 100) + if m.IsAllowed(builder) { + t.Fatal("revoked builder should not be allowed within 24h of revoke") + } + + rec, ok := getBidBlockPermissionRecord(m, builder) + if !ok { + t.Fatal("record expected after Revoke") + } + if rec.Reason != testInsertChainReason { + t.Fatalf("reason: got %s, want %s", rec.Reason, testInsertChainReason) + } + if rec.BlockHash != hash { + t.Fatalf("blockHash: got %s, want %s", rec.BlockHash.Hex(), hash.Hex()) + } + if rec.BlockNum != 100 { + t.Fatalf("blockNum: got %d, want 100", rec.BlockNum) + } + if rec.Duration != bidBlockRevokeDuration { + t.Fatalf("duration: got %s, want %s", rec.Duration, bidBlockRevokeDuration) + } +} + +func TestBidBlockPermission_BuildersIndependent(t *testing.T) { + m := NewBidBlockPermissionManager() + a := common.HexToAddress("0xa") + b := common.HexToAddress("0xb") + + m.Revoke(a, testInsertChainReason, common.Hash{}, 1) + if m.IsAllowed(a) { + t.Fatal("a should be revoked") + } + if !m.IsAllowed(b) { + t.Fatal("b should remain active") + } +} + +func TestBidBlockPermission_RevokeForCustomDuration(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + now := time.Date(2026, 5, 8, 12, 0, 0, 0, time.UTC) + + setBidBlockPermissionClock(m, func() time.Time { return now }) + m.RevokeFor(builder, errBidBlockAverageGasPriceTooLow.Error(), common.Hash{}, 1, bidBlockGasPriceLowRevokeDuration) + + status := m.GetStatus(builder) + if status.Allowed { + t.Fatal("builder should be revoked") + } + if want := now.Add(bidBlockGasPriceLowRevokeDuration); !status.ResetAt.Equal(want) { + t.Fatalf("resetAt: got %s, want %s", status.ResetAt, want) + } + + setBidBlockPermissionClock(m, func() time.Time { return now.Add(bidBlockGasPriceLowRevokeDuration) }) + if !m.IsAllowed(builder) { + t.Fatal("gas price low revoke should expire after the custom duration") + } +} + +func TestBidBlockPermission_RevokeOverwrites(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + + m.Revoke(builder, testInsertChainReason, common.HexToHash("0x1"), 1) + m.Revoke(builder, RevokeReasonManual, common.HexToHash("0x2"), 2) + + rec, ok := getBidBlockPermissionRecord(m, builder) + if !ok { + t.Fatal("record expected") + } + if rec.Reason != RevokeReasonManual { + t.Fatalf("most recent reason should win: got %s", rec.Reason) + } + if rec.BlockNum != 2 { + t.Fatalf("most recent blockNum should win: got %d", rec.BlockNum) + } +} + +func TestBidBlockPermission_ExpiresAt24h(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + + revokeTime := time.Date(2026, 5, 8, 12, 0, 0, 0, time.UTC) + exactly24hLater := revokeTime.Add(24 * time.Hour) + + setBidBlockPermissionClock(m, func() time.Time { return revokeTime }) + m.Revoke(builder, testInsertChainReason, common.Hash{}, 1) + if m.IsAllowed(builder) { + t.Fatal("freshly revoked builder should be blocked") + } + + setBidBlockPermissionClock(m, func() time.Time { return exactly24hLater }) + if !m.IsAllowed(builder) { + t.Fatal("record at exactly revokedAt + 24h should be expired") + } + if _, ok := getBidBlockPermissionRecord(m, builder); ok { + t.Fatal("getRecord should report expired at revokedAt + 24h") + } +} + +func TestBidBlockPermission_StillRevokedWithin24h(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + + // UTC midnight should not reset the revoke; only elapsed time matters. + // This covers the old day-boundary bypass. + revokeTime := time.Date(2026, 5, 8, 23, 59, 59, 0, time.UTC) + setBidBlockPermissionClock(m, func() time.Time { return revokeTime }) + m.Revoke(builder, testInsertChainReason, common.Hash{}, 1) + + justAfterUTCMidnight := time.Date(2026, 5, 9, 0, 0, 1, 0, time.UTC) + setBidBlockPermissionClock(m, func() time.Time { return justAfterUTCMidnight }) + if m.IsAllowed(builder) { + t.Fatal("revoke must not expire just because UTC day rolled over (only 2s elapsed)") + } + + justBefore24h := revokeTime.Add(24*time.Hour - time.Second) + setBidBlockPermissionClock(m, func() time.Time { return justBefore24h }) + if m.IsAllowed(builder) { + t.Fatal("revoke must still be active 1s before the 24h boundary") + } +} + +// Builders revoked at different times should expire independently. +func TestBidBlockPermission_IndependentResetAt(t *testing.T) { + m := NewBidBlockPermissionManager() + a := common.HexToAddress("0xa") + b := common.HexToAddress("0xb") + + t0 := time.Date(2026, 5, 8, 10, 0, 0, 0, time.UTC) + + setBidBlockPermissionClock(m, func() time.Time { return t0 }) + m.Revoke(a, testInsertChainReason, common.Hash{}, 1) + + setBidBlockPermissionClock(m, func() time.Time { return t0.Add(5 * time.Hour) }) + m.Revoke(b, testInsertChainReason, common.Hash{}, 2) + + // Both revoked at t0 + 6h; resetAt fields must be independent. + setBidBlockPermissionClock(m, func() time.Time { return t0.Add(6 * time.Hour) }) + statusA := m.GetStatus(a) + statusB := m.GetStatus(b) + if statusA.Allowed || statusB.Allowed { + t.Fatal("both builders should be revoked at t0 + 6h") + } + if want := t0.Add(24 * time.Hour); !statusA.ResetAt.Equal(want) { + t.Fatalf("A resetAt: got %s, want %s", statusA.ResetAt, want) + } + if want := t0.Add(29 * time.Hour); !statusB.ResetAt.Equal(want) { + t.Fatalf("B resetAt: got %s, want %s", statusB.ResetAt, want) + } + + // At A.RevokedAt + 24h, A's lockout expires but B still has 5h left. + setBidBlockPermissionClock(m, func() time.Time { return t0.Add(24 * time.Hour) }) + if !m.IsAllowed(a) { + t.Fatal("A should be allowed at its own RevokedAt + 24h") + } + if m.IsAllowed(b) { + t.Fatal("B should still be revoked (only 19h elapsed since its own RevokedAt)") + } + + // At B.RevokedAt + 24h, B's lockout also expires. + setBidBlockPermissionClock(m, func() time.Time { return t0.Add(29 * time.Hour) }) + if !m.IsAllowed(b) { + t.Fatal("B should be allowed at its own RevokedAt + 24h") + } +} + +func TestBidBlockPermission_ConcurrentAccess(t *testing.T) { + m := NewBidBlockPermissionManager() + builders := []common.Address{ + common.HexToAddress("0xa"), + common.HexToAddress("0xb"), + common.HexToAddress("0xc"), + } + + var wg sync.WaitGroup + for i := 0; i < 50; i++ { + wg.Add(3) + b := builders[i%len(builders)] + go func() { defer wg.Done(); m.IsAllowed(b) }() + go func() { defer wg.Done(); m.Revoke(b, testInsertChainReason, common.Hash{}, 1) }() + go func() { defer wg.Done(); getBidBlockPermissionRecord(m, b) }() + } + wg.Wait() +} + +func TestBidBlockPermission_ActiveRevokeCount(t *testing.T) { + m := NewBidBlockPermissionManager() + + if got := m.ActiveRevokeCount(); got != 0 { + t.Fatalf("empty manager: got %d, want 0", got) + } + + revokeTime := time.Date(2026, 5, 8, 12, 0, 0, 0, time.UTC) + after24h := revokeTime.Add(24 * time.Hour) + setBidBlockPermissionClock(m, func() time.Time { return revokeTime }) + + a := common.HexToAddress("0xa") + b := common.HexToAddress("0xb") + m.Revoke(a, testInsertChainReason, common.Hash{}, 1) + m.Revoke(b, RevokeReasonManual, common.Hash{}, 2) + + if got := m.ActiveRevokeCount(); got != 2 { + t.Fatalf("two revoked: got %d, want 2", got) + } + + setBidBlockPermissionClock(m, func() time.Time { return after24h }) + if got := m.ActiveRevokeCount(); got != 0 { + t.Fatalf("after revokedAt + 24h: got %d, want 0 (entries are stale, not active)", got) + } +} + +func TestBidBlockPermission_GetStatus(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + now := time.Date(2026, 5, 9, 10, 0, 0, 0, time.UTC) + resetAt := now.Add(24 * time.Hour) + setBidBlockPermissionClock(m, func() time.Time { return now }) + + status := m.GetStatus(builder) + if !status.Allowed { + t.Fatal("fresh builder should be allowed") + } + if !status.ResetAt.IsZero() { + t.Fatalf("allowed status should not set resetAt: got %s", status.ResetAt) + } + + hash := common.HexToHash("0xabc") + m.Revoke(builder, testInsertChainReason, hash, 100) + status = m.GetStatus(builder) + if status.Allowed { + t.Fatal("revoked builder should not be allowed") + } + if status.Reason != testInsertChainReason { + t.Fatalf("reason: got %s", status.Reason) + } + if status.BlockHash != hash || status.BlockNum != 100 || !status.RevokedAt.Equal(now) || !status.ResetAt.Equal(resetAt) { + t.Fatalf("status mismatch: %#v", status) + } +} + +func TestBidBlockAdmission_RevokedDoesNotConsumeQuota(t *testing.T) { + permMgr := NewBidBlockPermissionManager() + b := &bidSimulator{ + builders: make(map[common.Address]*builderclient.Client), + pending: make(map[uint64]map[common.Address]map[common.Hash]struct{}), + maxBidsPerBuilder: 2, + } + + builder := common.HexToAddress("0x1") + const blockNum uint64 = 100 + + b.builders[builder] = nil + permMgr.Revoke(builder, testInsertChainReason, common.Hash{}, blockNum-1) + + if !b.ExistBuilder(builder) { + t.Fatal("registered builder must pass ExistBuilder") + } + if permMgr.IsAllowed(builder) { + t.Fatal("revoked builder must fail permission check") + } + + b.pendingMu.RLock() + pendingForBlock := b.pending[blockNum] + b.pendingMu.RUnlock() + if len(pendingForBlock) != 0 { + t.Fatalf("revoked admission must not touch pending map; got %d entries", len(pendingForBlock)) + } + + other := common.HexToAddress("0x2") + otherHash := common.HexToHash("0xbeef") + if err := b.CheckPending(blockNum, other, otherHash); err != nil { + t.Fatalf("active builder should pass CheckPending: %v", err) + } + b.AddPending(blockNum, other, otherHash) + + b.pendingMu.RLock() + otherCount := len(b.pending[blockNum][other]) + revokedCount := len(b.pending[blockNum][builder]) + b.pendingMu.RUnlock() + if otherCount != 1 { + t.Fatalf("active builder should have 1 pending entry; got %d", otherCount) + } + if revokedCount != 0 { + t.Fatalf("revoked builder should have 0 pending entries; got %d", revokedCount) + } +} + +func TestBidBlockAdmission_DisabledDoesNotConsumeQuota(t *testing.T) { + for _, tc := range []struct { + name string + mevEnabled bool + bidBlockEnabled bool + }{ + {name: "BidBlock disabled", mevEnabled: true, bidBlockEnabled: false}, + {name: "MEV disabled", mevEnabled: false, bidBlockEnabled: true}, + } { + t.Run(tc.name, func(t *testing.T) { + miner := &Miner{ + worker: &worker{config: &minerconfig.Config{ + Mev: minerconfig.MevConfig{ + Enabled: &tc.mevEnabled, + BidBlockEnabled: &tc.bidBlockEnabled, + }, + }}, + bidSimulator: &bidSimulator{ + pending: make(map[uint64]map[common.Address]map[common.Hash]struct{}), + }, + } + + _, err := miner.SendBidBlock(context.Background(), &types.BidBlockArgs{}) + if err == nil || !strings.Contains(err.Error(), "BidBlock disabled") { + t.Fatalf("expected BidBlock disabled error, got %v", err) + } + if len(miner.bidSimulator.pending) != 0 { + t.Fatalf("disabled SendBidBlock must not touch pending map; got %d entries", len(miner.bidSimulator.pending)) + } + }) + } +} + +func TestMinerBidBlockPermission_UsesWorkerManager(t *testing.T) { + m := NewBidBlockPermissionManager() + miner := &Miner{worker: &worker{permMgr: m}} + builder := common.HexToAddress("0x1") + + m.Revoke(builder, testInsertChainReason, common.Hash{}, 1) + if miner.GetBidBlockPermission(builder).Allowed { + t.Fatal("miner should report worker revoke") + } +} + +func TestBidBlockPermission_SetAllowed_Deny(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + + m.SetAllowed(builder, false) + if m.IsAllowed(builder) { + t.Fatal("builder should be denied after SetAllowed(false)") + } + rec, ok := getBidBlockPermissionRecord(m, builder) + if !ok { + t.Fatal("record expected after SetAllowed(false)") + } + if rec.Reason != RevokeReasonManual { + t.Fatalf("reason: got %q, want %q", rec.Reason, RevokeReasonManual) + } +} + +func TestBidBlockPermission_SetAllowed_Clear(t *testing.T) { + m := NewBidBlockPermissionManager() + builder := common.HexToAddress("0x1") + + m.Revoke(builder, testInsertChainReason, common.HexToHash("0xabc"), 100) + m.SetAllowed(builder, true) + if !m.IsAllowed(builder) { + t.Fatal("manual SetAllowed(true) should override revoke") + } + if _, ok := getBidBlockPermissionRecord(m, builder); ok { + t.Fatal("record should be cleared") + } +} diff --git a/miner/bid_gas_price.go b/miner/bid_gas_price.go new file mode 100644 index 0000000000..8c30b4f1ab --- /dev/null +++ b/miner/bid_gas_price.go @@ -0,0 +1,41 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. + +package miner + +import ( + "errors" + "fmt" + "math/big" + + "github.com/ethereum/go-ethereum/core/types" +) + +var errBidBlockAverageGasPriceTooLow = errors.New("BidBlock average gas price too low") + +func validateBidBlockAverageGasPrice( + gasFee *big.Int, + receipts types.Receipts, + systemTxStart int, + minGasPrice *big.Int, +) (*big.Int, uint64, error) { + gasUsed := calcNonSystemGasUsed(receipts[:systemTxStart]) + if gasUsed == 0 { + return nil, 0, nil + } + avgGasPrice := new(big.Int).Div(new(big.Int).Set(gasFee), new(big.Int).SetUint64(gasUsed)) + if avgGasPrice.Cmp(minGasPrice) < 0 { + return avgGasPrice, gasUsed, fmt.Errorf("%w, avg:%v, min:%v", errBidBlockAverageGasPriceTooLow, avgGasPrice, minGasPrice) + } + return avgGasPrice, gasUsed, nil +} + +func calcNonSystemGasUsed( + receipts types.Receipts, +) uint64 { + gasUsed := uint64(0) + for _, receipt := range receipts { + gasUsed += receipt.GasUsed + } + return gasUsed +} diff --git a/miner/bid_gas_price_test.go b/miner/bid_gas_price_test.go new file mode 100644 index 0000000000..c2d4572f68 --- /dev/null +++ b/miner/bid_gas_price_test.go @@ -0,0 +1,48 @@ +// Copyright 2026 The go-ethereum Authors +// This file is part of the go-ethereum library. + +package miner + +import ( + "errors" + "math/big" + "testing" + + "github.com/ethereum/go-ethereum/core/types" +) + +func TestValidateBidBlockAverageGasPriceTooLow(t *testing.T) { + receipts := types.Receipts{{GasUsed: 21_000}} + gasFee := big.NewInt(21_000) + + avg, gasUsed, err := validateBidBlockAverageGasPrice(gasFee, receipts, 1, big.NewInt(2)) + if !errors.Is(err, errBidBlockAverageGasPriceTooLow) { + t.Fatalf("expected low gas price error, got %v", err) + } + if avg.Cmp(big.NewInt(1)) != 0 { + t.Fatalf("avg gas price: got %v, want 1", avg) + } + if gasUsed != 21_000 { + t.Fatalf("gas used: got %d, want 21000", gasUsed) + } +} + +func TestValidateBidBlockAverageGasPriceExcludesSystemTxs(t *testing.T) { + receipts := types.Receipts{ + {GasUsed: 21_000}, + {GasUsed: 21_000}, + {GasUsed: 21_000}, + } + gasFee := big.NewInt(5 * 42_000) + + avg, gasUsed, err := validateBidBlockAverageGasPrice(gasFee, receipts, 2, big.NewInt(5)) + if err != nil { + t.Fatalf("check gas price failed: %v", err) + } + if avg.Cmp(big.NewInt(5)) != 0 { + t.Fatalf("avg gas price: got %v, want 5", avg) + } + if gasUsed != 42_000 { + t.Fatalf("gas used: got %d, want 42000", gasUsed) + } +} diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index 88676655a0..3eb7ed9ab4 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -33,6 +33,9 @@ import ( const prefetchTxNumber = 50 +// uint256BitLen is the bit width of uint256; a value wider than this cannot fit a tx value. +const uint256BitLen = 256 + var ( bidPreCheckTimer = metrics.NewRegisteredTimer("bid/preCheck", nil) bidTryInterruptTimer = metrics.NewRegisteredTimer("bid/sim/tryInterrupt", nil) @@ -45,6 +48,17 @@ var ( // greedyMergeOnchainCounter counts bids that went through greedy merge and were finally chosen as BUILDER BLOCK. greedyMergeOnchainCounter = metrics.NewRegisteredCounter("bid/greedyMerge/onchain", nil) + + // bidBlockBuildersGauge tracks the distinct registered builders that have + // sent BidBlock since node start (cumulative, in-memory, resets on restart). + bidBlockBuildersGauge = metrics.NewRegisteredGauge("bidblock/sendBidBlock/builders", nil) + + // bidBlockPreCheckTimer measures SendBidBlock admission time from RPC receive + // to successful pre-seal verification, matching the legacy bid/preCheck scope. + bidBlockPreCheckTimer = metrics.NewRegisteredTimer("bidblock/sendBidBlock/preCheck", nil) + + // bidBlockPreSealVerifyTimer measures only preSealVerifyBidBlock duration. + bidBlockPreSealVerifyTimer = metrics.NewRegisteredTimer("bidblock/sendBidBlock/preSealVerify", nil) ) var ( @@ -73,6 +87,7 @@ var ( type bidWorker interface { prepareWork(params *generateParams, witness bool) (*environment, error) etherbase() common.Address + getGasCeil() uint64 getPrefetcher() core.Prefetcher fillTransactions(interruptCh chan int32, env *environment, stopTimer *time.Timer, bidTxs mapset.Set[common.Hash]) (err error) } @@ -90,6 +105,11 @@ type newBidPackage struct { receiveTime int64 } +type newBidBlockPackage struct { + bidBlock *types.DecodedBidBlock + feedback chan error +} + // bidSimulator is in charge of receiving bid from builders, reporting issue to builders. // And take care of bid simulation, rewards computing, best bid maintaining. type bidSimulator struct { @@ -132,6 +152,15 @@ type bidSimulator struct { bidsToSim map[uint64][]*BidRuntime // blockNumber --> bidRuntime list, used to discard envs maxBidsPerBuilder uint32 // Maximum number of bids allowed per builder per block + + // SendBidBlock fields + bestBidBlockMu sync.RWMutex + bestBidBlock map[common.Hash]*types.DecodedBidBlock // parentHash -> best bid block + newBidBlockCh chan newBidBlockPackage // channel for incoming bid blocks + + // distinct registered builders that have sent BidBlock since node start + bidBlockBuildersMu sync.Mutex + bidBlockBuilders map[common.Address]struct{} } func newBidSimulator( @@ -144,23 +173,26 @@ func newBidSimulator( bidWorker bidWorker, ) *bidSimulator { b := &bidSimulator{ - config: config, - minGasPrice: minGasPrice, - chain: eth.BlockChain(), - txpool: eth.TxPool(), - chainConfig: chainConfig, - engine: engine, - bidWorker: bidWorker, - exitCh: make(chan struct{}), - chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), - builders: make(map[common.Address]*builderclient.Client), - simBidCh: make(chan *simBidReq), - newBidCh: make(chan newBidPackage, 100), - pending: make(map[uint64]map[common.Address]map[common.Hash]struct{}), - bestBid: make(map[common.Hash]*BidRuntime), - bestBidToRun: make(map[common.Hash]*types.Bid), - simulatingBid: make(map[common.Hash]*BidRuntime), - bidsToSim: make(map[uint64][]*BidRuntime), + config: config, + minGasPrice: minGasPrice, + chain: eth.BlockChain(), + txpool: eth.TxPool(), + chainConfig: chainConfig, + engine: engine, + bidWorker: bidWorker, + exitCh: make(chan struct{}), + chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize), + builders: make(map[common.Address]*builderclient.Client), + simBidCh: make(chan *simBidReq), + newBidCh: make(chan newBidPackage, 100), + pending: make(map[uint64]map[common.Address]map[common.Hash]struct{}), + bestBid: make(map[common.Hash]*BidRuntime), + bestBidToRun: make(map[common.Hash]*types.Bid), + simulatingBid: make(map[common.Hash]*BidRuntime), + bidsToSim: make(map[uint64][]*BidRuntime), + bestBidBlock: make(map[common.Hash]*types.DecodedBidBlock), + newBidBlockCh: make(chan newBidBlockPackage, 100), + bidBlockBuilders: make(map[common.Address]struct{}), } if delayLeftOver != nil { b.delayLeftOver = *delayLeftOver @@ -183,6 +215,7 @@ func newBidSimulator( go b.clearLoop() go b.mainLoop() go b.newBidLoop() + go b.newBidBlockLoop() return b } @@ -558,6 +591,11 @@ func (b *bidSimulator) bidBetterBefore(parentHash common.Hash) time.Time { return bidutil.BidBetterBefore(parentHeader, b.getBlockInterval(parentHeader), b.delayLeftOver, *b.config.BidSimulationLeftOver) } +func (b *bidSimulator) bidMustBefore(parentHash common.Hash) time.Time { + parentHeader := b.chain.GetHeaderByHash(parentHash) + return bidutil.BidMustBefore(parentHeader, b.getBlockInterval(parentHeader), b.delayLeftOver) +} + func (b *bidSimulator) clearLoop() { clearFn := func(parentHash common.Hash, blockNumber uint64) { b.pendingMu.Lock() @@ -601,6 +639,14 @@ func (b *bidSimulator) clearLoop() { } } b.simBidMu.Unlock() + + b.bestBidBlockMu.Lock() + for k, block := range b.bestBidBlock { + if block == nil || block.BlockNumber() <= clearThreshold { + delete(b.bestBidBlock, k) + } + } + b.bestBidBlockMu.Unlock() } for { @@ -622,6 +668,217 @@ func (b *bidSimulator) clearLoop() { } } +// AddBidBlock keeps the best BidBlock for a given parent hash. +func (b *bidSimulator) AddBidBlock(parentHash common.Hash, block *types.DecodedBidBlock) error { + b.bestBidBlockMu.Lock() + defer b.bestBidBlockMu.Unlock() + + if existing := b.bestBidBlock[parentHash]; existing != nil && block.GasFee.Cmp(existing.GasFee) <= 0 { + return fmt.Errorf("BidBlock gasFee not higher than current best: bidHash=%s got %s, bestBidHash=%s best %s", + block.Hash(), weiToEtherStringF6(block.GasFee), existing.Hash(), weiToEtherStringF6(existing.GasFee)) + } + b.bestBidBlock[parentHash] = block + return nil +} + +// GetBestBidBlock returns the best BidBlock for a given parent hash. +func (b *bidSimulator) GetBestBidBlock(parentHash common.Hash) *types.DecodedBidBlock { + b.bestBidBlockMu.RLock() + defer b.bestBidBlockMu.RUnlock() + return b.bestBidBlock[parentHash] +} + +// recordBidBlockBuilder adds builder to the cumulative set of registered +// builders that have sent BidBlock and publishes the distinct count. +// The set is kept in memory and resets on restart. +func (b *bidSimulator) recordBidBlockBuilder(builder common.Address) { + b.bidBlockBuildersMu.Lock() + b.bidBlockBuilders[builder] = struct{}{} + count := len(b.bidBlockBuilders) + b.bidBlockBuildersMu.Unlock() + bidBlockBuildersGauge.Update(int64(count)) +} + +// preSealVerifyBidBlock validates a BidBlock before admission. +func (b *bidSimulator) preSealVerifyBidBlock(decoded *types.DecodedBidBlock) error { + start := time.Now() + defer bidBlockPreSealVerifyTimer.UpdateSince(start) + parliaEngine, ok := b.engine.(*parlia.Parlia) + if !ok { + return errors.New("consensus engine is not parlia") + } + header := decoded.Header + + if header.Coinbase != b.bidWorker.etherbase() { + return fmt.Errorf("invalid coinbase: got %s, want %s", + header.Coinbase.Hex(), b.bidWorker.etherbase().Hex()) + } + parent := b.chain.GetHeaderByHash(header.ParentHash) + if parent == nil { + return consensus.ErrUnknownAncestor + } + expectedGasLimit := core.CalcGasLimit(parent.GasLimit, b.bidWorker.getGasCeil()) + if header.GasLimit != expectedGasLimit { + return fmt.Errorf("invalid gasLimit: got %d, want %d", header.GasLimit, expectedGasLimit) + } + if err := parliaEngine.VerifyUnsealedHeader(b.chain, header, nil); err != nil { + return fmt.Errorf("invalid header: %v", err) + } + if err := parliaEngine.BlockTimeUpperCheck(b.chain, header); err != nil { + return fmt.Errorf("invalid header: %v", err) + } + + decoded.SystemTxStart, decoded.GasFee = parliaEngine.ExtractBidBlockDepositValue(decoded.Txs) + + // GasFee comes from the deposit tx value; reject overflow before bid selection. + if decoded.GasFee.Sign() <= 0 { + return errors.New("empty gasFee") + } + if decoded.GasFee.BitLen() > uint256BitLen { + return fmt.Errorf("gasFee exceeds uint256: bitLen %d", decoded.GasFee.BitLen()) + } + + // Only cheap sidecar checks run at admission; KZG is checked for the selected BidBlock. + if err := b.validateBidBlockBlobSidecars(decoded); err != nil { + return err + } + + // Per-tx gas cap over user txs only, mirroring SendBid. + for _, tx := range decoded.Txs[:decoded.SystemTxStart] { + if tx.Gas() > params.MaxTxGas { + return fmt.Errorf("%w (cap: %d, tx: %d)", core.ErrGasLimitTooHigh, params.MaxTxGas, tx.Gas()) + } + } + + return parliaEngine.VerifyBidBlockSystemTxs(decoded, parent, decoded.SystemTxStart) +} + +// validateBidBlockBlobSidecars checks cheap sidecar invariants before bid selection. +func (b *bidSimulator) validateBidBlockBlobSidecars(decoded *types.DecodedBidBlock) error { + header := decoded.Header + blobEligibleBlock := eip4844.IsBlobEligibleBlock(b.chainConfig, header.Number.Uint64(), header.Time) + maxBlobsPerBlock := eip4844.MaxBlobsPerBlock(b.chainConfig, header.Time) + sidecarIndex := 0 + blobCount := 0 + for txIndex, tx := range decoded.Txs[:decoded.SystemTxStart] { + if tx.Type() != types.BlobTxType { + continue + } + if !blobEligibleBlock { + return fmt.Errorf("blob transactions not allowed in block %d (N %% %d != 0)", + header.Number.Uint64(), params.BlobEligibleBlockInterval) + } + if sidecarIndex >= len(decoded.Sidecars) { + return fmt.Errorf("blob info mismatch: sidecars %d, blob txs at least %d", + len(decoded.Sidecars), sidecarIndex+1) + } + sidecar := decoded.Sidecars[sidecarIndex] + if sidecar == nil { + return fmt.Errorf("missing sidecar for blob tx at index %d", txIndex) + } + if sidecar.Version == types.BlobSidecarVersion1 { + return errors.New("cell proof is not supported yet") + } + if sidecar.TxHash != tx.Hash() { + return fmt.Errorf("sidecar's TxHash mismatch with transaction at index %d, want: %v, have: %v", + txIndex, tx.Hash(), sidecar.TxHash) + } + if sidecar.TxIndex != uint64(txIndex) { + return fmt.Errorf("sidecar's TxIndex mismatch with transaction at index %d, want: %d, have: %d", + txIndex, txIndex, sidecar.TxIndex) + } + blobCount += len(sidecar.Blobs) + if blobCount > maxBlobsPerBlock { + return fmt.Errorf("too many blobs in block: have %d, permitted %d", + blobCount, maxBlobsPerBlock) + } + sidecarIndex++ + } + if sidecarIndex != len(decoded.Sidecars) { + return fmt.Errorf("blob info mismatch: sidecars %d, blob txs %d", len(decoded.Sidecars), sidecarIndex) + } + return nil +} + +// sendBidBlock queues a decoded BidBlock for selection. +func (b *bidSimulator) sendBidBlock(_ context.Context, block *types.DecodedBidBlock) error { + timer := time.NewTimer(1 * time.Second) + defer timer.Stop() + + replyCh := make(chan error, 1) + + select { + case b.newBidBlockCh <- newBidBlockPackage{bidBlock: block, feedback: replyCh}: + b.AddPending(block.BlockNumber(), block.Builder, block.Hash()) + case <-timer.C: + return types.ErrMevBusy + } + + select { + case reply := <-replyCh: + return reply + case <-timer.C: + return types.ErrMevBusy + } +} + +// newBidBlockLoop stores the best incoming BidBlock by GasFee. +func (b *bidSimulator) newBidBlockLoop() { + for { + select { + case newBidBlock := <-b.newBidBlockCh: + block := newBidBlock.bidBlock + if !b.isRunning() || !b.receivingBid() { + if newBidBlock.feedback != nil { + newBidBlock.feedback <- fmt.Errorf("BidBlock is discarded, not receiving bids: blockNumber=%d builder=%s bidHash=%s", + block.BlockNumber(), block.Builder, block.Hash()) + } + continue + } + + // Discard stale blocks whose block number is no longer current. + currentBlock := b.chain.CurrentBlock() + if block.BlockNumber() <= currentBlock.Number.Uint64() { + log.Debug("BidBlock: discard stale block", + "blockNumber", block.BlockNumber(), + "builder", block.Builder, + "bidHash", block.Hash()) + if newBidBlock.feedback != nil { + newBidBlock.feedback <- fmt.Errorf("BidBlock is discarded, stale block number: %d, latest block: %d, builder=%s, bidHash=%s", + block.BlockNumber(), currentBlock.Number.Uint64(), block.Builder, block.Hash()) + } + continue + } + + if err := b.AddBidBlock(block.ParentHash(), block); err != nil { + log.Debug("BidBlock: discard BidBlock", + "blockNumber", block.BlockNumber(), + "builder", block.Builder, + "bidHash", block.Hash(), + "gasFee", weiToEtherStringF6(block.GasFee), + "err", err) + if newBidBlock.feedback != nil { + newBidBlock.feedback <- err + } + continue + } + + log.Info("[BID BLOCK ARRIVED]", + "blockNumber", block.BlockNumber(), + "bidHash", block.Hash(), + "builder", block.Builder, + "gasFee", weiToEtherStringF6(block.GasFee), + "txs", len(block.Txs)) + if newBidBlock.feedback != nil { + newBidBlock.feedback <- nil + } + + case <-b.exitCh: + return + } + } +} + // sendBid checks if the bid is already exists or if the builder sends too many bids, // if yes, return error, if not, add bid into newBid chan waiting for judge profit. func (b *bidSimulator) sendBid(ctx context.Context, bid *types.Bid) error { diff --git a/miner/miner.go b/miner/miner.go index 3479f81dce..8dd6302c79 100644 --- a/miner/miner.go +++ b/miner/miner.go @@ -60,6 +60,7 @@ type Miner struct { } func New(eth Backend, config *minerconfig.Config, mux *event.TypeMux, engine consensus.Engine) *Miner { + bidBlockPermMgr := NewBidBlockPermissionManager() miner := &Miner{ mux: mux, eth: eth, @@ -67,7 +68,7 @@ func New(eth Backend, config *minerconfig.Config, mux *event.TypeMux, engine con exitCh: make(chan struct{}), startCh: make(chan struct{}), stopCh: make(chan struct{}), - worker: newWorker(config, engine, eth, mux), + worker: newWorker(config, engine, eth, mux, bidBlockPermMgr), } miner.bidSimulator = newBidSimulator(&config.Mev, config.DelayLeftOver, config.GasPrice, eth, eth.BlockChain().Config(), engine, miner.worker) diff --git a/miner/miner_mev.go b/miner/miner_mev.go index 7f7b0cf4b6..5183643fde 100644 --- a/miner/miner_mev.go +++ b/miner/miner_mev.go @@ -2,11 +2,13 @@ package miner import ( "context" + "errors" "fmt" "math/big" "time" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/consensus/parlia" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/internal/version" @@ -48,6 +50,109 @@ func (miner *Miner) HasBuilder(builder common.Address) bool { return miner.bidSimulator.ExistBuilder(builder) } +func (miner *Miner) GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus { + return miner.worker.permMgr.GetStatus(builder) +} + +func (miner *Miner) SetBidBlockPermission(builder common.Address, allowed bool) { + miner.worker.permMgr.SetAllowed(builder, allowed) +} + +// bidBlockEnabled reports whether SendBidBlock is accepted. +func (miner *Miner) bidBlockEnabled() bool { + if !*miner.worker.config.Mev.Enabled || !*miner.worker.config.Mev.BidBlockEnabled { + return false + } + return miner.bidBlockPasteurActive() +} + +func (miner *Miner) bidBlockPasteurActive() bool { + head := miner.worker.chain.CurrentBlock() + return head != nil && miner.worker.chainConfig.IsPasteur(head.Number, head.Time) +} + +func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) { + if !miner.bidBlockEnabled() { + return common.Hash{}, types.NewInvalidBidError("BidBlock disabled, fallback to SendBid") + } + + bb := args.BidBlock + bidHash := bb.Hash() + + builder, err := args.EcrecoverSender() + if err != nil { + return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("invalid signature: bidHash=%s, err=%v", bidHash, err)) + } + + if !miner.bidSimulator.ExistBuilder(builder) { + return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("builder is not registered: builder=%s, bidHash=%s", builder, bidHash)) + } + miner.bidSimulator.recordBidBlockBuilder(builder) + + // Check permission before CheckPending so rejected BidBlocks do not use quota. + if !miner.worker.permMgr.IsAllowed(builder) { + return common.Hash{}, types.NewBidBlockPermissionRevokedError("builder BidBlock permission revoked, fallback to SendBid") + } + + if len(bb.Transactions) == 0 { + return common.Hash{}, types.NewInvalidBidError("empty BidBlock txs") + } + blockNumber := bb.Header.Number.Uint64() + parentHash := bb.Header.ParentHash + if miner.bidSimulator.chain.GetHeaderByHash(parentHash) == nil { + return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("parent not found: %s, bidHash=%s", parentHash.Hex(), bidHash)) + } + if err := miner.bidSimulator.CheckPending(blockNumber, builder, bidHash); err != nil { + return common.Hash{}, err + } + + bidMustBefore := miner.bidSimulator.bidMustBefore(parentHash) + if timeout := time.Until(bidMustBefore); timeout <= 0 { + return common.Hash{}, types.NewBidBlockTooLateError(fmt.Sprintf("too late, expected before %s, appeared %s later, bidHash=%s", + bidMustBefore, common.PrettyDuration(timeout), bidHash)) + } + + decoded, err := args.ToDecodedBidBlock(builder) + if err != nil { + return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("failed to decode bid block: bidHash=%s, err=%v", bidHash, err)) + } + + // Validator owns the entire Extra: overwrite builder's bytes with the operator-configured + // vanity and let SetExtraData rebuild forkhash + validators + turnLength + reserved seal + // space. This runs before preSealVerifyBidBlock so VerifyUnsealedHeader validates the + // validator-constructed Extra rather than the builder's. + parliaEngine, ok := miner.worker.engine.(*parlia.Parlia) + if !ok { + return common.Hash{}, errors.New("consensus engine is not parlia") + } + miner.worker.confMu.RLock() + decoded.Header.Extra = common.CopyBytes(miner.worker.extra) + miner.worker.confMu.RUnlock() + if err := parliaEngine.SetExtraData(miner.worker.chain, decoded.Header); err != nil { + return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("set extra data: %v", err)) + } + // Record MEV v2 (bidblock path) source and builder address. + setBidMevInfo(decoded.Header, builder, true) + + if err := miner.bidSimulator.preSealVerifyBidBlock(decoded); err != nil { + log.Warn("BidBlock pre-seal verification failed", + "block", blockNumber, + "builder", builder, + "bidHash", decoded.Hash(), + "err", err) + return common.Hash{}, types.NewBidBlockPreSealVerifyError(fmt.Sprintf("pre-seal verify failed: bidHash=%s, err=%v", bidHash, err)) + } + if receiveTime, ok := ctx.Value("receiveTime").(int64); ok { + bidBlockPreCheckTimer.UpdateSince(time.UnixMilli(receiveTime)) + } + + if err := miner.bidSimulator.sendBidBlock(ctx, decoded); err != nil { + return common.Hash{}, err + } + + return bidHash, nil +} + func (miner *Miner) SendBid(ctx context.Context, bidArgs *types.BidArgs) (common.Hash, error) { builder, err := bidArgs.EcrecoverSender() if err != nil { @@ -146,6 +251,7 @@ func (miner *Miner) MevParams() *types.MevParams { GasCeil: miner.worker.config.GasCeil, GasPrice: miner.worker.config.GasPrice, BuilderFeeCeil: builderFeeCeil, + BidBlockEnabled: miner.bidBlockEnabled(), Version: version.Semantic, } } diff --git a/miner/miner_mev_test.go b/miner/miner_mev_test.go index abd4627099..38a0f69f23 100644 --- a/miner/miner_mev_test.go +++ b/miner/miner_mev_test.go @@ -2,6 +2,8 @@ package miner import ( "crypto/rand" + "errors" + "strings" "testing" "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" @@ -85,3 +87,22 @@ func TestStartAsyncBlobValidation_InvalidProof(t *testing.T) { t.Fatal("expected error for invalid KZG proof") } } + +func TestValidateBidBlockBlobTxs_InvalidProof(t *testing.T) { + sidecar := validBlobSidecar(1) + sidecar.Proofs[0][0] ^= 0xff + + tx := makeSignedBlobTx(0, sidecar).WithoutBlobTxSidecar() + blockSidecar := &types.BlobSidecar{ + BlobTxSidecar: *sidecar, + TxHash: tx.Hash(), + TxIndex: 0, + } + if err := validateBidBlockBlobTxs(&types.Header{}, []*types.Transaction{tx}, types.BlobSidecars{blockSidecar}, 1); err == nil { + t.Fatal("expected error for invalid BidBlock blob proof") + } else if !errors.Is(err, errInvalidBidBlockBlobTx) { + t.Fatalf("expected invalid BidBlock blob tx error, got %v", err) + } else if !strings.Contains(err.Error(), "BidBlock blob validation failed") { + t.Fatalf("unexpected error message: %v", err) + } +} diff --git a/miner/minerconfig/config.go b/miner/minerconfig/config.go index 2b530dad3e..c024c2e325 100644 --- a/miner/minerconfig/config.go +++ b/miner/minerconfig/config.go @@ -54,6 +54,9 @@ var ( defaultBuilderFeeCeil = "0" defaultValidatorCommission = uint64(100) defaultMaxBidsPerBuilder = uint32(2) // Simple strategy: send one bid early, another near deadline + // MEV validators accept SendBidBlock by default; the RPC stays gated on the + // Pasteur fork and can be disabled via Mev.BidBlockEnabled=false. + defaultBidBlockEnabled = true ) // Config is the configuration parameters of mining. @@ -97,6 +100,7 @@ type BuilderConfig struct { type MevConfig struct { Enabled *bool `toml:",omitempty"` // Whether to enable Mev or not + BidBlockEnabled *bool `toml:",omitempty"` // Whether to accept SendBidBlock RPC (BEP-675); coexists with legacy SendBid GreedyMergeTx *bool `toml:",omitempty"` // Whether to merge local transactions to the bid BuilderFeeCeil *string `toml:",omitempty"` // The maximum builder fee of a bid SentryURL string // The url of Mev sentry @@ -109,6 +113,7 @@ type MevConfig struct { var DefaultMevConfig = MevConfig{ Enabled: &defaultMevEnabled, + BidBlockEnabled: &defaultBidBlockEnabled, GreedyMergeTx: &defaultGreedyMergeTx, BuilderFeeCeil: &defaultBuilderFeeCeil, SentryURL: "", @@ -144,6 +149,10 @@ func ApplyDefaultMinerConfig(cfg *Config) { cfg.Mev.Enabled = &defaultMevEnabled log.Info("ApplyDefaultMinerConfig", "Mev.Enabled", *cfg.Mev.Enabled) } + if cfg.Mev.BidBlockEnabled == nil { + cfg.Mev.BidBlockEnabled = &defaultBidBlockEnabled + log.Info("ApplyDefaultMinerConfig", "Mev.BidBlockEnabled", *cfg.Mev.BidBlockEnabled) + } if cfg.Mev.BuilderFeeCeil == nil { cfg.Mev.BuilderFeeCeil = &defaultBuilderFeeCeil log.Info("ApplyDefaultMinerConfig", "Mev.BuilderFeeCeil", *cfg.Mev.BuilderFeeCeil) diff --git a/miner/worker.go b/miner/worker.go index 2f5d0eb660..c45fdddd48 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -77,6 +77,12 @@ var ( inturnBlocksGauge = metrics.NewRegisteredGauge("worker/inturnBlocks", nil) bestBidGasUsedGauge = metrics.NewRegisteredGauge("worker/bestBidGasUsed", nil) // MGas bestWorkGasUsedGauge = metrics.NewRegisteredGauge("worker/bestWorkGasUsed", nil) // MGas + bidBlockExistGauge = metrics.NewRegisteredGauge("worker/bidBlockExist", nil) + bidBlockCommitGauge = metrics.NewRegisteredGauge("worker/bidBlockCommit", nil) + bidBlockGasUsedGauge = metrics.NewRegisteredGauge("worker/bidBlockGasUsed", nil) // MGas + bidBlockRevokeGauge = metrics.NewRegisteredGauge("worker/bidBlockRevoke", nil) // cumulative revoke count + // bidBlockRevokedBuildersGauge snapshots how many builders are revoked, taken at each revoke. + bidBlockRevokedBuildersGauge = metrics.NewRegisteredGauge("worker/bidBlockRevokedBuilders", nil) writeBlockTimer = metrics.NewRegisteredTimer("worker/writeblock", nil) finalizeBlockTimer = metrics.NewRegisteredTimer("worker/finalizeblock", nil) @@ -128,6 +134,8 @@ type task struct { state *state.StateDB block *types.Block + bidBlockInfo *bidBlockTaskInfo + createdAt time.Time miningStartAt time.Time } @@ -178,6 +186,7 @@ type getWorkReq struct { type bidFetcher interface { GetBestBid(parentHash common.Hash) *BidRuntime GetSimulatingBid(prevBlockHash common.Hash) *BidRuntime + GetBestBidBlock(parentHash common.Hash) *types.DecodedBidBlock } // worker is the main object which takes care of submitting new work to consensus engine @@ -189,6 +198,7 @@ type worker struct { chainConfig *params.ChainConfig engine consensus.Engine eth Backend + permMgr *BidBlockPermissionManager prio []common.Address // A list of senders to prioritize chain *core.BlockChain @@ -234,7 +244,10 @@ type worker struct { resubmitHook func(time.Duration, time.Duration) // Method to call upon updating resubmitting interval. } -func newWorker(config *minerconfig.Config, engine consensus.Engine, eth Backend, mux *event.TypeMux) *worker { +func newWorker(config *minerconfig.Config, engine consensus.Engine, eth Backend, mux *event.TypeMux, permMgr *BidBlockPermissionManager) *worker { + if permMgr == nil { + permMgr = NewBidBlockPermissionManager() + } chainConfig := eth.BlockChain().Config() prefetcher := core.NewStatePrefetcher(chainConfig, eth.BlockChain().HeadChain()) if config.Mev.Enabled != nil && *config.Mev.Enabled { @@ -246,6 +259,7 @@ func newWorker(config *minerconfig.Config, engine consensus.Engine, eth Backend, chainConfig: chainConfig, engine: engine, eth: eth, + permMgr: permMgr, chain: eth.BlockChain(), mux: mux, coinbase: config.Etherbase, @@ -574,6 +588,17 @@ func (w *worker) resultLoop() { log.Error("Block found but no relative pending task", "number", block.Number(), "sealhash", sealhash, "hash", hash) continue } + + if !w.recordMinedBlock(block) { + continue + } + + // BidBlock path: broadcast first, then InsertChain for async verification + if task.bidBlockInfo != nil { + w.handleBidBlockResult(block, task) + continue + } + // Different block could share same sealhash, deep copy here to prevent write-write conflict. var ( receipts = make([]*types.Receipt, len(task.receipts)) @@ -601,27 +626,6 @@ func (w *worker) resultLoop() { logs = append(logs, receipt.Logs...) } - if prev, ok := w.recentMinedBlocks.Get(block.NumberU64()); ok { - doubleSign := false - prevParents := prev - 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 - } - prevParents = append(prevParents, block.ParentHash()) - w.recentMinedBlocks.Add(block.NumberU64(), prevParents) - } else { - // Add() will call removeOldest internally to remove the oldest element - // if the LRU Cache is full - w.recentMinedBlocks.Add(block.NumberU64(), []common.Hash{block.ParentHash()}) - } - // Commit block and state to database. start := time.Now() status, err := w.chain.WriteBlockAndSetHead(block, receipts, logs, task.state, w.mux) @@ -647,6 +651,26 @@ func (w *worker) resultLoop() { } } +// recordMinedBlock records the mined parent for this height and rejects repeat signing. +func (w *worker) recordMinedBlock(block *types.Block) bool { + if prev, ok := w.recentMinedBlocks.Get(block.NumberU64()); ok { + if slices.Contains(prev, block.ParentHash()) { + log.Error("Reject Double Sign!!", "block", block.NumberU64(), + "hash", block.Hash(), + "root", block.Root(), + "ParentHash", block.ParentHash()) + return false + } + prevParents := append(prev, block.ParentHash()) + w.recentMinedBlocks.Add(block.NumberU64(), prevParents) + } else { + // Add() will call removeOldest internally to remove the oldest element + // if the LRU Cache is full. + w.recentMinedBlocks.Add(block.NumberU64(), []common.Hash{block.ParentHash()}) + } + return true +} + // makeEnv creates a new environment for the sealing block. func (w *worker) makeEnv(parent *types.Header, header *types.Header, coinbase common.Address, prevEnv *environment, witness bool) (*environment, error) { @@ -1401,8 +1425,18 @@ LOOP: // when out-turn, use bestWork to prevent bundle leakage. // when in-turn, compare with remote work. + var bestBid *BidRuntime + var bestBidBlock *types.DecodedBidBlock + var bidBlockCommitted bool + var bidBlockFallback bool + var simBidBlockReward *uint256.Int + var simBidValidatorReward *uint256.Int + var localValidatorReward *uint256.Int if w.bidFetcher != nil && bestWork.header.Difficulty.Cmp(diffInTurn) == 0 { inturnBlocksGauge.Inc(1) + localValidatorReward = new(uint256.Int).Mul(bestReward, uint256.NewInt(*w.config.Mev.ValidatorCommission)) + localValidatorReward.Div(localValidatorReward, uint256.NewInt(10000)) + // We want to start sealing the block as late as possible here if mev is enabled, so we could give builder the chance to send their final bid. // Time left till sealing the block. tillSealingTime := time.Until(time.UnixMilli(int64(bestWork.header.MilliTimestamp()))) - *w.config.DelayLeftOver @@ -1421,44 +1455,71 @@ LOOP: } } - bestBid := w.bidFetcher.GetBestBid(bestWork.header.ParentHash) - + // Stage 1 candidate A — legacy SendBid (simBid). + bestBid = w.bidFetcher.GetBestBid(bestWork.header.ParentHash) if bestBid != nil { bidExistGauge.Inc(1) bestBidGasUsedGauge.Update(int64(bestBid.bid.GasUsed) / 1_000_000) bestWorkGasUsedGauge.Update(int64(bestWork.header.GasUsed) / 1_000_000) - - log.Debug("BidSimulator: final compare", "block", bestWork.header.Number.Uint64(), - "localBlockReward", bestReward.String(), - "bidBlockReward", bestBid.packedBlockReward.String()) + simBidBlockReward = uint256.MustFromBig(bestBid.packedBlockReward) + simBidValidatorReward = uint256.MustFromBig(bestBid.packedValidatorReward) } - if bestBid != nil && bestReward.CmpBig(bestBid.packedBlockReward) < 0 { - // localValidatorReward is the reward for the validator self by the local block. - localValidatorReward := new(uint256.Int).Mul(bestReward, uint256.NewInt(*w.config.Mev.ValidatorCommission)) - localValidatorReward.Div(localValidatorReward, uint256.NewInt(10000)) - - log.Debug("BidSimulator: final compare", "block", bestWork.header.Number.Uint64(), - "localValidatorReward", localValidatorReward.String(), - "bidValidatorReward", bestBid.packedValidatorReward.String()) + // Stage 1 candidate B — SendBidBlock. + bestBidBlock = w.bidFetcher.GetBestBidBlock(parentHash) + if bestBidBlock != nil { + bidBlockExistGauge.Inc(1) + } + } - // blockReward(benefits delegators) and validatorReward(benefits the validator) are both optimal - if localValidatorReward.CmpBig(bestBid.packedValidatorReward) < 0 { - bidWinGauge.Inc(1) - if bestBid.greedyMerged { - greedyMergeOnchainCounter.Inc(1) - } + if bestBidBlock != nil && w.selectBidBlock(bestBidBlock, simBidBlockReward, simBidValidatorReward, bestReward) { + task, err := w.prepareBidBlockTask(bestBidBlock, start) + if err != nil { + log.Error("Failed to prepare bid block, fallback", + "builder", bestBidBlock.Builder, + "err", err) + bidBlockFallback = true + } else { + systemTxCount := len(bestBidBlock.Txs) - bestBidBlock.SystemTxStart + w.enqueueBidBlockTask(task, systemTxCount) + bidBlockCommitted = true + bidBlockCommitGauge.Inc(1) + bidBlockGasUsedGauge.Update(int64(bestBidBlock.Header.GasUsed) / 1_000_000) + bestWorkGasUsedGauge.Update(int64(bestWork.header.GasUsed) / 1_000_000) + } + } - bestWork = bestBid.env + if bidBlockCommitted { + if w.current != nil { + w.current.discard() + w.current = nil + } + return + } - log.Info("[BUILDER BLOCK]", - "block", bestWork.header.Number.Uint64(), - "builder", bestBid.bid.Builder, - "blockReward", weiToEtherStringF6(bestBid.packedBlockReward), - "validatorReward", weiToEtherStringF6(bestBid.packedValidatorReward), - "bid", bestBid.bid.Hash().TerminalString(), - ) + // simBid fallback. Re-runs the legacy dual-threshold gate against simBid + // whenever no BidBlock is being committed. + if bestBid != nil { + if bestReward.Cmp(simBidBlockReward) < 0 && + localValidatorReward.Cmp(simBidValidatorReward) < 0 { + bidWinGauge.Inc(1) + if bestBid.greedyMerged { + greedyMergeOnchainCounter.Inc(1) } + bestWork = bestBid.env + // Record MEV v1 (bid path) source and builder address. + setBidMevInfo(bestWork.header, bestBid.bid.Builder, false) + logMsg := "[BUILDER BLOCK]" + if bidBlockFallback { + logMsg = "[BUILDER BLOCK] (simBid fallback)" + } + log.Info(logMsg, + "block", bestWork.header.Number.Uint64(), + "builder", bestBid.bid.Builder, + "blockReward", weiToEtherStringF6(simBidBlockReward.ToBig()), + "validatorReward", weiToEtherStringF6(simBidValidatorReward.ToBig()), + "bid", bestBid.bid.Hash().TerminalString(), + ) } } diff --git a/miner/worker_test.go b/miner/worker_test.go index e0fab878b6..e4041f6465 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -17,6 +17,7 @@ package miner // TOFIX import ( + "bytes" "math/big" "testing" "time" @@ -26,6 +27,7 @@ import ( "github.com/ethereum/go-ethereum/consensus" "github.com/ethereum/go-ethereum/consensus/clique" "github.com/ethereum/go-ethereum/consensus/ethash" + "github.com/ethereum/go-ethereum/consensus/parlia" "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/txpool" @@ -36,6 +38,7 @@ import ( "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/miner/minerconfig" "github.com/ethereum/go-ethereum/params" + "github.com/ethereum/go-ethereum/trie" "github.com/holiman/uint256" ) @@ -161,7 +164,7 @@ func (b *testWorkerBackend) newRandomTx(creation bool) *types.Transaction { func newTestWorker(t *testing.T, chainConfig *params.ChainConfig, engine consensus.Engine, db ethdb.Database, blocks int) (*worker, *testWorkerBackend) { backend := newTestWorkerBackend(t, chainConfig, engine, db, blocks) backend.txPool.Add(pendingTxs, true) - w := newWorker(testConfig, engine, backend, new(event.TypeMux)) + w := newWorker(testConfig, engine, backend, new(event.TypeMux), NewBidBlockPermissionManager()) w.setEtherbase(testBankAddress) return w, backend } @@ -210,6 +213,91 @@ func TestGenerateAndImportBlock(t *testing.T) { } } +func TestCommitBidBlockPreservesBuilderExecutionHeaderFields(t *testing.T) { + // TODO: rewrite this test with ParliaTestChainConfig + a parlia-formatted + // genesis (vanity + validator + seal) so the snapshot bootstrap inside + // SetExtraData / prepareValidators succeeds. The current TestChainConfig + // has no parlia config and the empty genesis has no validator bytes, so + // prepareBidBlockTask returns "invalid validators bytes" before any of the + // preservation assertions can run. + t.Skip("needs parlia-formatted genesis; see TODO above") + engine := parlia.New(params.TestChainConfig, rawdb.NewMemoryDatabase(), nil, common.Hash{}) + defer engine.Close() + chain, err := core.NewBlockChain(rawdb.NewMemoryDatabase(), &core.Genesis{Config: params.TestChainConfig}, ethash.NewFaker(), nil) + if err != nil { + t.Fatalf("core.NewBlockChain failed: %v", err) + } + defer chain.Stop() + w := &worker{ + chainConfig: params.TestChainConfig, + chain: chain, + engine: engine, + taskCh: make(chan *task, 1), + exitCh: make(chan struct{}), + } + w.running.Store(true) + + tx := types.NewTransaction(0, common.Address{0x1}, big.NewInt(1), params.TxGas, big.NewInt(1), nil) + receiptHash := common.Hash{0x11} + root := common.Hash{0x22} + var bloom types.Bloom + bloom[0] = 0x33 + + builderUncleHash := common.Hash{0xbb} + decoded := &types.DecodedBidBlock{ + Header: &types.Header{ + Number: big.NewInt(1), + ParentHash: chain.Genesis().Hash(), + UncleHash: builderUncleHash, + Root: root, + ReceiptHash: receiptHash, + Bloom: bloom, + GasUsed: 21000, + Extra: []byte{0xaa, 0xbb}, + }, + Txs: types.Transactions{tx}, + GasFee: big.NewInt(1), + SystemTxStart: 1, // no trailing unsigned system txs in this test + } + w.extra = []byte{0x44, 0x55} + + task, err := w.prepareBidBlockTask(decoded, time.Now()) + if err != nil { + t.Fatalf("prepareBidBlockTask failed: %v", err) + } + + block := task.block + if block.ReceiptHash() != receiptHash { + t.Fatalf("receipt hash mismatch: got %s want %s", block.ReceiptHash(), receiptHash) + } + if block.Root() != root { + t.Fatalf("root mismatch: got %s want %s", block.Root(), root) + } + if block.Bloom() != bloom { + t.Fatalf("bloom mismatch") + } + if block.GasUsed() != decoded.Header.GasUsed { + t.Fatalf("gas used mismatch: got %d want %d", block.GasUsed(), decoded.Header.GasUsed) + } + wantTxHash := types.DeriveSha(types.Transactions{tx}, trie.NewStackTrie(nil)) + if block.TxHash() != wantTxHash { + t.Fatalf("tx hash mismatch: got %s want %s", block.TxHash(), wantTxHash) + } + // Builder's UncleHash must be preserved verbatim (design principle: validator + // only computes Extra / signatures / TxHash; everything else flows from builder). + if block.UncleHash() != builderUncleHash { + t.Fatalf("uncle hash mismatch: got %s want %s", block.UncleHash(), builderUncleHash) + } + expectedHeader := types.CopyHeader(decoded.Header) + expectedHeader.Extra = common.CopyBytes(w.extra) + if err := engine.SetExtraData(chain, expectedHeader); err != nil { + t.Fatalf("SetExtraData failed: %v", err) + } + if got := block.Extra(); !bytes.Equal(got, expectedHeader.Extra) { + t.Fatalf("extra mismatch: got %x want %x", got, expectedHeader.Extra) + } +} + func TestEmptyWorkEthash(t *testing.T) { t.Parallel() testEmptyWork(t, ethashChainConfig, ethash.NewFaker()) From e5b056228dff2d5949bf02a100e2db497cfa69a9 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 17 Jun 2026 11:37:12 +0800 Subject: [PATCH 40/48] core/vm: deprecate legacy v1 Tendermint precompiles, reprice v2 light block at Pasteur (#3726) Builds on the Pasteur precompile set introduced in #3623. The legacy v1 Tendermint light-client precompiles 0x64 (tmHeaderValidate) and 0x65 (iavlMerkleProofValidate) are only reachable via the deprecated BC<->BSC cross-chain stack (contracts/deprecated/), which no longer exists. Rename the existing *Nano suspend handlers to tmHeaderValidateDeprecated / iavlMerkleProofValidateDeprecated (error "deprecated") and map 0x64/0x65 to them in the Pasteur set, deprecating them from Pasteur. For the v2 cometBFT light-client (0x67), the verification work scales with the light block's validator/signature count while the gas was flat. Price the Pasteur variant's RequiredGas per input byte (CometBFTLightBlockValidatePerByteGas) so gas tracks the real CPU/memory cost (cf. the per-key pricing of 0x66 blsSignatureVerify). The pre-Pasteur Hertz variant keeps the flat gas so earlier blocks replay identically. Note: the per-byte rate is tunable; raising 0x67 gas affects the live Greenfield/op-stack relayer gas budget and should be coordinated. Co-authored-by: Claude Opus 4.8 (1M context) --- core/vm/contracts.go | 8 ++-- core/vm/contracts_lightclient.go | 32 ++++++++------- core/vm/precompile_pasteur_test.go | 62 ++++++++++++++++++++++++++++++ params/protocol_params.go | 7 ++-- 4 files changed, 89 insertions(+), 20 deletions(-) create mode 100644 core/vm/precompile_pasteur_test.go diff --git a/core/vm/contracts.go b/core/vm/contracts.go index 0730876fff..e132467a4e 100644 --- a/core/vm/contracts.go +++ b/core/vm/contracts.go @@ -112,8 +112,8 @@ var PrecompiledContractsNano = PrecompiledContracts{ common.BytesToAddress([]byte{0x8}): &bn256PairingIstanbul{}, common.BytesToAddress([]byte{0x9}): &blake2F{}, - common.BytesToAddress([]byte{0x64}): &tmHeaderValidateNano{}, - common.BytesToAddress([]byte{0x65}): &iavlMerkleProofValidateNano{}, + common.BytesToAddress([]byte{0x64}): &tmHeaderValidateDeprecated{}, + common.BytesToAddress([]byte{0x65}): &iavlMerkleProofValidateDeprecated{}, } var PrecompiledContractsMoran = PrecompiledContracts{ @@ -371,8 +371,8 @@ var PrecompiledContractsPasteur = PrecompiledContracts{ common.BytesToAddress([]byte{0x10}): &bls12381MapG1{}, common.BytesToAddress([]byte{0x11}): &bls12381MapG2{}, - common.BytesToAddress([]byte{0x64}): &tmHeaderValidate{}, - common.BytesToAddress([]byte{0x65}): &iavlMerkleProofValidatePlato{}, + common.BytesToAddress([]byte{0x64}): &tmHeaderValidateDeprecated{}, + common.BytesToAddress([]byte{0x65}): &iavlMerkleProofValidateDeprecated{}, common.BytesToAddress([]byte{0x66}): &blsSignatureVerify{}, common.BytesToAddress([]byte{0x67}): &cometBFTLightBlockValidatePasteur{}, common.BytesToAddress([]byte{0x68}): &verifyDoubleSignEvidence{}, diff --git a/core/vm/contracts_lightclient.go b/core/vm/contracts_lightclient.go index 4eefcf6731..9290b818b6 100644 --- a/core/vm/contracts_lightclient.go +++ b/core/vm/contracts_lightclient.go @@ -134,33 +134,34 @@ func (c *iavlMerkleProofValidate) Name() string { return "IAVL_MERKLE_PROOF_VALIDATE" } -// tmHeaderValidateNano implemented as a native contract. -type tmHeaderValidateNano struct{} +// tmHeaderValidateDeprecated implemented as a native contract that disables the +// legacy v1 Tendermint header-validate precompile (returns an error for any input). +type tmHeaderValidateDeprecated struct{} -func (c *tmHeaderValidateNano) RequiredGas(input []byte) uint64 { +func (c *tmHeaderValidateDeprecated) RequiredGas(input []byte) uint64 { return params.TendermintHeaderValidateGas } -func (c *tmHeaderValidateNano) Run(input []byte) (result []byte, err error) { - return nil, errors.New("suspend") +func (c *tmHeaderValidateDeprecated) Run(input []byte) (result []byte, err error) { + return nil, errors.New("deprecated") } -func (c *tmHeaderValidateNano) Name() string { - return "HEADER_VALIDATE_NANO" +func (c *tmHeaderValidateDeprecated) Name() string { + return "HEADER_VALIDATE_DEPRECATED" } -type iavlMerkleProofValidateNano struct{} +type iavlMerkleProofValidateDeprecated struct{} -func (c *iavlMerkleProofValidateNano) RequiredGas(_ []byte) uint64 { +func (c *iavlMerkleProofValidateDeprecated) RequiredGas(_ []byte) uint64 { return params.IAVLMerkleProofValidateGas } -func (c *iavlMerkleProofValidateNano) Run(_ []byte) (result []byte, err error) { - return nil, errors.New("suspend") +func (c *iavlMerkleProofValidateDeprecated) Run(_ []byte) (result []byte, err error) { + return nil, errors.New("deprecated") } -func (c *iavlMerkleProofValidateNano) Name() string { - return "IAVL_MERKLE_PROOF_VALIDATE_NANO" +func (c *iavlMerkleProofValidateDeprecated) Name() string { + return "IAVL_MERKLE_PROOF_VALIDATE_DEPRECATED" } // ------------------------------------------------------------------------------------------------------------------------------------------------ @@ -446,6 +447,11 @@ type cometBFTLightBlockValidatePasteur struct { cometBFTLightBlockValidate } +// Price per input byte so cost scales with the validator/signature count. +func (c *cometBFTLightBlockValidatePasteur) RequiredGas(input []byte) uint64 { + return params.CometBFTLightBlockValidateGas + uint64(len(input))*params.CometBFTLightBlockValidatePerByteGas +} + func (c *cometBFTLightBlockValidatePasteur) Run(input []byte) (result []byte, err error) { return c.run(input, true, true) } diff --git a/core/vm/precompile_pasteur_test.go b/core/vm/precompile_pasteur_test.go new file mode 100644 index 0000000000..eed827c08d --- /dev/null +++ b/core/vm/precompile_pasteur_test.go @@ -0,0 +1,62 @@ +package vm + +import ( + "testing" + + "github.com/ethereum/go-ethereum/common" +) + +// 0x64/0x65 are deprecated from Pasteur; 0x67 switches to a per-byte-priced variant. +func TestPasteurSuspendsLegacyTendermintPrecompiles(t *testing.T) { + addr64 := common.BytesToAddress([]byte{0x64}) + addr65 := common.BytesToAddress([]byte{0x65}) + + // Under Pasteur, 0x64/0x65 return "deprecated" for any input. + for _, addr := range []common.Address{addr64, addr65} { + p := PrecompiledContractsPasteur[addr] + if p == nil { + t.Fatalf("%s missing from Pasteur precompile set", addr.Hex()) + } + if _, err := p.Run([]byte("x")); err == nil || err.Error() != "deprecated" { + t.Fatalf("%s under Pasteur: expected deprecated error, got %v", addr.Hex(), err) + } + } + + // Pre-Pasteur (Osaka) they are still the live, active implementations. + if _, ok := PrecompiledContractsOsaka[addr64].(*tmHeaderValidate); !ok { + t.Fatalf("0x64 must remain active (tmHeaderValidate) pre-Pasteur") + } + if _, ok := PrecompiledContractsOsaka[addr65].(*iavlMerkleProofValidatePlato); !ok { + t.Fatalf("0x65 must remain active (iavlMerkleProofValidatePlato) pre-Pasteur") + } + + // 0x67 stays active but switches to the per-byte-priced Pasteur variant + // (Hertz/flat-gas pre-Pasteur, for replay of earlier blocks). + addr67 := common.BytesToAddress([]byte{0x67}) + if _, ok := PrecompiledContractsPasteur[addr67].(*cometBFTLightBlockValidatePasteur); !ok { + t.Fatalf("0x67 must be the Pasteur variant under Pasteur") + } + if _, ok := PrecompiledContractsOsaka[addr67].(*cometBFTLightBlockValidateHertz); !ok { + t.Fatalf("0x67 must remain the Hertz variant pre-Pasteur") + } + + // The still-needed precompiles (0x66, 0x68, 0x69) remain present under Pasteur. + for _, b := range []byte{0x66, 0x68, 0x69} { + addr := common.BytesToAddress([]byte{b}) + if PrecompiledContractsPasteur[addr] == nil { + t.Fatalf("%s must remain present under Pasteur", addr.Hex()) + } + } + + // 0x67 gas scales with input size under Pasteur, but is flat pre-Pasteur. + small := make([]byte, 1024) + large := make([]byte, 16*1024) + pasteur67 := PrecompiledContractsPasteur[addr67] + if pasteur67.RequiredGas(large) <= pasteur67.RequiredGas(small) { + t.Fatalf("Pasteur 0x67 gas must scale with input size") + } + osaka67 := PrecompiledContractsOsaka[addr67] + if osaka67.RequiredGas(large) != osaka67.RequiredGas(small) { + t.Fatalf("pre-Pasteur 0x67 gas must stay flat") + } +} diff --git a/params/protocol_params.go b/params/protocol_params.go index d41af34e81..a5311e934c 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -143,9 +143,10 @@ const ( // Precompiled contract gas prices - TendermintHeaderValidateGas uint64 = 3000 // Gas for validate tendermiint consensus state - IAVLMerkleProofValidateGas uint64 = 3000 // Gas for validate merkle proof - CometBFTLightBlockValidateGas uint64 = 3000 // Gas for validate cometBFT light block + TendermintHeaderValidateGas uint64 = 3000 // Gas for validate tendermiint consensus state + IAVLMerkleProofValidateGas uint64 = 3000 // Gas for validate merkle proof + CometBFTLightBlockValidateGas uint64 = 3000 // Base gas for validate cometBFT light block + CometBFTLightBlockValidatePerByteGas uint64 = 16 // Per-input-byte gas for cometBFT light block (Pasteur) EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation From a66424f7e5de6dcbd51cbaeba2dcf846e5490b79 Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 17 Jun 2026 12:22:08 +0800 Subject: [PATCH 41/48] core/systemcontracts: point Pasteur CommitUrl to genesis-contract v1.2.6 (#3727) Update the Pasteur upgrade CommitUrl for StakeHub (0x2002) and BSCGovernor (0x2004) from the interim commit 3f02a2e to the tagged release v1.2.6 (commit 041881a02475638b19f3d840871b7621cdebd8f8). The embedded bytecode is unchanged: verified the StakeHub/Governor code for Mainnet/Chapel/Rialto matches the v1.2.6 genesis byte-for-byte, so this only corrects the provenance reference to the official release tag. Co-authored-by: Claude Opus 4.8 (1M context) --- core/systemcontracts/upgrade.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go index 49f1dd645b..825c15a2dc 100644 --- a/core/systemcontracts/upgrade.go +++ b/core/systemcontracts/upgrade.go @@ -1064,12 +1064,12 @@ func init() { Configs: []*UpgradeConfig{ { ContractAddr: common.HexToAddress(StakeHubContract), - CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/041881a02475638b19f3d840871b7621cdebd8f8", Code: pasteur.MainnetStakeHubContract, }, { ContractAddr: common.HexToAddress(GovernorContract), - CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/041881a02475638b19f3d840871b7621cdebd8f8", Code: pasteur.MainnetGovernorContract, }, }, @@ -1080,12 +1080,12 @@ func init() { Configs: []*UpgradeConfig{ { ContractAddr: common.HexToAddress(StakeHubContract), - CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/041881a02475638b19f3d840871b7621cdebd8f8", Code: pasteur.ChapelStakeHubContract, }, { ContractAddr: common.HexToAddress(GovernorContract), - CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/041881a02475638b19f3d840871b7621cdebd8f8", Code: pasteur.ChapelGovernorContract, }, }, @@ -1096,12 +1096,12 @@ func init() { Configs: []*UpgradeConfig{ { ContractAddr: common.HexToAddress(StakeHubContract), - CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/041881a02475638b19f3d840871b7621cdebd8f8", Code: pasteur.RialtoStakeHubContract, }, { ContractAddr: common.HexToAddress(GovernorContract), - CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/3f02a2e834308eb989ea230cd3b90ea8c47e6699", + CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/041881a02475638b19f3d840871b7621cdebd8f8", Code: pasteur.RialtoGovernorContract, }, }, From 7bd352703cc5383a310067ee2a4c29fe39de8cad Mon Sep 17 00:00:00 2001 From: Eric <45141191+zlacfzy@users.noreply.github.com> Date: Wed, 17 Jun 2026 15:30:01 +0800 Subject: [PATCH 42/48] beacon, cmd: remove fake-beacon op-stack shim (revert #2678) (#3728) The fake-beacon service (#2678) is an internal-only op-stack blob/DA shim, off by default and bound to localhost. Its block-number lookup (fetchBlockNumberByTime) has an unbounded retry loop with no lower bound and no ctx cancellation, plus an inner nil-header dereference, so an operator who enables and exposes it can leak handler goroutines (SRC-2026-1000). Rather than patch an auxiliary, default-off feature, the service is removed entirely. Removes the beacon/fakebeacon package and its --fake-beacon[.addr|.port] flags and startup wiring in cmd/geth and cmd/utils. Co-authored-by: Claude Opus 4.8 (1M context) --- beacon/fakebeacon/api_func.go | 87 ---------------------------- beacon/fakebeacon/handlers.go | 89 ----------------------------- beacon/fakebeacon/server.go | 97 -------------------------------- beacon/fakebeacon/server_test.go | 90 ----------------------------- beacon/fakebeacon/utils.go | 65 --------------------- cmd/geth/config.go | 20 ++----- cmd/geth/main.go | 7 --- cmd/utils/flags.go | 20 ------- go.mod | 1 - go.sum | 2 - 10 files changed, 4 insertions(+), 474 deletions(-) delete mode 100644 beacon/fakebeacon/api_func.go delete mode 100644 beacon/fakebeacon/handlers.go delete mode 100644 beacon/fakebeacon/server.go delete mode 100644 beacon/fakebeacon/server_test.go delete mode 100644 beacon/fakebeacon/utils.go diff --git a/beacon/fakebeacon/api_func.go b/beacon/fakebeacon/api_func.go deleted file mode 100644 index 674bf7fb39..0000000000 --- a/beacon/fakebeacon/api_func.go +++ /dev/null @@ -1,87 +0,0 @@ -package fakebeacon - -import ( - "context" - "sort" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto/kzg4844" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/rpc" -) - -type BlobSidecar struct { - Blob kzg4844.Blob `json:"blob"` - Index int `json:"index"` - KZGCommitment kzg4844.Commitment `json:"kzg_commitment"` - KZGProof kzg4844.Proof `json:"kzg_proof"` -} - -type APIGetBlobSidecarsResponse struct { - Data []*BlobSidecar `json:"data"` -} - -type ReducedGenesisData struct { - GenesisTime string `json:"genesis_time"` -} - -type APIGenesisResponse struct { - Data ReducedGenesisData `json:"data"` -} - -type ReducedConfigData struct { - SecondsPerSlot string `json:"SECONDS_PER_SLOT"` -} - -type IndexedBlobHash struct { - Index int // absolute index in the block, a.k.a. position in sidecar blobs array - Hash common.Hash // hash of the blob, used for consistency checks -} - -func configSpec() ReducedConfigData { - return ReducedConfigData{SecondsPerSlot: "1"} -} - -func beaconGenesis() APIGenesisResponse { - return APIGenesisResponse{Data: ReducedGenesisData{GenesisTime: "0"}} -} - -func beaconBlobSidecars(ctx context.Context, backend ethapi.Backend, slot uint64, indices []int) (APIGetBlobSidecarsResponse, error) { - var blockNrOrHash rpc.BlockNumberOrHash - header, err := fetchBlockNumberByTime(ctx, int64(slot), backend) - if err != nil { - log.Error("Error fetching block number", "slot", slot, "indices", indices) - return APIGetBlobSidecarsResponse{}, err - } - sideCars, err := backend.GetBlobSidecars(ctx, header.Hash()) - if err != nil { - log.Error("Error fetching Sidecars", "blockNrOrHash", blockNrOrHash, "err", err) - return APIGetBlobSidecarsResponse{}, err - } - sort.Ints(indices) - fullBlob := len(indices) == 0 - res := APIGetBlobSidecarsResponse{} - idx := 0 - curIdx := 0 - for _, sideCar := range sideCars { - for i := 0; i < len(sideCar.Blobs); i++ { - //hash := kZGToVersionedHash(sideCar.Commitments[i]) - if !fullBlob && curIdx >= len(indices) { - break - } - if fullBlob || idx == indices[curIdx] { - res.Data = append(res.Data, &BlobSidecar{ - Index: idx, - Blob: sideCar.Blobs[i], - KZGCommitment: sideCar.Commitments[i], - KZGProof: sideCar.Proofs[i], - }) - curIdx++ - } - idx++ - } - } - - return res, nil -} diff --git a/beacon/fakebeacon/handlers.go b/beacon/fakebeacon/handlers.go deleted file mode 100644 index 53af5aad29..0000000000 --- a/beacon/fakebeacon/handlers.go +++ /dev/null @@ -1,89 +0,0 @@ -package fakebeacon - -import ( - "fmt" - "net/http" - "net/url" - "strconv" - "strings" - - "github.com/prysmaticlabs/prysm/v5/api/server/structs" - "github.com/prysmaticlabs/prysm/v5/network/httputil" -) - -const MaxBlobsPerBlock = 6 - -var ( - versionMethod = "/eth/v1/node/version" - specMethod = "/eth/v1/config/spec" - genesisMethod = "/eth/v1/beacon/genesis" - sidecarsMethodPrefix = "/eth/v1/beacon/blob_sidecars/{slot}" -) - -func VersionMethod(w http.ResponseWriter, r *http.Request) { - resp := &structs.GetVersionResponse{ - Data: &structs.Version{ - Version: "", - }, - } - httputil.WriteJson(w, resp) -} - -func SpecMethod(w http.ResponseWriter, r *http.Request) { - httputil.WriteJson(w, &structs.GetSpecResponse{Data: configSpec()}) -} - -func GenesisMethod(w http.ResponseWriter, r *http.Request) { - httputil.WriteJson(w, beaconGenesis()) -} - -func (s *Service) SidecarsMethod(w http.ResponseWriter, r *http.Request) { - indices, err := parseIndices(r.URL) - if err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - segments := strings.Split(r.URL.Path, "/") - slot, err := strconv.ParseUint(segments[len(segments)-1], 10, 64) - if err != nil { - httputil.HandleError(w, "not a valid slot(timestamp)", http.StatusBadRequest) - return - } - - resp, err := beaconBlobSidecars(r.Context(), s.backend, slot, indices) - if err != nil { - httputil.HandleError(w, err.Error(), http.StatusBadRequest) - return - } - httputil.WriteJson(w, resp) -} - -// parseIndices filters out invalid and duplicate blob indices -func parseIndices(url *url.URL) ([]int, error) { - rawIndices := url.Query()["indices"] - indices := make([]int, 0, MaxBlobsPerBlock) - invalidIndices := make([]string, 0) -loop: - for _, raw := range rawIndices { - ix, err := strconv.Atoi(raw) - if err != nil { - invalidIndices = append(invalidIndices, raw) - continue - } - if ix >= MaxBlobsPerBlock { - invalidIndices = append(invalidIndices, raw) - continue - } - for i := range indices { - if ix == indices[i] { - continue loop - } - } - indices = append(indices, ix) - } - - if len(invalidIndices) > 0 { - return nil, fmt.Errorf("requested blob indices %v are invalid", invalidIndices) - } - return indices, nil -} diff --git a/beacon/fakebeacon/server.go b/beacon/fakebeacon/server.go deleted file mode 100644 index ef5cb6af9b..0000000000 --- a/beacon/fakebeacon/server.go +++ /dev/null @@ -1,97 +0,0 @@ -package fakebeacon - -import ( - "net/http" - "strconv" - - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/gorilla/mux" - "github.com/prysmaticlabs/prysm/v5/api/server/middleware" -) - -const ( - DefaultAddr = "localhost" - DefaultPort = 8686 -) - -type Config struct { - Enable bool - Addr string - Port int -} - -func defaultConfig() *Config { - return &Config{ - Enable: false, - Addr: DefaultAddr, - Port: DefaultPort, - } -} - -type Service struct { - cfg *Config - router *mux.Router - backend ethapi.Backend -} - -func NewService(cfg *Config, backend ethapi.Backend) *Service { - cfgs := defaultConfig() - if cfg.Addr != "" { - cfgs.Addr = cfg.Addr - } - if cfg.Port > 0 { - cfgs.Port = cfg.Port - } - - s := &Service{ - cfg: cfgs, - backend: backend, - } - router := s.newRouter() - s.router = router - return s -} - -func (s *Service) Run() { - _ = http.ListenAndServe(s.cfg.Addr+":"+strconv.Itoa(s.cfg.Port), s.router) -} - -func (s *Service) newRouter() *mux.Router { - r := mux.NewRouter() - r.Use(middleware.NormalizeQueryValuesHandler) - for _, e := range s.endpoints() { - r.HandleFunc(e.path, e.handler).Methods(e.methods...) - } - return r -} - -type endpoint struct { - path string - handler http.HandlerFunc - methods []string -} - -func (s *Service) endpoints() []endpoint { - return []endpoint{ - { - path: versionMethod, - handler: VersionMethod, - methods: []string{http.MethodGet}, - }, - { - path: specMethod, - handler: SpecMethod, - methods: []string{http.MethodGet}, - }, - { - path: genesisMethod, - handler: GenesisMethod, - methods: []string{http.MethodGet}, - }, - { - path: sidecarsMethodPrefix, - handler: s.SidecarsMethod, - methods: []string{http.MethodGet}, - }, - } -} diff --git a/beacon/fakebeacon/server_test.go b/beacon/fakebeacon/server_test.go deleted file mode 100644 index 0b74f565ba..0000000000 --- a/beacon/fakebeacon/server_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package fakebeacon - -import ( - "context" - "fmt" - "strconv" - "testing" - - "github.com/stretchr/testify/assert" -) - -// -//func TestFetchBlockNumberByTime(t *testing.T) { -// blockNum, err := fetchBlockNumberByTime(context.Background(), 1724052941, client) -// assert.Nil(t, err) -// assert.Equal(t, uint64(41493946), blockNum) -// -// blockNum, err = fetchBlockNumberByTime(context.Background(), 1734052941, client) -// assert.Equal(t, err, errors.New("time too large")) -// -// blockNum, err = fetchBlockNumberByTime(context.Background(), 1600153618, client) -// assert.Nil(t, err) -// assert.Equal(t, uint64(493946), blockNum) -//} -// -//func TestBeaconBlobSidecars(t *testing.T) { -// indexBlobHash := []IndexedBlobHash{ -// {Hash: common.HexToHash("0x01231952ecbaede62f8d0398b656072c072db36982c9ef106fbbc39ce14f983c"), Index: 0}, -// {Hash: common.HexToHash("0x012c21a8284d2d707bb5318e874d2e1b97a53d028e96abb702b284a2cbb0f79c"), Index: 1}, -// {Hash: common.HexToHash("0x011196c8d02536ede0382aa6e9fdba6c460169c0711b5f97fcd701bd8997aee3"), Index: 2}, -// {Hash: common.HexToHash("0x019c86b46b27401fb978fd175d1eb7dadf4976d6919501b0c5280d13a5bab57b"), Index: 3}, -// {Hash: common.HexToHash("0x01e00db7ee99176b3fd50aab45b4fae953292334bbf013707aac58c455d98596"), Index: 4}, -// {Hash: common.HexToHash("0x0117d23b68123d578a98b3e1aa029661e0abda821a98444c21992eb1e5b7208f"), Index: 5}, -// //{Hash: common.HexToHash("0x01e00db7ee99176b3fd50aab45b4fae953292334bbf013707aac58c455d98596"), Index: 1}, -// } -// -// resp, err := beaconBlobSidecars(context.Background(), 1724055046, []int{0, 1, 2, 3, 4, 5}) // block: 41494647 -// assert.Nil(t, err) -// assert.NotNil(t, resp) -// assert.NotEmpty(t, resp.Data) -// for i, sideCar := range resp.Data { -// assert.Equal(t, indexBlobHash[i].Index, sideCar.Index) -// assert.Equal(t, indexBlobHash[i].Hash, kZGToVersionedHash(sideCar.KZGCommitment)) -// } -// -// apiscs := make([]*BlobSidecar, 0, len(indexBlobHash)) -// // filter and order by hashes -// for _, h := range indexBlobHash { -// for _, apisc := range resp.Data { -// if h.Index == int(apisc.Index) { -// apiscs = append(apiscs, apisc) -// break -// } -// } -// } -// -// assert.Equal(t, len(apiscs), len(resp.Data)) -// assert.Equal(t, len(apiscs), len(indexBlobHash)) -//} - -type TimeToSlotFn func(timestamp uint64) (uint64, error) - -// GetTimeToSlotFn returns a function that converts a timestamp to a slot number. -func GetTimeToSlotFn(ctx context.Context) (TimeToSlotFn, error) { - genesis := beaconGenesis() - config := configSpec() - - genesisTime, _ := strconv.ParseUint(genesis.Data.GenesisTime, 10, 64) - secondsPerSlot, _ := strconv.ParseUint(config.SecondsPerSlot, 10, 64) - if secondsPerSlot == 0 { - return nil, fmt.Errorf("got bad value for seconds per slot: %v", config.SecondsPerSlot) - } - timeToSlotFn := func(timestamp uint64) (uint64, error) { - if timestamp < genesisTime { - return 0, fmt.Errorf("provided timestamp (%v) precedes genesis time (%v)", timestamp, genesisTime) - } - return (timestamp - genesisTime) / secondsPerSlot, nil - } - return timeToSlotFn, nil -} - -func TestAPI(t *testing.T) { - slotFn, err := GetTimeToSlotFn(context.Background()) - assert.Nil(t, err) - - expTx := uint64(123151345) - gotTx, err := slotFn(expTx) - assert.Nil(t, err) - assert.Equal(t, expTx, gotTx) -} diff --git a/beacon/fakebeacon/utils.go b/beacon/fakebeacon/utils.go deleted file mode 100644 index cc6fe889b9..0000000000 --- a/beacon/fakebeacon/utils.go +++ /dev/null @@ -1,65 +0,0 @@ -package fakebeacon - -import ( - "context" - "errors" - "fmt" - "math/rand" - "time" - - "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/internal/ethapi" - "github.com/ethereum/go-ethereum/rpc" -) - -func fetchBlockNumberByTime(ctx context.Context, ts int64, backend ethapi.Backend) (*types.Header, error) { - // calc the block number of the ts. - currentHeader := backend.CurrentHeader() - blockTime := int64(currentHeader.Time) - if ts > blockTime { - return nil, errors.New("time too large") - } - blockNum := currentHeader.Number.Uint64() - estimateEndNumber := int64(blockNum) - (blockTime-ts)/3 - // find the end number - for { - header, err := backend.HeaderByNumber(ctx, rpc.BlockNumber(estimateEndNumber)) - if err != nil { - time.Sleep(time.Duration(rand.Int()%180) * time.Millisecond) - continue - } - if header == nil { - estimateEndNumber -= 1 - time.Sleep(time.Duration(rand.Int()%180) * time.Millisecond) - continue - } - headerTime := int64(header.Time) - if headerTime == ts { - return header, nil - } - - // let the estimateEndNumber a little bigger than real value - if headerTime > ts+8 { - estimateEndNumber -= (headerTime - ts) / 3 - } else if headerTime < ts { - estimateEndNumber += (ts-headerTime)/3 + 1 - } else { - // search one by one - for headerTime >= ts { - header, err = backend.HeaderByNumber(ctx, rpc.BlockNumber(estimateEndNumber-1)) - if err != nil { - time.Sleep(time.Duration(rand.Int()%180) * time.Millisecond) - continue - } - headerTime = int64(header.Time) - if headerTime == ts { - return header, nil - } - estimateEndNumber -= 1 - if headerTime < ts { //found the real endNumber - return nil, fmt.Errorf("block not found by time %d", ts) - } - } - } - } -} diff --git a/cmd/geth/config.go b/cmd/geth/config.go index ccb42022ca..3361a5216e 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -35,7 +35,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/accounts/scwallet" "github.com/ethereum/go-ethereum/accounts/usbwallet" - "github.com/ethereum/go-ethereum/beacon/fakebeacon" "github.com/ethereum/go-ethereum/cmd/utils" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/rawdb" @@ -110,11 +109,10 @@ type ethstatsConfig struct { } type gethConfig struct { - Eth ethconfig.Config - Node node.Config - Ethstats ethstatsConfig - Metrics metrics.Config - FakeBeacon fakebeacon.Config + Eth ethconfig.Config + Node node.Config + Ethstats ethstatsConfig + Metrics metrics.Config } func loadConfig(file string, cfg *gethConfig) error { @@ -356,16 +354,6 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { } } - if ctx.IsSet(utils.FakeBeaconAddrFlag.Name) { - cfg.FakeBeacon.Addr = ctx.String(utils.FakeBeaconAddrFlag.Name) - } - if ctx.IsSet(utils.FakeBeaconPortFlag.Name) { - cfg.FakeBeacon.Port = ctx.Int(utils.FakeBeaconPortFlag.Name) - } - if cfg.FakeBeacon.Enable || ctx.IsSet(utils.FakeBeaconEnabledFlag.Name) { - go fakebeacon.NewService(&cfg.FakeBeacon, backend).Run() - } - git, _ := version.VCS() utils.SetupMetrics(&cfg.Metrics, utils.EnableBuildInfo(git.Commit, git.Date), diff --git a/cmd/geth/main.go b/cmd/geth/main.go index ee58f8245c..9834460db2 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -259,12 +259,6 @@ var ( utils.MetricsInfluxDBOrganizationFlag, utils.StateSizeTrackingFlag, } - - fakeBeaconFlags = []cli.Flag{ - utils.FakeBeaconEnabledFlag, - utils.FakeBeaconAddrFlag, - utils.FakeBeaconPortFlag, - } ) var app = flags.NewApp("the go-ethereum command line interface") @@ -321,7 +315,6 @@ func init() { consoleFlags, debug.Flags, metricsFlags, - fakeBeaconFlags, ) flags.AutoEnvVars(app.Flags, "GETH") diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index fc8230785f..be4cd15962 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -37,7 +37,6 @@ import ( "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/keystore" - "github.com/ethereum/go-ethereum/beacon/fakebeacon" bparams "github.com/ethereum/go-ethereum/beacon/params" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/fdlimit" @@ -1304,25 +1303,6 @@ Please note that --` + MetricsHTTPFlag.Name + ` must be set to start the server. Category: flags.MiscCategory, } - // Fake beacon - FakeBeaconEnabledFlag = &cli.BoolFlag{ - Name: "fake-beacon", - Usage: "Enable the HTTP-RPC server of fake-beacon", - Category: flags.APICategory, - } - FakeBeaconAddrFlag = &cli.StringFlag{ - Name: "fake-beacon.addr", - Usage: "HTTP-RPC server listening addr of fake-beacon", - Value: fakebeacon.DefaultAddr, - Category: flags.APICategory, - } - FakeBeaconPortFlag = &cli.IntFlag{ - Name: "fake-beacon.port", - Usage: "HTTP-RPC server listening port of fake-beacon", - Value: fakebeacon.DefaultPort, - Category: flags.APICategory, - } - // incremental snapshot related flags EnableIncrSnapshotFlag = &cli.BoolFlag{ Name: "incr.enable", diff --git a/go.mod b/go.mod index ef9300801b..42b193e8a7 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,6 @@ require ( github.com/google/gofuzz v1.2.0 github.com/google/pprof v0.0.0-20241210010833-40e02aabc2ad github.com/google/uuid v1.6.0 - github.com/gorilla/mux v1.8.1 github.com/gorilla/websocket v1.5.3 github.com/graph-gophers/graphql-go v1.3.0 github.com/hashicorp/go-bexpr v0.1.10 diff --git a/go.sum b/go.sum index ace9c6596e..1234ce693a 100644 --- a/go.sum +++ b/go.sum @@ -513,8 +513,6 @@ github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51 github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= -github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= -github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= From 86359cf9aa33fdcca137fb21961bb98097eeee55 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Wed, 17 Jun 2026 16:05:06 +0800 Subject: [PATCH 43/48] release: prepare for release v1.7.4 (#3729) --- CHANGELOG.md | 88 ++++++++++++++++++++++++++++++++++++++++++++++ version/version.go | 2 +- 2 files changed, 89 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d46d2b7730..4e657ad063 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,92 @@ # Changelog +## v1.7.4 +v1.7.4 is for BSC Chapel testnet [Pasteur hardfork](https://github.com/bnb-chain/BEPs/blob/master/BEPs/BEP-673.md),the hard fork time is 2026-07-XX 02:30:00 AM UTC + +### Pasteur Hardfork +- [\#3623](https://github.com/bnb-chain/bsc/pull/3623) core/vm: reject duplicate bridge validators at Pasteur +- [\#3691](https://github.com/bnb-chain/bsc/pull/3691) miner: support builder-proposed block with validator blind signing +- [\#3717](https://github.com/bnb-chain/bsc/pull/3717) params: move Pasteur next to Mendel +- [\#3721](https://github.com/bnb-chain/bsc/pull/3721) core/systemcontracts: introduce Pasteur hardfork system-contract upgrade +- [\#3727](https://github.com/bnb-chain/bsc/pull/3727) core/systemcontracts: point Pasteur CommitUrl to genesis-contract v1.2.6 + +### BUGFIX +- [\#3668](https://github.com/bnb-chain/bsc/pull/3668) eth/handler.go: add verify bal +- [\#3671](https://github.com/bnb-chain/bsc/pull/3671) eth/protocols/bsc: cap GetBlocksByRange response size +- [\#3672](https://github.com/bnb-chain/bsc/pull/3672) eth/protocols/bsc: rate-limit incoming votes by vote count +- [\#3680](https://github.com/bnb-chain/bsc/pull/3680) internal/ethapi: limit number of getProofs keys +- [\#3681](https://github.com/bnb-chain/bsc/pull/3681) internal/ethapi: limit number of calls to eth_simulateV1 +- [\#3682](https://github.com/bnb-chain/bsc/pull/3682) internal/ethapi: fix gas cap for eth_simulateV1 +- [\#3683](https://github.com/bnb-chain/bsc/pull/3683) core: fix txLookupLock mutex leak on error returns in reorg() +- [\#3684](https://github.com/bnb-chain/bsc/pull/3684) cmd, core, eth, tests: prevent state flushing in RPC +- [\#3685](https://github.com/bnb-chain/bsc/pull/3685) core/tracing: fix nonce revert edge case +- [\#3686](https://github.com/bnb-chain/bsc/pull/3686) eth/filters: fix race in pending tx and new heads subscriptions +- [\#3687](https://github.com/bnb-chain/bsc/pull/3687) core, internal/ethapi: fix incorrect max-initcode RPC error mapping +- [\#3688](https://github.com/bnb-chain/bsc/pull/3688) eth/filters: rangeLogs should error on invalid block range +- [\#3689](https://github.com/bnb-chain/bsc/pull/3689) eth/filters: fix race in NewVotes and NewFinalizedHeaders +- [\#3692](https://github.com/bnb-chain/bsc/pull/3692) eth/filters: fix source leak when New Filters +- [\#3700](https://github.com/bnb-chain/bsc/pull/3700) crypto: add hash length check in nocgo VerifySignature +- [\#3701](https://github.com/bnb-chain/bsc/pull/3701) p2p/discover: copy buffer before sending read errors to unhandled +- [\#3702](https://github.com/bnb-chain/bsc/pull/3702) p2p/discover: fix timeout loop early exit when removing expired matchers +- [\#3703](https://github.com/bnb-chain/bsc/pull/3703) eth/tracers/logger: fix exclude address list +- [\#3705](https://github.com/bnb-chain/bsc/pull/3705) eth/protocols/eth: stop serving on unavailable responses +- [\#3706](https://github.com/bnb-chain/bsc/pull/3706) triedb/pathdb: fix lookup sentinel collision with zero disk layer root +- [\#3707](https://github.com/bnb-chain/bsc/pull/3707) eth/tracers: forward OnSystemCall hooks through mux +- [\#3708](https://github.com/bnb-chain/bsc/pull/3708) eth/downloader: drop invalid peers + fix deliver index +- [\#3709](https://github.com/bnb-chain/bsc/pull/3709) core/state: fix StateDB Reader error discarded after Commit +- [\#3710](https://github.com/bnb-chain/bsc/pull/3710) p2p/discover: decouple nodeFeed from Table mutex in waitForNodes +- [\#3711](https://github.com/bnb-chain/bsc/pull/3711) core/rawdb: fix file descriptor leak in freezer error paths +- [\#3712](https://github.com/bnb-chain/bsc/pull/3712) core/rawdb: fsync temp file before rename in copyFrom +- [\#3718](https://github.com/bnb-chain/bsc/pull/3718) fix: nocgo sigToPub hash check + pathdb zero-base regression test + +### IMPROVEMENT +- [\#3669](https://github.com/bnb-chain/bsc/pull/3669) miner: reduce local mining time for last block in one turn +- [\#3694](https://github.com/bnb-chain/bsc/pull/3694) consensus/parlia: extract VerifyUnsealedHeader from verifyHeader + +### CLEAN UP +- [\#3670](https://github.com/bnb-chain/bsc/pull/3670) triedb/pathdb: remove legacy field JournalFilePath +- [\#3678](https://github.com/bnb-chain/bsc/pull/3678) miner: remove optional transaction gas limit cap +- [\#3690](https://github.com/bnb-chain/bsc/pull/3690) all: remove BEP-592 non-consensus block access list +- [\#3716](https://github.com/bnb-chain/bsc/pull/3716) ethdb,trie: remove multidb code from bsc +- [\#3720](https://github.com/bnb-chain/bsc/pull/3720) core/rawdb: cleanup bep-592 bal key related +- [\#3722](https://github.com/bnb-chain/bsc/pull/3722) core/txpool/legacypool: remove overflowpool for txs +- [\#3728](https://github.com/bnb-chain/bsc/pull/3728) beacon, cmd: remove fake-beacon op-stack shim (revert #2678) + +#### Deprecated Flags & Config Fields +The following flags and config fields are removed or deprecated in this release. Please update your node configuration accordingly before upgrading: + +**CLI Flags** + +| Flag | Change | Note | +|---|---|---| +| `--journalfile` | Deprecated (no effect) | Remove from your startup script ([#3670](https://github.com/bnb-chain/bsc/pull/3670)) | +| `--miner.txgaslimit` | Deprecated (no effect) | Per-transaction gas limit is now enforced by EIP-7825 ([#3678](https://github.com/bnb-chain/bsc/pull/3678)) | +| `--enablebal` | Deprecated (no effect) | BEP-592 block access list has been removed ([#3690](https://github.com/bnb-chain/bsc/pull/3690)) | +| `--multidatabase` | Removed | Multi-database support is fully removed ([#3716](https://github.com/bnb-chain/bsc/pull/3716)) | +| `--txpool.overflowpoolslots` | Deprecated (no effect) | Overflow pool has been removed ([#3722](https://github.com/bnb-chain/bsc/pull/3722)) | +| `--fake-beacon` | Removed | fake-beacon op-stack shim removed ([#3728](https://github.com/bnb-chain/bsc/pull/3728)) | +| `--fake-beacon.addr` | Removed | See `--fake-beacon` ([#3728](https://github.com/bnb-chain/bsc/pull/3728)) | +| `--fake-beacon.port` | Removed | See `--fake-beacon` ([#3728](https://github.com/bnb-chain/bsc/pull/3728)) | + +**Config File (TOML) Fields** + +| Field | Change | Note | +|---|---|---| +| `[Eth] EnableBAL` | **Removed** — causes load error if present | Remove this field from your config.toml before upgrading ([#3690](https://github.com/bnb-chain/bsc/pull/3690)) | +| `[TxPool] OverflowPoolSlots` | Deprecated — silently ignored | Safe to leave but recommend removing ([#3722](https://github.com/bnb-chain/bsc/pull/3722)) | + +## MetaInfo +Mandatory Update Required: Yes +Target Audience: all BSC Testnet users +Procedure: before upgrading, review the deprecated flags and config fields listed above and confirm their removal has no impact on your node; once confirmed, binary replacement is sufficient: + - `--journalfile`: no longer has any effect, safe to remove + - `--miner.txgaslimit`: per-transaction gas limit is now enforced by EIP-7825; confirm EIP-7825 behaviour meets your requirements before removing + - `--enablebal`: no longer has any effect, safe to remove + - `--multidatabase`: single-database mode is now the only option; confirm your data directory is compatible + - `--txpool.overflowpoolslots`: overflow pool is removed; review your txpool capacity settings if you relied on it + - `[Eth] EnableBAL` in config.toml: **must be removed before upgrading** — will cause a startup error if left in + - `[TxPool] OverflowPoolSlots` in config.toml: silently ignored, but recommend removing to keep config clean +Schedule(Timeline): TBD + ## v1.7.3 v1.7.3 is a maintenance release, which mainly fixes online block pruning and kvdb abnormal continuous growth, pls refer change log for detail. diff --git a/version/version.go b/version/version.go index e52a90d33b..4d5ca988fb 100644 --- a/version/version.go +++ b/version/version.go @@ -19,6 +19,6 @@ package version const ( Major = 1 // Major version component of the current release Minor = 7 // Minor version component of the current release - Patch = 3 // Patch version component of the current release + Patch = 4 // Patch version component of the current release Meta = "" // Version metadata to append to the version string ) From 469b3f75f24cdebb28bd5c7641a1360ec1ffe1d0 Mon Sep 17 00:00:00 2001 From: wayen <19421226+flywukong@users.noreply.github.com> Date: Thu, 25 Jun 2026 16:51:02 +0800 Subject: [PATCH 44/48] miner: add BidBlock verify metrics (#3736) --- miner/bid_block.go | 13 ++++++++++--- miner/bid_simulator.go | 9 +++++++++ miner/miner_mev.go | 9 +++++++++ miner/worker.go | 4 ++++ 4 files changed, 32 insertions(+), 3 deletions(-) diff --git a/miner/bid_block.go b/miner/bid_block.go index 5ea72dae83..2c4d781b3d 100644 --- a/miner/bid_block.go +++ b/miner/bid_block.go @@ -122,6 +122,9 @@ func (w *worker) prepareBidBlockTask( decoded *types.DecodedBidBlock, start time.Time, ) (*task, error) { + prepareStart := time.Now() + defer bidBlockPrepareTimer.UpdateSince(prepareStart) + if !w.isRunning() { return nil, errors.New("worker is not running") } @@ -270,7 +273,10 @@ func (w *worker) handleBidBlockResult(block *types.Block, task *task) { // - Tx precheck failures (nonce, balance, signature, intrinsic gas, ...) // - System tx value / params (e.g. deposit value vs. SystemAddress balance) // - Blob sidecar checks (KZG proofs, blob hashes) - if _, err := w.chain.InsertChain(types.Blocks{block}); err != nil { + verifyStart := time.Now() + _, insertErr := w.chain.InsertChain(types.Blocks{block}) + bidBlockVerifyTimer.UpdateSince(verifyStart) + if insertErr != nil { log.Error("[BID BLOCK VERIFY FAILED]", "number", block.Number(), "hash", hash, @@ -281,8 +287,9 @@ func (w *worker) handleBidBlockResult(block *types.Block, task *task) { "stateRoot", block.Root(), "receiptHash", block.ReceiptHash(), "builder", task.bidBlockInfo.builder, - "err", err) - w.revokeBidBlockBuilder(task.bidBlockInfo.builder, fmt.Sprintf("InsertChain err: %v", err), hash, block.NumberU64()) + "err", insertErr) + bidBlockVerifyFailedGauge.Inc(1) + w.revokeBidBlockBuilder(task.bidBlockInfo.builder, fmt.Sprintf("InsertChain err: %v", insertErr), hash, block.NumberU64()) return } // Check the post-import average gas price excluding system transactions; only future BidBlock permission is revoked. diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index 3eb7ed9ab4..7b631611a4 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -59,6 +59,15 @@ var ( // bidBlockPreSealVerifyTimer measures only preSealVerifyBidBlock duration. bidBlockPreSealVerifyTimer = metrics.NewRegisteredTimer("bidblock/sendBidBlock/preSealVerify", nil) + + // bidBlockPrepareTimer measures prepareBidBlockTask: the selected BidBlock's + // blob KZG validation + system-tx bind-signing + TxHash recompute, on the + // critical path between selection and seal (fires on success and failure). + bidBlockPrepareTimer = metrics.NewRegisteredTimer("bidblock/prepare/duration", nil) + + // bidBlockVerifyTimer times the sealed-BidBlock InsertChain verify; fires on + // success+failure, so _count = total verifies (verified = _count - bidBlockVerifyFailed). + bidBlockVerifyTimer = metrics.NewRegisteredTimer("bidblock/verify/duration", nil) ) var ( diff --git a/miner/miner_mev.go b/miner/miner_mev.go index 5183643fde..85c01b48c0 100644 --- a/miner/miner_mev.go +++ b/miner/miner_mev.go @@ -84,6 +84,15 @@ func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("invalid signature: bidHash=%s, err=%v", bidHash, err)) } + // Receive marker for the mev-sentry -> validator hop: correlate this bidHash with + // the send-side log for latency. Logged before the gates so rejected arrivals count too. + log.Debug("[BID BLOCK RECEIVED]", + "bidHash", bidHash, + "builder", builder, + "number", bb.Header.Number, + "parentHash", bb.Header.ParentHash, + "txs", len(bb.Transactions)) + if !miner.bidSimulator.ExistBuilder(builder) { return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("builder is not registered: builder=%s, bidHash=%s", builder, bidHash)) } diff --git a/miner/worker.go b/miner/worker.go index c45fdddd48..6b3fb1dc44 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -78,9 +78,12 @@ var ( bestBidGasUsedGauge = metrics.NewRegisteredGauge("worker/bestBidGasUsed", nil) // MGas bestWorkGasUsedGauge = metrics.NewRegisteredGauge("worker/bestWorkGasUsed", nil) // MGas bidBlockExistGauge = metrics.NewRegisteredGauge("worker/bidBlockExist", nil) + bidBlockWinGauge = metrics.NewRegisteredGauge("worker/bidBlockWin", nil) bidBlockCommitGauge = metrics.NewRegisteredGauge("worker/bidBlockCommit", nil) bidBlockGasUsedGauge = metrics.NewRegisteredGauge("worker/bidBlockGasUsed", nil) // MGas bidBlockRevokeGauge = metrics.NewRegisteredGauge("worker/bidBlockRevoke", nil) // cumulative revoke count + // bidBlockVerifyFailedGauge counts sealed BidBlocks that failed async InsertChain verification (cumulative). + bidBlockVerifyFailedGauge = metrics.NewRegisteredGauge("worker/bidBlockVerifyFailed", nil) // bidBlockRevokedBuildersGauge snapshots how many builders are revoked, taken at each revoke. bidBlockRevokedBuildersGauge = metrics.NewRegisteredGauge("worker/bidBlockRevokedBuilders", nil) @@ -1473,6 +1476,7 @@ LOOP: } if bestBidBlock != nil && w.selectBidBlock(bestBidBlock, simBidBlockReward, simBidValidatorReward, bestReward) { + bidBlockWinGauge.Inc(1) task, err := w.prepareBidBlockTask(bestBidBlock, start) if err != nil { log.Error("Failed to prepare bid block, fallback", From e4d0b32c31703f72b5ae8988fd54bd20183b0a5b Mon Sep 17 00:00:00 2001 From: wayen <19421226+flywukong@users.noreply.github.com> Date: Tue, 30 Jun 2026 16:57:26 +0800 Subject: [PATCH 45/48] core/types: extract bid and block mev info into builder subpackage (#3739) * docs: add builder integration spec * core/types: extract bid and block mev info into builder subpackage * docs: fix BidBlock quota error mapping --- consensus/parlia/bid_block.go | 3 +- consensus/parlia/bid_block_test.go | 3 +- .../builder/bep-675-builder-integration.md | 185 ++++++++++++++++++ core/types/{ => builder}/bid.go | 54 +++-- .../{ => builder}/bid_block_permission.go | 2 +- core/types/{ => builder}/bid_error.go | 2 +- core/types/{ => builder}/bid_test.go | 7 +- core/types/{ => builder}/block_mev_info.go | 2 +- .../{ => builder}/block_mev_info_test.go | 2 +- eth/api_backend.go | 9 +- ethclient/ethclient.go | 9 +- internal/ethapi/api.go | 7 +- internal/ethapi/api_mev.go | 48 ++--- internal/ethapi/api_test.go | 15 +- internal/ethapi/backend.go | 9 +- internal/ethapi/transaction_args_test.go | 13 +- miner/bid_block.go | 11 +- miner/bid_block_permission.go | 6 +- miner/bid_block_permission_test.go | 4 +- miner/bid_simulator.go | 51 ++--- miner/builderclient/builderclient.go | 4 +- miner/miner_mev.go | 39 ++-- miner/miner_mev_test.go | 3 +- miner/worker.go | 5 +- miner/worker_test.go | 3 +- params/protocol_params.go | 2 +- 26 files changed, 355 insertions(+), 143 deletions(-) create mode 100644 core/types/builder/bep-675-builder-integration.md rename core/types/{ => builder}/bid.go (82%) rename core/types/{ => builder}/bid_block_permission.go (95%) rename core/types/{ => builder}/bid_error.go (99%) rename core/types/{ => builder}/bid_test.go (93%) rename core/types/{ => builder}/block_mev_info.go (99%) rename core/types/{ => builder}/block_mev_info_test.go (99%) diff --git a/consensus/parlia/bid_block.go b/consensus/parlia/bid_block.go index 7f6b3dcf62..a7b839cafd 100644 --- a/consensus/parlia/bid_block.go +++ b/consensus/parlia/bid_block.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" ) var signableSystemTxSelectors = map[string][4]byte{ @@ -155,7 +156,7 @@ func (p *Parlia) ExtractBidBlockDepositValue(txs []*types.Transaction) (int, *bi // // Stage 1 — each trailing unsigned tx must be on the BEP-675 signable whitelist. // Stage 2 — selectors & order must match expectedSystemTxShape for this header. -func (p *Parlia) VerifyBidBlockSystemTxs(decoded *types.DecodedBidBlock, parent *types.Header, systemTxStart int) error { +func (p *Parlia) VerifyBidBlockSystemTxs(decoded *buildertypes.DecodedBidBlock, parent *types.Header, systemTxStart int) error { for i := systemTxStart; i < len(decoded.Txs); i++ { if !p.isSignableSystemTx(decoded.Txs[i]) { toAddr := "" diff --git a/consensus/parlia/bid_block_test.go b/consensus/parlia/bid_block_test.go index 1899fc8cc3..be93e06ed5 100644 --- a/consensus/parlia/bid_block_test.go +++ b/consensus/parlia/bid_block_test.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" ) // sysTx builds an unsigned system-tx candidate: to=ValidatorContract, gasPrice=0, @@ -57,7 +58,7 @@ func TestVerifyBidBlockSystemTxs(t *testing.T) { } for _, tc := range tests { t.Run(tc.name, func(t *testing.T) { - decoded := &types.DecodedBidBlock{Header: header, Txs: tc.txs} + decoded := &buildertypes.DecodedBidBlock{Header: header, Txs: tc.txs} err := p.VerifyBidBlockSystemTxs(decoded, parent, tc.sysStart) if (err != nil) != tc.wantErr { t.Fatalf("VerifyBidBlockSystemTxs err=%v, wantErr=%v", err, tc.wantErr) diff --git a/core/types/builder/bep-675-builder-integration.md b/core/types/builder/bep-675-builder-integration.md new file mode 100644 index 0000000000..4b292d0f21 --- /dev/null +++ b/core/types/builder/bep-675-builder-integration.md @@ -0,0 +1,185 @@ +This document describes the concrete builder-side integration details for the BidBlock path: API call chain, payload assembly, signature, permission lifecycle, error handling, and timing. + +For the protocol design and high-level workflow, see [BEP-675: Builder-Proposed Block with Validator Blind Signing](https://github.com/bnb-chain/BEPs/blob/master/BEPs/BEP-675.md). This document does not restate the rationale covered there. + +## Workflow + +The builder's end-to-end flow for producing and submitting a BidBlock: + +``` +parent header / state + → initialize header skeleton + → Parlia.PrepareForBidBlock + fills Coinbase / Difficulty / Time / MixDigest / Extra / Nonce + (Extra will be overwritten by the validator) + + → select and execute user txs + produces body.Transactions / receipts / updated state + + → Parlia.FinalizeAndAssembleBidBlock + executes and appends unsigned system tx + returns the complete block + + → block → builder.BidBlock + Header = block.Header() + Transactions = tx.MarshalBinary() + Sidecars = block.Sidecars() + + → Sign BidBlock.Hash() + produces builder.BidBlockArgs + + → mev_getBidBlockPermission(builder) + (cached; if !allowed, fall back to mev_sendBid) + + → mev_sendBidBlock +``` + +## 1. Prepare the Header Skeleton + +The builder first fills in the locally known fields, then calls `PrepareForBidBlock` to complete the Parlia consensus fields: + +```go +header := &types.Header{ + ParentHash: parent.Hash(), + Number: new(big.Int).Add(parent.Number, common.Big1), + GasLimit: gasLimit, + BaseFee: baseFee, +} +err := parliaEngine.PrepareForBidBlock(chain, header) +``` + +`PrepareForBidBlock` writes `Coinbase` / `Difficulty` / `Time` / `MixDigest` / `Extra` / `Nonce`. `Coinbase` is taken from the parent snapshot's `inturnValidator()`, not the local `p.val` — the builder does not have a validator key. + +## 2. Execute User Transactions + +Transaction selection and EVM execution are entirely builder-driven; this specification does not constrain them. The builder runs selected user transactions against the parent state and maintains `state` / `receipts` / `body.Transactions` / `sidecars`. + +## 3. Finalize (generate unsigned system tx) + +```go +block, receipts, err := parliaEngine.FinalizeAndAssembleBidBlock( + chain, header, state, body, receipts, tracer, +) +``` + +**Input:** + +- The `header` / `state` / `body` / `receipts` after user txs have already been executed. + +**Execution:** + +1. Enters `finalizeAndAssemble(..., systemTxPacking)`. +2. Generates and executes the trailing system txs per Parlia rules: + - `deposit` (always) + - `distributeFinalityReward` (every 200 blocks) + - `updateValidatorSetV2` (breathe blocks only) +3. The system tx genuinely executes on the EVM: + - updates state + - increases `header.GasUsed` + - appends a receipt + - affects `Root` / `ReceiptHash` / `Bloom` / `GasUsed` +4. However, in `systemTxPacking` mode the transactions are **not** signed with the validator key: + - the system txs appended to the block are unsigned (v/r/s = 0, gasPrice = 0) +5. Computes the final state root and assembles the block from `header` + `body` + `receipts`. + +**Output:** + +- the complete block (with unsigned trailing system txs) +- the complete receipts + +Signing does not affect EVM state transitions, so the execution results are identical whether the system transactions are signed (validator-mining path) or unsigned (builder packing path). The validator bind-signs these unsigned system txs at seal time and recomputes `TxHash`. + +`GasFee` is not a wire field of `BidBlock`. The validator derives it from the `value` of the trailing `deposit` system transaction and uses it to rank competing BidBlocks for the same parent. + +## 4. Assemble the BidBlock Payload + +```go +txBytes := make([]hexutil.Bytes, len(block.Transactions())) +for i, tx := range block.Transactions() { + enc, _ := tx.MarshalBinary() + txBytes[i] = enc +} +bidBlock := &builder.BidBlock{ + Header: block.Header(), + Transactions: txBytes, + Sidecars: block.Sidecars(), +} +``` + +**Hard ordering constraint:** user txs come first, unsigned system txs come last. + +## 5. Signing + +```go +sig, _ := crypto.Sign(bidBlock.Hash().Bytes(), builderKey) +args := &builder.BidBlockArgs{BidBlock: bidBlock, Signature: sig} +``` + +A bare keccak digest, with no EIP-191/712 prefix, consistent with the existing `mev_sendBid`. The validator recovers the address using `args.EcrecoverSender()`. + +## 6. Send and Fallback + +### Check permission + +Builders poll `mev_getBidBlockPermission` to determine whether the BidBlock path is currently open for them on a given validator, and fall back to legacy `mev_sendBid` when it is not. + +The RPC does not surface permission denial through a JSON-RPC error; state is carried in the `allowed` field of the result. When `allowed` is false, `reason` identifies why. Current values: + +- `insertchain_failed` — the last sealed BidBlock from this builder failed validator-side `InsertChain` (e.g. invalid state root, mismatched receipt hash, KZG proof failure). +- `gasprice_too_low` — the sealed BidBlock imported successfully, but its average gas price (excluding system transactions) was below the validator's configured minimum. +- `manual` — admin revoke via `admin_setBidBlockPermission`. + +`mev_getBidBlockPermission` response: + +```jsonc +{ + "allowed": false, + "reason": "insertchain_failed", + "blockHash": "0x...", + "blockNumber": "0x123", + "revokedAt": "2026-05-22T...", // when the revoke happened + "resetAt": "2026-05-23T00:00:00Z" // when the revoke expires (RPC returns the lockout expiry; builder may treat as informational) +} +``` + +### `mev_sendBidBlock` error mapping + +The main BidBlock failure modes have dedicated JSON-RPC codes; match by code where possible. Code `-38001` remains a catch-all for parameter / pre-check errors, so still inspect the message for those. + +| Error message contains | JSON-RPC code | Builder action | +| --- | --- | --- | +| `BidBlock disabled, fallback to SendBid` | -38001 | fallback to `mev_sendBid` | +| `builder BidBlock permission revoked, fallback to SendBid` | -38006 | permission not allowed; fallback to `mev_sendBid` | +| `pre-seal verify failed: ...` | -38007 | **fix build logic; do NOT retry the same BidBlock** | +| `too late, expected before ...` | -38008 | dropped; next slot | +| `the validator stop accepting bids ...` | -38003 | validator paused; retry later | +| `the validator is working on too many bids ...` | -38004 | validator busy/overloaded (admission timed out); retry later | +| `the validator is not in-turn ...` | -38005 | next slot or try another validator | +| `too many bids: exceeded limit of N bids per builder per block` | _(no dedicated code; plain JSON-RPC error)_ | per-builder quota hit (`mev_params.MaxBidsPerBuilder`); retry next slot or fall back to `mev_sendBid` | + +**Recommended practice:** + +- Poll `mev_getBidBlockPermission` once every 5–10 seconds and cache the current validator's BidBlock permission for that builder. +- For each validator, periodically query `mev_params` to check whether that validator has BidBlock enabled (`BidBlockEnabled` field). When disabled, treat it the same as permission denied and fall back to legacy `mev_sendBid`. + +### BidBlock send window + +The BidBlock path skips validator-side simulation, so the receive deadline is: + +``` +BidMustBefore = parent.MilliTimestamp + BlockInterval - DelayLeftOver // 15ms +``` + +As the validator still needs µs-level time for signature recovery, tx decoding, pre-seal verification, and `Extra` overwrite before sealing, arrivals **exactly at** `BidMustBefore` may still miss the seal. We recommend builders leave a buffer of ≈100µs–1ms before `BidMustBefore`. + +The transmission latency on the wire is not constant: the number of transactions and the number of blobs in the BidBlock both increase the payload size and therefore the time it takes to reach the validator. A larger BidBlock arrives later, so this transmission cost must be factored into the send-window control logic (e.g. estimate the on-wire delay from the current tx/blob count and bring the send time forward accordingly), rather than assuming a fixed offset before `BidMustBefore`. + +## Summary + +1. GasFee does not need to be provided explicitly; the validator derives it from the trailing deposit system tx. +2. The validator overwrites `Extra` and recomputes `TxHash` after bind-signing the system tx; all other header fields are used as-is from the builder. +3. The BidBlock send window is later than legacy `mev_sendBid` because no validator-side simulation is needed (see [BidBlock send window](#bidblock-send-window)). +4. BidBlock and the legacy bid share the same per-block quota, exposed via `mev_params.MaxBidsPerBuilder`. +5. Permission must be polled continuously (every 5–10 seconds is recommended); the cache is also invalidated whenever `mev_sendBidBlock` returns "permission revoked". When `mev_params.BidBlockEnabled == false`, treat it the same as permission denied. +6. The builder must handle BidBlock failure paths: (1) `mev_sendBidBlock` may return a direct error; (2) permission may be revoked, with the reason exposed by `mev_getBidBlockPermission`; (3) validator admin or local policy changes may later restore or revoke permission. +7. **Send the BidBlock as close to `BidMustBefore` as possible** (leaving the ≈100µs buffer noted above) — a later send leaves more time for transaction selection and execution, maximizing the value packed into the block. diff --git a/core/types/bid.go b/core/types/builder/bid.go similarity index 82% rename from core/types/bid.go rename to core/types/builder/bid.go index 318f7bbb77..a4005ef1cc 100644 --- a/core/types/bid.go +++ b/core/types/builder/bid.go @@ -1,4 +1,4 @@ -package types +package builder import ( "fmt" @@ -10,7 +10,9 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/rlp" ) const TxDecodeConcurrencyForPerBid = 5 @@ -36,7 +38,7 @@ func (b *BidArgs) EcrecoverSender() (common.Address, error) { return crypto.PubkeyToAddress(*pk), nil } -func (b *BidArgs) ToBid(builder common.Address, signer Signer) (*Bid, error) { +func (b *BidArgs) ToBid(builder common.Address, signer types.Signer) (*Bid, error) { txs, err := b.RawBid.DecodeTxs(signer) if err != nil { return nil, err @@ -49,7 +51,7 @@ func (b *BidArgs) ToBid(builder common.Address, signer Signer) (*Bid, error) { unRevertibleHashes.Append(b.RawBid.UnRevertible...) if len(b.PayBidTx) != 0 { - var payBidTx = new(Transaction) + var payBidTx = new(types.Transaction) err = payBidTx.UnmarshalBinary(b.PayBidTx) if err != nil { return nil, err @@ -90,21 +92,21 @@ type RawBid struct { hash atomic.Value } -func (b *RawBid) DecodeTxs(signer Signer) ([]*Transaction, error) { +func (b *RawBid) DecodeTxs(signer types.Signer) ([]*types.Transaction, error) { if len(b.Txs) == 0 { - return []*Transaction{}, nil + return []*types.Transaction{}, nil } txChan := make(chan int, len(b.Txs)) - bidTxs := make([]*Transaction, len(b.Txs)) - decode := func(txBytes hexutil.Bytes) (*Transaction, error) { - tx := new(Transaction) + bidTxs := make([]*types.Transaction, len(b.Txs)) + decode := func(txBytes hexutil.Bytes) (*types.Transaction, error) { + tx := new(types.Transaction) err := tx.UnmarshalBinary(txBytes) if err != nil { return nil, err } - _, err = Sender(signer, tx) + _, err = types.Sender(signer, tx) if err != nil { return nil, err } @@ -167,7 +169,7 @@ type Bid struct { Builder common.Address BlockNumber uint64 ParentHash common.Hash - Txs Transactions + Txs types.Transactions UnRevertible mapset.Set[common.Hash] GasUsed uint64 GasFee *big.Int @@ -227,12 +229,12 @@ func (b *BidBlockArgs) ToDecodedBidBlock(builder common.Address) (*DecodedBidBlo sidecars := b.BidBlock.Sidecars if sidecars == nil { - sidecars = BlobSidecars{} + sidecars = types.BlobSidecars{} } return &DecodedBidBlock{ Builder: builder, - Header: CopyHeader(b.BidBlock.Header), + Header: types.CopyHeader(b.BidBlock.Header), Txs: txs, Sidecars: sidecars, bidHash: b.BidBlock.Hash(), @@ -240,10 +242,10 @@ func (b *BidBlockArgs) ToDecodedBidBlock(builder common.Address) (*DecodedBidBlo } // DecodeTxs decodes user txs followed by unsigned system txs. -func (b *BidBlockArgs) DecodeTxs() ([]*Transaction, error) { - txs := make([]*Transaction, len(b.BidBlock.Transactions)) +func (b *BidBlockArgs) DecodeTxs() ([]*types.Transaction, error) { + txs := make([]*types.Transaction, len(b.BidBlock.Transactions)) for i, txBytes := range b.BidBlock.Transactions { - tx := new(Transaction) + tx := new(types.Transaction) if err := tx.UnmarshalBinary(txBytes); err != nil { return nil, fmt.Errorf("failed to decode tx %d: %v", i, err) } @@ -254,9 +256,9 @@ func (b *BidBlockArgs) DecodeTxs() ([]*Transaction, error) { // BidBlock is the builder-proposed block carried by BidBlockArgs. type BidBlock struct { - Header *Header `json:"header"` - Transactions []hexutil.Bytes `json:"transactions"` // user txs first, unsigned system txs last - Sidecars BlobSidecars `json:"sidecars,omitempty"` + Header *types.Header `json:"header"` + Transactions []hexutil.Bytes `json:"transactions"` // user txs first, unsigned system txs last + Sidecars types.BlobSidecars `json:"sidecars,omitempty"` hash atomic.Value } @@ -274,9 +276,9 @@ func (b *BidBlock) Hash() common.Hash { // DecodedBidBlock is the validator-side decoded representation of a BidBlock. type DecodedBidBlock struct { Builder common.Address // recovered from BidBlockArgs.Signature - Header *Header - Txs Transactions - Sidecars BlobSidecars + Header *types.Header + Txs types.Transactions + Sidecars types.BlobSidecars GasFee *big.Int SystemTxStart int // index in Txs where the unsigned trailing system-tx region begins; set during admission. @@ -309,3 +311,13 @@ type MevParams struct { BidBlockEnabled bool // whether mev_sendBidBlock is accepted Version string } + +// rlpHash encodes x and returns the keccak256 hash of the encoding. It mirrors +// the unexported helper in package types, replicated here so the bid/bidblock +// hashing stays byte-for-byte identical after moving out of core/types. +func rlpHash(x interface{}) (h common.Hash) { + sha := crypto.NewKeccakState() + rlp.Encode(sha, x) + sha.Read(h[:]) + return h +} diff --git a/core/types/bid_block_permission.go b/core/types/builder/bid_block_permission.go similarity index 95% rename from core/types/bid_block_permission.go rename to core/types/builder/bid_block_permission.go index 8215da9449..2d7aee19cd 100644 --- a/core/types/bid_block_permission.go +++ b/core/types/builder/bid_block_permission.go @@ -1,4 +1,4 @@ -package types +package builder import ( "time" diff --git a/core/types/bid_error.go b/core/types/builder/bid_error.go similarity index 99% rename from core/types/bid_error.go rename to core/types/builder/bid_error.go index 32079d869d..ac9008ab23 100644 --- a/core/types/bid_error.go +++ b/core/types/builder/bid_error.go @@ -1,4 +1,4 @@ -package types +package builder import "errors" diff --git a/core/types/bid_test.go b/core/types/builder/bid_test.go similarity index 93% rename from core/types/bid_test.go rename to core/types/builder/bid_test.go index 93d9b7c8aa..adfe8d0c21 100644 --- a/core/types/bid_test.go +++ b/core/types/builder/bid_test.go @@ -1,19 +1,20 @@ // Copyright 2026 The go-ethereum Authors // This file is part of the go-ethereum library. -package types +package builder import ( "math/big" "testing" "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/core/types" ) func TestBidBlockArgsToDecodedBidBlockNormalizesNilSidecars(t *testing.T) { args := &BidBlockArgs{ BidBlock: &BidBlock{ - Header: &Header{ + Header: &types.Header{ Difficulty: big.NewInt(1), Number: big.NewInt(1), Extra: make([]byte, 32), @@ -36,7 +37,7 @@ func TestBidBlockArgsToDecodedBidBlockNormalizesNilSidecars(t *testing.T) { func TestBidBlockArgsToDecodedBidBlockCopiesHeader(t *testing.T) { args := &BidBlockArgs{ BidBlock: &BidBlock{ - Header: &Header{ + Header: &types.Header{ Difficulty: big.NewInt(1), Number: big.NewInt(1), Extra: []byte{1, 2, 3}, diff --git a/core/types/block_mev_info.go b/core/types/builder/block_mev_info.go similarity index 99% rename from core/types/block_mev_info.go rename to core/types/builder/block_mev_info.go index ca1dd98b7d..1ed1e94ae9 100644 --- a/core/types/block_mev_info.go +++ b/core/types/builder/block_mev_info.go @@ -4,7 +4,7 @@ // BEP-675 block-source tagging. Validators encode the winning MEV path and // builder address into header.RequestsHash; local blocks keep EmptyRequestsHash. -package types +package builder import ( "github.com/ethereum/go-ethereum/common" diff --git a/core/types/block_mev_info_test.go b/core/types/builder/block_mev_info_test.go similarity index 99% rename from core/types/block_mev_info_test.go rename to core/types/builder/block_mev_info_test.go index 6b97d7d5a9..41faf4562a 100644 --- a/core/types/block_mev_info_test.go +++ b/core/types/builder/block_mev_info_test.go @@ -1,7 +1,7 @@ // Copyright 2026 The go-ethereum Authors // This file is part of the go-ethereum library. -package types +package builder import ( "testing" diff --git a/eth/api_backend.go b/eth/api_backend.go index 41d67d0d2e..be02b11de7 100644 --- a/eth/api_backend.go +++ b/eth/api_backend.go @@ -36,6 +36,7 @@ import ( "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/txpool/locals" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth/downloader" "github.com/ethereum/go-ethereum/eth/gasprice" @@ -542,7 +543,7 @@ func (b *EthAPIBackend) MevRunning() bool { return b.Miner().MevRunning() } -func (b *EthAPIBackend) MevParams() *types.MevParams { +func (b *EthAPIBackend) MevParams() *buildertypes.MevParams { return b.Miner().MevParams() } @@ -566,15 +567,15 @@ func (b *EthAPIBackend) HasBuilder(builder common.Address) bool { return b.Miner().HasBuilder(builder) } -func (b *EthAPIBackend) GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus { +func (b *EthAPIBackend) GetBidBlockPermission(builder common.Address) buildertypes.BidBlockPermissionStatus { return b.Miner().GetBidBlockPermission(builder) } -func (b *EthAPIBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) { +func (b *EthAPIBackend) SendBid(ctx context.Context, bid *buildertypes.BidArgs) (common.Hash, error) { return b.Miner().SendBid(ctx, bid) } -func (b *EthAPIBackend) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) { +func (b *EthAPIBackend) SendBidBlock(ctx context.Context, args *buildertypes.BidBlockArgs) (common.Hash, error) { return b.Miner().SendBidBlock(ctx, args) } diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go index 8d77701275..1b2c30f527 100644 --- a/ethclient/ethclient.go +++ b/ethclient/ethclient.go @@ -29,6 +29,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/rpc" ) @@ -861,7 +862,7 @@ func (ec *Client) HasBuilder(ctx context.Context, address common.Address) (bool, } // SendBid sends a bid -func (ec *Client) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, error) { +func (ec *Client) SendBid(ctx context.Context, args buildertypes.BidArgs) (common.Hash, error) { var hash common.Hash err := ec.c.CallContext(ctx, &hash, "mev_sendBid", args) if err != nil { @@ -871,7 +872,7 @@ func (ec *Client) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, } // SendBidBlock sends a BidBlock (zero-simulate MEV path). -func (ec *Client) SendBidBlock(ctx context.Context, args types.BidBlockArgs) (common.Hash, error) { +func (ec *Client) SendBidBlock(ctx context.Context, args buildertypes.BidBlockArgs) (common.Hash, error) { var hash common.Hash err := ec.c.CallContext(ctx, &hash, "mev_sendBidBlock", args) if err != nil { @@ -911,8 +912,8 @@ func (ec *Client) BestBidGasFee(ctx context.Context, parentHash common.Hash) (*b } // MevParams returns the static params of mev -func (ec *Client) MevParams(ctx context.Context) (*types.MevParams, error) { - var params types.MevParams +func (ec *Client) MevParams(ctx context.Context) (*buildertypes.MevParams, error) { + var params buildertypes.MevParams err := ec.c.CallContext(ctx, ¶ms, "mev_params") if err != nil { return nil, err diff --git a/internal/ethapi/api.go b/internal/ethapi/api.go index 8a040b31b5..0bab97d092 100644 --- a/internal/ethapi/api.go +++ b/internal/ethapi/api.go @@ -42,6 +42,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/tracing" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/eth/gasestimator" @@ -567,14 +568,14 @@ func (api *BlockChainAPI) GetBlockMevInfo(ctx context.Context, blockNrOrHash rpc if header.RequestsHash == nil { return info, nil } - version, builder, ok := types.DecodeBlockMevInfo(*header.RequestsHash) + version, builder, ok := buildertypes.DecodeBlockMevInfo(*header.RequestsHash) if !ok { return info, nil } switch version { - case types.BlockMevInfoVersionBid: + case buildertypes.BlockMevInfoVersionBid: info.Version = "v1" - case types.BlockMevInfoVersionBidBlock: + case buildertypes.BlockMevInfoVersionBidBlock: info.Version = "v2" } b := builder diff --git a/internal/ethapi/api_mev.go b/internal/ethapi/api_mev.go index e76580691b..b67e32ac01 100644 --- a/internal/ethapi/api_mev.go +++ b/internal/ethapi/api_mev.go @@ -7,7 +7,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" - "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/params" ) @@ -25,10 +25,10 @@ func NewMevAPI(b Backend) *MevAPI { // SendBid receives bid from the builders. // If mev is not running or bid is invalid, return error. // Otherwise, creates a builder bid for the given argument, submit it to the miner. -func (m *MevAPI) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, error) { +func (m *MevAPI) SendBid(ctx context.Context, args buildertypes.BidArgs) (common.Hash, error) { ctx = context.WithValue(ctx, "receiveTime", time.Now().UnixMilli()) if !m.b.MevRunning() { - return common.Hash{}, types.ErrMevNotRunning + return common.Hash{}, buildertypes.ErrMevNotRunning } var ( @@ -37,12 +37,12 @@ func (m *MevAPI) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, ) if rawBid == nil { - return common.Hash{}, types.NewInvalidBidError("rawBid should not be nil") + return common.Hash{}, buildertypes.NewInvalidBidError("rawBid should not be nil") } // only support bidding for the next block not for the future block if latestBlockNumber := currentBlock.Number.Uint64(); rawBid.BlockNumber < latestBlockNumber+1 { - return common.Hash{}, types.NewInvalidBidError( + return common.Hash{}, buildertypes.NewInvalidBidError( fmt.Sprintf("stale block number: %d, latest block: %d", rawBid.BlockNumber, latestBlockNumber)) } else if rawBid.BlockNumber > latestBlockNumber+1 { // For the first block of a validator's turn, the previous block must be imported first. @@ -50,38 +50,38 @@ func (m *MevAPI) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, // However, this is not a significant issue because: // a. Each turn consists of 16 blocks, so this situation can only occur at most 1/16 of the time. // b. Each builder is allowed to submit multiple bids for each block. - return common.Hash{}, types.NewInvalidBidError( + return common.Hash{}, buildertypes.NewInvalidBidError( fmt.Sprintf("block in future: %d, latest block: %d", rawBid.BlockNumber, latestBlockNumber)) } else if !m.b.MinerInTurn() { - return common.Hash{}, types.ErrMevNotInTurn + return common.Hash{}, buildertypes.ErrMevNotInTurn } if rawBid.ParentHash != currentBlock.Hash() { - return common.Hash{}, types.NewInvalidBidError( + return common.Hash{}, buildertypes.NewInvalidBidError( fmt.Sprintf("non-aligned parent hash: %v", currentBlock.Hash())) } if rawBid.GasFee == nil || rawBid.GasFee.Cmp(common.Big0) == 0 || rawBid.GasUsed == 0 { - return common.Hash{}, types.NewInvalidBidError("empty gasFee or empty gasUsed") + return common.Hash{}, buildertypes.NewInvalidBidError("empty gasFee or empty gasUsed") } if rawBid.BuilderFee != nil { builderFee := rawBid.BuilderFee if builderFee.Cmp(common.Big0) < 0 { - return common.Hash{}, types.NewInvalidBidError("builder fee should not be less than 0") + return common.Hash{}, buildertypes.NewInvalidBidError("builder fee should not be less than 0") } if builderFee.Cmp(rawBid.GasFee) >= 0 { - return common.Hash{}, types.NewInvalidBidError("builder fee must be less than gas fee") + return common.Hash{}, buildertypes.NewInvalidBidError("builder fee must be less than gas fee") } } if len(args.PayBidTx) == 0 || args.PayBidTxGasUsed == 0 { - return common.Hash{}, types.NewInvalidPayBidTxError("payBidTx and payBidTxGasUsed are must-have") + return common.Hash{}, buildertypes.NewInvalidPayBidTxError("payBidTx and payBidTxGasUsed are must-have") } if args.PayBidTxGasUsed > params.PayBidTxGasLimit { - return common.Hash{}, types.NewInvalidBidError( + return common.Hash{}, buildertypes.NewInvalidBidError( fmt.Sprintf("transfer tx gas used must be no more than %v", params.PayBidTxGasLimit)) } @@ -89,19 +89,19 @@ func (m *MevAPI) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, } // SendBidBlock receives a BidBlock from builders. -func (m *MevAPI) SendBidBlock(ctx context.Context, args types.BidBlockArgs) (common.Hash, error) { +func (m *MevAPI) SendBidBlock(ctx context.Context, args buildertypes.BidBlockArgs) (common.Hash, error) { ctx = context.WithValue(ctx, "receiveTime", time.Now().UnixMilli()) if !m.b.MevRunning() { - return common.Hash{}, types.ErrMevNotRunning + return common.Hash{}, buildertypes.ErrMevNotRunning } // Basic structural validation. if args.BidBlock == nil { - return common.Hash{}, types.NewInvalidBidError("empty BidBlock") + return common.Hash{}, buildertypes.NewInvalidBidError("empty BidBlock") } bb := args.BidBlock if bb.Header == nil { - return common.Hash{}, types.NewInvalidBidError("empty Header") + return common.Hash{}, buildertypes.NewInvalidBidError("empty Header") } blockNumber := bb.Header.Number.Uint64() @@ -110,32 +110,32 @@ func (m *MevAPI) SendBidBlock(ctx context.Context, args types.BidBlockArgs) (com currentNumber := currentBlock.Number.Uint64() if blockNumber < currentNumber+1 { - return common.Hash{}, types.NewInvalidBidError( + return common.Hash{}, buildertypes.NewInvalidBidError( fmt.Sprintf("stale block number: %d, latest block: %d", blockNumber, currentNumber)) } else if blockNumber > currentNumber+1 { - return common.Hash{}, types.NewInvalidBidError( + return common.Hash{}, buildertypes.NewInvalidBidError( fmt.Sprintf("block in future: %d, latest block: %d", blockNumber, currentNumber)) } else if !m.b.MinerInTurn() { - return common.Hash{}, types.ErrMevNotInTurn + return common.Hash{}, buildertypes.ErrMevNotInTurn } if parentHash != currentBlock.Hash() { - return common.Hash{}, types.NewInvalidBidError( + return common.Hash{}, buildertypes.NewInvalidBidError( fmt.Sprintf("non-aligned parent hash: %v", currentBlock.Hash())) } if bb.Header.GasUsed == 0 { - return common.Hash{}, types.NewInvalidBidError("empty gasUsed in header") + return common.Hash{}, buildertypes.NewInvalidBidError("empty gasUsed in header") } if len(bb.Transactions) == 0 { - return common.Hash{}, types.NewInvalidBidError("empty transactions") + return common.Hash{}, buildertypes.NewInvalidBidError("empty transactions") } return m.b.SendBidBlock(ctx, &args) } -func (m *MevAPI) Params() *types.MevParams { +func (m *MevAPI) Params() *buildertypes.MevParams { return m.b.MevParams() } diff --git a/internal/ethapi/api_test.go b/internal/ethapi/api_test.go index 8c742b031c..0d8be8bee8 100644 --- a/internal/ethapi/api_test.go +++ b/internal/ethapi/api_test.go @@ -48,6 +48,7 @@ import ( "github.com/ethereum/go-ethereum/core/rawdb" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/kzg4844" @@ -104,7 +105,7 @@ func TestMevAPIGetBidBlockPermission(t *testing.T) { revokedAt := time.Date(2026, 5, 9, 10, 0, 0, 0, time.UTC) resetAt := time.Date(2026, 5, 10, 0, 0, 0, 0, time.UTC) api := NewMevAPI(&testBackend{ - bidBlockPermission: types.BidBlockPermissionStatus{ + bidBlockPermission: buildertypes.BidBlockPermissionStatus{ Allowed: false, Reason: "gasfee_overclaim", BlockHash: blockHash, @@ -488,7 +489,7 @@ type testBackend struct { syncDefaultTimeout time.Duration syncMaxTimeout time.Duration - bidBlockPermission types.BidBlockPermissionStatus + bidBlockPermission buildertypes.BidBlockPermissionStatus } func fakeBlockHash(txh common.Hash) common.Hash { @@ -760,20 +761,20 @@ func (b testBackend) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscripti func (b *testBackend) MevRunning() bool { return false } func (b *testBackend) HasBuilder(builder common.Address) bool { return false } -func (b *testBackend) GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus { +func (b *testBackend) GetBidBlockPermission(builder common.Address) buildertypes.BidBlockPermissionStatus { return b.bidBlockPermission } -func (b *testBackend) MevParams() *types.MevParams { - return &types.MevParams{} +func (b *testBackend) MevParams() *buildertypes.MevParams { + return &buildertypes.MevParams{} } func (b *testBackend) StartMev() {} func (b *testBackend) StopMev() {} func (b *testBackend) AddBuilder(builder common.Address, builderUrl string) error { return nil } func (b *testBackend) RemoveBuilder(builder common.Address) error { return nil } -func (b *testBackend) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) { +func (b *testBackend) SendBid(ctx context.Context, bid *buildertypes.BidArgs) (common.Hash, error) { panic("implement me") } -func (b *testBackend) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) { +func (b *testBackend) SendBidBlock(ctx context.Context, args *buildertypes.BidBlockArgs) (common.Hash, error) { panic("implement me") } func (b *testBackend) MinerInTurn() bool { return false } diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go index 473ce9567e..5b9a9624a8 100644 --- a/internal/ethapi/backend.go +++ b/internal/ethapi/backend.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/core/filtermaps" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" @@ -110,7 +111,7 @@ type Backend interface { // MevRunning return true if mev is running MevRunning() bool // MevParams returns the static params of mev - MevParams() *types.MevParams + MevParams() *buildertypes.MevParams // StartMev starts mev StartMev() // StopMev stops mev @@ -122,11 +123,11 @@ type Backend interface { // HasBuilder returns true if the builder is in the builder list. HasBuilder(builder common.Address) bool // GetBidBlockPermission returns the builder's current SendBidBlock permission. - GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus + GetBidBlockPermission(builder common.Address) buildertypes.BidBlockPermissionStatus // SendBid receives bid from the builders. - SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) + SendBid(ctx context.Context, bid *buildertypes.BidArgs) (common.Hash, error) // SendBidBlock receives a BidBlock from builders. - SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) + SendBidBlock(ctx context.Context, args *buildertypes.BidBlockArgs) (common.Hash, error) // MinerInTurn returns true if the validator is in turn to propose the block. MinerInTurn() bool diff --git a/internal/ethapi/transaction_args_test.go b/internal/ethapi/transaction_args_test.go index 004018a3e0..9a29323565 100644 --- a/internal/ethapi/transaction_args_test.go +++ b/internal/ethapi/transaction_args_test.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/core/filtermaps" "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" @@ -423,20 +424,20 @@ func (b *backendMock) CurrentValidators() ([]common.Address, error) { return []c func (b *backendMock) MevRunning() bool { return false } func (b *backendMock) HasBuilder(builder common.Address) bool { return false } -func (b *backendMock) GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus { - return types.BidBlockPermissionStatus{} +func (b *backendMock) GetBidBlockPermission(builder common.Address) buildertypes.BidBlockPermissionStatus { + return buildertypes.BidBlockPermissionStatus{} } -func (b *backendMock) MevParams() *types.MevParams { - return &types.MevParams{} +func (b *backendMock) MevParams() *buildertypes.MevParams { + return &buildertypes.MevParams{} } func (b *backendMock) StartMev() {} func (b *backendMock) StopMev() {} func (b *backendMock) AddBuilder(builder common.Address, builderUrl string) error { return nil } func (b *backendMock) RemoveBuilder(builder common.Address) error { return nil } -func (b *backendMock) SendBid(ctx context.Context, bid *types.BidArgs) (common.Hash, error) { +func (b *backendMock) SendBid(ctx context.Context, bid *buildertypes.BidArgs) (common.Hash, error) { panic("implement me") } -func (b *backendMock) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) { +func (b *backendMock) SendBidBlock(ctx context.Context, args *buildertypes.BidBlockArgs) (common.Hash, error) { panic("implement me") } func (b *backendMock) MinerInTurn() bool { return false } diff --git a/miner/bid_block.go b/miner/bid_block.go index 2c4d781b3d..5639a7a81c 100644 --- a/miner/bid_block.go +++ b/miner/bid_block.go @@ -19,6 +19,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/trie" ) @@ -39,15 +40,15 @@ func setBidMevInfo(header *types.Header, builder common.Address, isBidBlock bool if !isBidBlock && header.RequestsHash == nil { return } - version := types.BlockMevInfoVersionBid + version := buildertypes.BlockMevInfoVersionBid if isBidBlock { - version = types.BlockMevInfoVersionBidBlock + version = buildertypes.BlockMevInfoVersionBidBlock } - tag := types.EncodeBlockMevInfo(version, builder) + tag := buildertypes.EncodeBlockMevInfo(version, builder) header.RequestsHash = &tag } -func (w *worker) selectBidBlock(bidBlock *types.DecodedBidBlock, simBidBlockReward, simBidValidatorReward, bestReward *uint256.Int) bool { +func (w *worker) selectBidBlock(bidBlock *buildertypes.DecodedBidBlock, simBidBlockReward, simBidValidatorReward, bestReward *uint256.Int) bool { if bidBlock == nil { return false } @@ -119,7 +120,7 @@ func bindSignBidBlockSystemTxs( // changing them after the builder's pre-execution would diverge the re-executed // stateRoot and fail InsertChain. func (w *worker) prepareBidBlockTask( - decoded *types.DecodedBidBlock, + decoded *buildertypes.DecodedBidBlock, start time.Time, ) (*task, error) { prepareStart := time.Now() diff --git a/miner/bid_block_permission.go b/miner/bid_block_permission.go index 00b04e73dd..d454956d76 100644 --- a/miner/bid_block_permission.go +++ b/miner/bid_block_permission.go @@ -10,7 +10,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" ) // RevokeReasonManual is the Reason value used when an operator manually revokes @@ -92,10 +92,10 @@ func (m *BidBlockPermissionManager) RevokeFor( } } -func (m *BidBlockPermissionManager) GetStatus(builder common.Address) types.BidBlockPermissionStatus { +func (m *BidBlockPermissionManager) GetStatus(builder common.Address) buildertypes.BidBlockPermissionStatus { m.mu.RLock() defer m.mu.RUnlock() - status := types.BidBlockPermissionStatus{ + status := buildertypes.BidBlockPermissionStatus{ Allowed: true, } rec, found := m.activeRecord(builder, m.clock()) diff --git a/miner/bid_block_permission_test.go b/miner/bid_block_permission_test.go index 7ab76847e2..92519c2ada 100644 --- a/miner/bid_block_permission_test.go +++ b/miner/bid_block_permission_test.go @@ -11,7 +11,7 @@ import ( "time" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/miner/builderclient" "github.com/ethereum/go-ethereum/miner/minerconfig" ) @@ -359,7 +359,7 @@ func TestBidBlockAdmission_DisabledDoesNotConsumeQuota(t *testing.T) { }, } - _, err := miner.SendBidBlock(context.Background(), &types.BidBlockArgs{}) + _, err := miner.SendBidBlock(context.Background(), &buildertypes.BidBlockArgs{}) if err == nil || !strings.Contains(err.Error(), "BidBlock disabled") { t.Fatalf("expected BidBlock disabled error, got %v", err) } diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index 7b631611a4..3124082f48 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -22,6 +22,7 @@ import ( "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/metrics" @@ -109,13 +110,13 @@ type simBidReq struct { // newBidPackage is the warp of a new bid and a feedback channel type newBidPackage struct { - bid *types.Bid + bid *buildertypes.Bid feedback chan error receiveTime int64 } type newBidBlockPackage struct { - bidBlock *types.DecodedBidBlock + bidBlock *buildertypes.DecodedBidBlock feedback chan error } @@ -153,8 +154,8 @@ type bidSimulator struct { pending map[uint64]map[common.Address]map[common.Hash]struct{} // blockNumber -> builder -> bidHash -> struct{} bestBidMu sync.RWMutex - bestBid map[common.Hash]*BidRuntime // prevBlockHash -> bidRuntime - bestBidToRun map[common.Hash]*types.Bid // prevBlockHash -> *types.Bid + bestBid map[common.Hash]*BidRuntime // prevBlockHash -> bidRuntime + bestBidToRun map[common.Hash]*buildertypes.Bid // prevBlockHash -> *buildertypes.Bid simBidMu sync.RWMutex simulatingBid map[common.Hash]*BidRuntime // prevBlockHash -> bidRuntime, in the process of simulation @@ -164,8 +165,8 @@ type bidSimulator struct { // SendBidBlock fields bestBidBlockMu sync.RWMutex - bestBidBlock map[common.Hash]*types.DecodedBidBlock // parentHash -> best bid block - newBidBlockCh chan newBidBlockPackage // channel for incoming bid blocks + bestBidBlock map[common.Hash]*buildertypes.DecodedBidBlock // parentHash -> best bid block + newBidBlockCh chan newBidBlockPackage // channel for incoming bid blocks // distinct registered builders that have sent BidBlock since node start bidBlockBuildersMu sync.Mutex @@ -196,10 +197,10 @@ func newBidSimulator( newBidCh: make(chan newBidPackage, 100), pending: make(map[uint64]map[common.Address]map[common.Hash]struct{}), bestBid: make(map[common.Hash]*BidRuntime), - bestBidToRun: make(map[common.Hash]*types.Bid), + bestBidToRun: make(map[common.Hash]*buildertypes.Bid), simulatingBid: make(map[common.Hash]*BidRuntime), bidsToSim: make(map[uint64][]*BidRuntime), - bestBidBlock: make(map[common.Hash]*types.DecodedBidBlock), + bestBidBlock: make(map[common.Hash]*buildertypes.DecodedBidBlock), newBidBlockCh: make(chan newBidBlockPackage, 100), bidBlockBuilders: make(map[common.Address]struct{}), } @@ -336,7 +337,7 @@ func (b *bidSimulator) GetBestBid(prevBlockHash common.Hash) *BidRuntime { } // best bid to run is based on bid's expectedBlockReward before the bid is simulated -func (b *bidSimulator) SetBestBidToRun(prevBlockHash common.Hash, bid *types.Bid) { +func (b *bidSimulator) SetBestBidToRun(prevBlockHash common.Hash, bid *buildertypes.Bid) { b.bestBidMu.Lock() defer b.bestBidMu.Unlock() @@ -344,7 +345,7 @@ func (b *bidSimulator) SetBestBidToRun(prevBlockHash common.Hash, bid *types.Bid } // in case the bid is invalid(invalid GasUsed,Reward,GasPrice...), remove it. -func (b *bidSimulator) DelBestBidToRun(prevBlockHash common.Hash, delBid *types.Bid) { +func (b *bidSimulator) DelBestBidToRun(prevBlockHash common.Hash, delBid *buildertypes.Bid) { b.bestBidMu.Lock() defer b.bestBidMu.Unlock() cur := b.bestBidToRun[prevBlockHash] @@ -356,7 +357,7 @@ func (b *bidSimulator) DelBestBidToRun(prevBlockHash common.Hash, delBid *types. } } -func (b *bidSimulator) GetBestBidToRun(prevBlockHash common.Hash) *types.Bid { +func (b *bidSimulator) GetBestBidToRun(prevBlockHash common.Hash) *buildertypes.Bid { b.bestBidMu.RLock() defer b.bestBidMu.RUnlock() @@ -575,7 +576,7 @@ func (b *bidSimulator) getBlockInterval(parentHeader *types.Header) uint64 { } // checkIfBidExceedsTxGasLimit checks whether any transaction in the bid exceeds the max txn gas. -func (b *bidSimulator) checkIfBidExceedsTxGasLimit(bid *types.Bid) error { +func (b *bidSimulator) checkIfBidExceedsTxGasLimit(bid *buildertypes.Bid) error { currentHeader := b.chain.CurrentBlock() if !b.chainConfig.IsOsaka(currentHeader.Number, currentHeader.Time) { return nil @@ -678,7 +679,7 @@ func (b *bidSimulator) clearLoop() { } // AddBidBlock keeps the best BidBlock for a given parent hash. -func (b *bidSimulator) AddBidBlock(parentHash common.Hash, block *types.DecodedBidBlock) error { +func (b *bidSimulator) AddBidBlock(parentHash common.Hash, block *buildertypes.DecodedBidBlock) error { b.bestBidBlockMu.Lock() defer b.bestBidBlockMu.Unlock() @@ -691,7 +692,7 @@ func (b *bidSimulator) AddBidBlock(parentHash common.Hash, block *types.DecodedB } // GetBestBidBlock returns the best BidBlock for a given parent hash. -func (b *bidSimulator) GetBestBidBlock(parentHash common.Hash) *types.DecodedBidBlock { +func (b *bidSimulator) GetBestBidBlock(parentHash common.Hash) *buildertypes.DecodedBidBlock { b.bestBidBlockMu.RLock() defer b.bestBidBlockMu.RUnlock() return b.bestBidBlock[parentHash] @@ -709,7 +710,7 @@ func (b *bidSimulator) recordBidBlockBuilder(builder common.Address) { } // preSealVerifyBidBlock validates a BidBlock before admission. -func (b *bidSimulator) preSealVerifyBidBlock(decoded *types.DecodedBidBlock) error { +func (b *bidSimulator) preSealVerifyBidBlock(decoded *buildertypes.DecodedBidBlock) error { start := time.Now() defer bidBlockPreSealVerifyTimer.UpdateSince(start) parliaEngine, ok := b.engine.(*parlia.Parlia) @@ -763,7 +764,7 @@ func (b *bidSimulator) preSealVerifyBidBlock(decoded *types.DecodedBidBlock) err } // validateBidBlockBlobSidecars checks cheap sidecar invariants before bid selection. -func (b *bidSimulator) validateBidBlockBlobSidecars(decoded *types.DecodedBidBlock) error { +func (b *bidSimulator) validateBidBlockBlobSidecars(decoded *buildertypes.DecodedBidBlock) error { header := decoded.Header blobEligibleBlock := eip4844.IsBlobEligibleBlock(b.chainConfig, header.Number.Uint64(), header.Time) maxBlobsPerBlock := eip4844.MaxBlobsPerBlock(b.chainConfig, header.Time) @@ -810,7 +811,7 @@ func (b *bidSimulator) validateBidBlockBlobSidecars(decoded *types.DecodedBidBlo } // sendBidBlock queues a decoded BidBlock for selection. -func (b *bidSimulator) sendBidBlock(_ context.Context, block *types.DecodedBidBlock) error { +func (b *bidSimulator) sendBidBlock(_ context.Context, block *buildertypes.DecodedBidBlock) error { timer := time.NewTimer(1 * time.Second) defer timer.Stop() @@ -820,14 +821,14 @@ func (b *bidSimulator) sendBidBlock(_ context.Context, block *types.DecodedBidBl case b.newBidBlockCh <- newBidBlockPackage{bidBlock: block, feedback: replyCh}: b.AddPending(block.BlockNumber(), block.Builder, block.Hash()) case <-timer.C: - return types.ErrMevBusy + return buildertypes.ErrMevBusy } select { case reply := <-replyCh: return reply case <-timer.C: - return types.ErrMevBusy + return buildertypes.ErrMevBusy } } @@ -890,7 +891,7 @@ func (b *bidSimulator) newBidBlockLoop() { // sendBid checks if the bid is already exists or if the builder sends too many bids, // if yes, return error, if not, add bid into newBid chan waiting for judge profit. -func (b *bidSimulator) sendBid(ctx context.Context, bid *types.Bid) error { +func (b *bidSimulator) sendBid(ctx context.Context, bid *buildertypes.Bid) error { timer := time.NewTimer(1 * time.Second) defer timer.Stop() @@ -907,14 +908,14 @@ func (b *bidSimulator) sendBid(ctx context.Context, bid *types.Bid) error { case b.newBidCh <- newBidPackage{bid: bid, feedback: replyCh, receiveTime: receiveTime}: b.AddPending(bid.BlockNumber, bid.Builder, bid.Hash()) case <-timer.C: - return types.ErrMevBusy + return buildertypes.ErrMevBusy } select { case reply := <-replyCh: return reply case <-timer.C: - return types.ErrMevBusy + return buildertypes.ErrMevBusy } } @@ -1246,7 +1247,7 @@ func (b *bidSimulator) reportIssue(bidRuntime *BidRuntime, err error) { cli := b.builders[bidRuntime.bid.Builder] if cli != nil { - err = cli.ReportIssue(context.Background(), &types.BidIssue{ + err = cli.ReportIssue(context.Background(), &buildertypes.BidIssue{ Validator: bidRuntime.env.header.Coinbase, Builder: bidRuntime.bid.Builder, BidHash: bidRuntime.bid.Hash(), @@ -1260,7 +1261,7 @@ func (b *bidSimulator) reportIssue(bidRuntime *BidRuntime, err error) { } type BidRuntime struct { - bid *types.Bid + bid *buildertypes.Bid env *environment @@ -1276,7 +1277,7 @@ type BidRuntime struct { greedyMerged bool } -func newBidRuntime(newBid *types.Bid, validatorCommission uint64) (*BidRuntime, error) { +func newBidRuntime(newBid *buildertypes.Bid, validatorCommission uint64) (*BidRuntime, error) { // check the block reward and validator reward of the newBid expectedBlockReward := newBid.GasFee expectedValidatorReward := new(big.Int).Mul(expectedBlockReward, big.NewInt(int64(validatorCommission))) diff --git a/miner/builderclient/builderclient.go b/miner/builderclient/builderclient.go index 9606a92d95..80e9953264 100644 --- a/miner/builderclient/builderclient.go +++ b/miner/builderclient/builderclient.go @@ -3,7 +3,7 @@ package builderclient import ( "context" - "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/rpc" ) @@ -28,6 +28,6 @@ func newClient(c *rpc.Client) *Client { } // ReportIssue reports an issue -func (ec *Client) ReportIssue(ctx context.Context, args *types.BidIssue) error { +func (ec *Client) ReportIssue(ctx context.Context, args *buildertypes.BidIssue) error { return ec.c.CallContext(ctx, nil, "mev_reportIssue", args) } diff --git a/miner/miner_mev.go b/miner/miner_mev.go index 85c01b48c0..c17e45088b 100644 --- a/miner/miner_mev.go +++ b/miner/miner_mev.go @@ -11,6 +11,7 @@ import ( "github.com/ethereum/go-ethereum/consensus/parlia" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/internal/version" "github.com/ethereum/go-ethereum/log" ) @@ -50,7 +51,7 @@ func (miner *Miner) HasBuilder(builder common.Address) bool { return miner.bidSimulator.ExistBuilder(builder) } -func (miner *Miner) GetBidBlockPermission(builder common.Address) types.BidBlockPermissionStatus { +func (miner *Miner) GetBidBlockPermission(builder common.Address) buildertypes.BidBlockPermissionStatus { return miner.worker.permMgr.GetStatus(builder) } @@ -71,9 +72,9 @@ func (miner *Miner) bidBlockPasteurActive() bool { return head != nil && miner.worker.chainConfig.IsPasteur(head.Number, head.Time) } -func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) (common.Hash, error) { +func (miner *Miner) SendBidBlock(ctx context.Context, args *buildertypes.BidBlockArgs) (common.Hash, error) { if !miner.bidBlockEnabled() { - return common.Hash{}, types.NewInvalidBidError("BidBlock disabled, fallback to SendBid") + return common.Hash{}, buildertypes.NewInvalidBidError("BidBlock disabled, fallback to SendBid") } bb := args.BidBlock @@ -81,7 +82,7 @@ func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) builder, err := args.EcrecoverSender() if err != nil { - return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("invalid signature: bidHash=%s, err=%v", bidHash, err)) + return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf("invalid signature: bidHash=%s, err=%v", bidHash, err)) } // Receive marker for the mev-sentry -> validator hop: correlate this bidHash with @@ -94,22 +95,22 @@ func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) "txs", len(bb.Transactions)) if !miner.bidSimulator.ExistBuilder(builder) { - return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("builder is not registered: builder=%s, bidHash=%s", builder, bidHash)) + return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf("builder is not registered: builder=%s, bidHash=%s", builder, bidHash)) } miner.bidSimulator.recordBidBlockBuilder(builder) // Check permission before CheckPending so rejected BidBlocks do not use quota. if !miner.worker.permMgr.IsAllowed(builder) { - return common.Hash{}, types.NewBidBlockPermissionRevokedError("builder BidBlock permission revoked, fallback to SendBid") + return common.Hash{}, buildertypes.NewBidBlockPermissionRevokedError("builder BidBlock permission revoked, fallback to SendBid") } if len(bb.Transactions) == 0 { - return common.Hash{}, types.NewInvalidBidError("empty BidBlock txs") + return common.Hash{}, buildertypes.NewInvalidBidError("empty BidBlock txs") } blockNumber := bb.Header.Number.Uint64() parentHash := bb.Header.ParentHash if miner.bidSimulator.chain.GetHeaderByHash(parentHash) == nil { - return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("parent not found: %s, bidHash=%s", parentHash.Hex(), bidHash)) + return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf("parent not found: %s, bidHash=%s", parentHash.Hex(), bidHash)) } if err := miner.bidSimulator.CheckPending(blockNumber, builder, bidHash); err != nil { return common.Hash{}, err @@ -117,13 +118,13 @@ func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) bidMustBefore := miner.bidSimulator.bidMustBefore(parentHash) if timeout := time.Until(bidMustBefore); timeout <= 0 { - return common.Hash{}, types.NewBidBlockTooLateError(fmt.Sprintf("too late, expected before %s, appeared %s later, bidHash=%s", + return common.Hash{}, buildertypes.NewBidBlockTooLateError(fmt.Sprintf("too late, expected before %s, appeared %s later, bidHash=%s", bidMustBefore, common.PrettyDuration(timeout), bidHash)) } decoded, err := args.ToDecodedBidBlock(builder) if err != nil { - return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("failed to decode bid block: bidHash=%s, err=%v", bidHash, err)) + return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf("failed to decode bid block: bidHash=%s, err=%v", bidHash, err)) } // Validator owns the entire Extra: overwrite builder's bytes with the operator-configured @@ -138,7 +139,7 @@ func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) decoded.Header.Extra = common.CopyBytes(miner.worker.extra) miner.worker.confMu.RUnlock() if err := parliaEngine.SetExtraData(miner.worker.chain, decoded.Header); err != nil { - return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("set extra data: %v", err)) + return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf("set extra data: %v", err)) } // Record MEV v2 (bidblock path) source and builder address. setBidMevInfo(decoded.Header, builder, true) @@ -149,7 +150,7 @@ func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) "builder", builder, "bidHash", decoded.Hash(), "err", err) - return common.Hash{}, types.NewBidBlockPreSealVerifyError(fmt.Sprintf("pre-seal verify failed: bidHash=%s, err=%v", bidHash, err)) + return common.Hash{}, buildertypes.NewBidBlockPreSealVerifyError(fmt.Sprintf("pre-seal verify failed: bidHash=%s, err=%v", bidHash, err)) } if receiveTime, ok := ctx.Value("receiveTime").(int64); ok { bidBlockPreCheckTimer.UpdateSince(time.UnixMilli(receiveTime)) @@ -162,14 +163,14 @@ func (miner *Miner) SendBidBlock(ctx context.Context, args *types.BidBlockArgs) return bidHash, nil } -func (miner *Miner) SendBid(ctx context.Context, bidArgs *types.BidArgs) (common.Hash, error) { +func (miner *Miner) SendBid(ctx context.Context, bidArgs *buildertypes.BidArgs) (common.Hash, error) { builder, err := bidArgs.EcrecoverSender() if err != nil { - return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("invalid signature:%v", err)) + return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf("invalid signature:%v", err)) } if !miner.bidSimulator.ExistBuilder(builder) { - return common.Hash{}, types.NewInvalidBidError("builder is not registered") + return common.Hash{}, buildertypes.NewInvalidBidError("builder is not registered") } err = miner.bidSimulator.CheckPending(bidArgs.RawBid.BlockNumber, builder, bidArgs.RawBid.Hash()) @@ -180,7 +181,7 @@ func (miner *Miner) SendBid(ctx context.Context, bidArgs *types.BidArgs) (common signer := types.MakeSigner(miner.worker.chainConfig, big.NewInt(int64(bidArgs.RawBid.BlockNumber)), uint64(time.Now().Unix())) bid, err := bidArgs.ToBid(builder, signer) if err != nil { - return common.Hash{}, types.NewInvalidBidError(fmt.Sprintf("fail to convert bidArgs to bid, %v", err)) + return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf("fail to convert bidArgs to bid, %v", err)) } bidBetterBefore := miner.bidSimulator.bidBetterBefore(bidArgs.RawBid.ParentHash) @@ -203,7 +204,7 @@ func (miner *Miner) SendBid(ctx context.Context, bidArgs *types.BidArgs) (common // startAsyncBlobValidation uses a fixed-size worker pool to validate blob // transactions in the background (field checks + KZG proof verification). // Results are stored per-tx in bid.BlobValResults keyed by tx hash. -func startAsyncBlobValidation(bid *types.Bid) { +func startAsyncBlobValidation(bid *buildertypes.Bid) { type blobJob struct { tx *types.Transaction ch chan error @@ -245,14 +246,14 @@ func startAsyncBlobValidation(bid *types.Bid) { } } -func (miner *Miner) MevParams() *types.MevParams { +func (miner *Miner) MevParams() *buildertypes.MevParams { builderFeeCeil, ok := big.NewInt(0).SetString(*miner.worker.config.Mev.BuilderFeeCeil, 10) if !ok { log.Error("failed to parse builder fee ceil", "BuilderFeeCeil", *miner.worker.config.Mev.BuilderFeeCeil) return nil } - return &types.MevParams{ + return &buildertypes.MevParams{ ValidatorCommission: *miner.worker.config.Mev.ValidatorCommission, BidSimulationLeftOver: *miner.worker.config.Mev.BidSimulationLeftOver, NoInterruptLeftOver: *miner.worker.config.Mev.NoInterruptLeftOver, diff --git a/miner/miner_mev_test.go b/miner/miner_mev_test.go index 38a0f69f23..96f425d004 100644 --- a/miner/miner_mev_test.go +++ b/miner/miner_mev_test.go @@ -9,6 +9,7 @@ import ( "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" gokzg4844 "github.com/crate-crypto/go-eth-kzg" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/params" @@ -74,7 +75,7 @@ func TestStartAsyncBlobValidation_InvalidProof(t *testing.T) { sidecar.Proofs[0][0] ^= 0xff tx := makeSignedBlobTx(0, sidecar) - bid := &types.Bid{ + bid := &buildertypes.Bid{ Txs: types.Transactions{tx}, } startAsyncBlobValidation(bid) diff --git a/miner/worker.go b/miner/worker.go index 6b3fb1dc44..93a79b1618 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -40,6 +40,7 @@ import ( "github.com/ethereum/go-ethereum/core/systemcontracts" "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/event" "github.com/ethereum/go-ethereum/log" @@ -189,7 +190,7 @@ type getWorkReq struct { type bidFetcher interface { GetBestBid(parentHash common.Hash) *BidRuntime GetSimulatingBid(prevBlockHash common.Hash) *BidRuntime - GetBestBidBlock(parentHash common.Hash) *types.DecodedBidBlock + GetBestBidBlock(parentHash common.Hash) *buildertypes.DecodedBidBlock } // worker is the main object which takes care of submitting new work to consensus engine @@ -1429,7 +1430,7 @@ LOOP: // when out-turn, use bestWork to prevent bundle leakage. // when in-turn, compare with remote work. var bestBid *BidRuntime - var bestBidBlock *types.DecodedBidBlock + var bestBidBlock *buildertypes.DecodedBidBlock var bidBlockCommitted bool var bidBlockFallback bool var simBidBlockReward *uint256.Int diff --git a/miner/worker_test.go b/miner/worker_test.go index e4041f6465..cc1f241bef 100644 --- a/miner/worker_test.go +++ b/miner/worker_test.go @@ -33,6 +33,7 @@ import ( "github.com/ethereum/go-ethereum/core/txpool" "github.com/ethereum/go-ethereum/core/txpool/legacypool" "github.com/ethereum/go-ethereum/core/types" + buildertypes "github.com/ethereum/go-ethereum/core/types/builder" "github.com/ethereum/go-ethereum/crypto" "github.com/ethereum/go-ethereum/ethdb" "github.com/ethereum/go-ethereum/event" @@ -244,7 +245,7 @@ func TestCommitBidBlockPreservesBuilderExecutionHeaderFields(t *testing.T) { bloom[0] = 0x33 builderUncleHash := common.Hash{0xbb} - decoded := &types.DecodedBidBlock{ + decoded := &buildertypes.DecodedBidBlock{ Header: &types.Header{ Number: big.NewInt(1), ParentHash: chain.Genesis().Hash(), diff --git a/params/protocol_params.go b/params/protocol_params.go index a5311e934c..ec68d95fa8 100644 --- a/params/protocol_params.go +++ b/params/protocol_params.go @@ -27,7 +27,7 @@ const ( MinGasLimit uint64 = 5000 // Minimum the gas limit may ever be. MaxGasLimit uint64 = 0x7fffffffffffffff // Maximum the gas limit (2^63-1). GenesisGasLimit uint64 = 4712388 // Gas limit of the Genesis block. - PayBidTxGasLimit uint64 = 25000 // Gas limit of the PayBidTx in the types.BidArgs. + PayBidTxGasLimit uint64 = 25000 // Gas limit of the PayBidTx in the builder.BidArgs. MaxTxGas uint64 = 1 << 24 // Maximum transaction gas limit after eip-7825 (16,777,216). MaximumExtraDataSize uint64 = 32 // Maximum size extra data may be after Genesis. From 37c6483306ecb238c044c013a02a79ce6c1d11c5 Mon Sep 17 00:00:00 2001 From: wayen <19421226+flywukong@users.noreply.github.com> Date: Fri, 3 Jul 2026 11:42:50 +0800 Subject: [PATCH 46/48] miner: disable BidBlock on hard-fork activation blocks (#3741) --- miner/miner_mev.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/miner/miner_mev.go b/miner/miner_mev.go index c17e45088b..cd52399639 100644 --- a/miner/miner_mev.go +++ b/miner/miner_mev.go @@ -109,9 +109,16 @@ func (miner *Miner) SendBidBlock(ctx context.Context, args *buildertypes.BidBloc } blockNumber := bb.Header.Number.Uint64() parentHash := bb.Header.ParentHash - if miner.bidSimulator.chain.GetHeaderByHash(parentHash) == nil { + parent := miner.bidSimulator.chain.GetHeaderByHash(parentHash) + if parent == nil { return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf("parent not found: %s, bidHash=%s", parentHash.Hex(), bidHash)) } + + // Security: validators must self-produce hard-fork activation blocks. + if miner.worker.chainConfig.IsOnPasteur(bb.Header.Number, parent.Time, bb.Header.Time) { + return common.Hash{}, buildertypes.NewInvalidBidError(fmt.Sprintf( + "BidBlock disabled on hard-fork activation block %d, fallback to SendBid", blockNumber)) + } if err := miner.bidSimulator.CheckPending(blockNumber, builder, bidHash); err != nil { return common.Hash{}, err } From 22387b2a643e1777b23a6c62da076ff2c8f70ae0 Mon Sep 17 00:00:00 2001 From: wayen <19421226+flywukong@users.noreply.github.com> Date: Fri, 3 Jul 2026 15:07:23 +0800 Subject: [PATCH 47/48] miner: optimize BidBlock signing hash (#3742) * core/types: optimize BidBlock signing hash * core/types: use header hash for BidBlock signing --- core/types/builder/bid.go | 9 +++++++-- miner/bid_simulator.go | 4 ++++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/core/types/builder/bid.go b/core/types/builder/bid.go index a4005ef1cc..32f932bf6e 100644 --- a/core/types/builder/bid.go +++ b/core/types/builder/bid.go @@ -12,6 +12,7 @@ import ( "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/crypto" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/rlp" ) @@ -263,12 +264,16 @@ type BidBlock struct { hash atomic.Value } -// Hash returns rlpHash over all BidBlock fields. This is what the builder signs. +// Hash returns the BidBlock signing hash. The header carries TxHash, and the +// validator checks TxHash against Transactions before blind-signing. func (b *BidBlock) Hash() common.Hash { if hash := b.hash.Load(); hash != nil { return hash.(common.Hash) } - h := rlpHash(b) + start := time.Now() + h := b.Header.Hash() + log.Debug("BidBlock Hash() computed", "number", b.Header.Number, "elapsed", time.Since(start), + "txs", len(b.Transactions), "sidecars", len(b.Sidecars)) b.hash.Store(h) return h } diff --git a/miner/bid_simulator.go b/miner/bid_simulator.go index 3124082f48..4046ac3238 100644 --- a/miner/bid_simulator.go +++ b/miner/bid_simulator.go @@ -30,6 +30,7 @@ import ( "github.com/ethereum/go-ethereum/miner/minerconfig" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/rpc" + "github.com/ethereum/go-ethereum/trie" ) const prefetchTxNumber = 50 @@ -737,6 +738,9 @@ func (b *bidSimulator) preSealVerifyBidBlock(decoded *buildertypes.DecodedBidBlo if err := parliaEngine.BlockTimeUpperCheck(b.chain, header); err != nil { return fmt.Errorf("invalid header: %v", err) } + if txHash := types.DeriveSha(decoded.Txs, trie.NewStackTrie(nil)); header.TxHash != txHash { + return fmt.Errorf("invalid tx root: got %s, want %s", header.TxHash, txHash) + } decoded.SystemTxStart, decoded.GasFee = parliaEngine.ExtractBidBlockDepositValue(decoded.Txs) From 052fe012faeb582a7eac2ed274b13ecf1b5e43c7 Mon Sep 17 00:00:00 2001 From: formless <213398294+allformless@users.noreply.github.com> Date: Wed, 8 Jul 2026 11:53:50 +0800 Subject: [PATCH 48/48] release: update changelog for release v1.7.6 (#3748) --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f56f2c0cb..87d62b1b43 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ v1.7.6 is for BSC Chapel testnet [Pasteur hardfork](https://github.com/bnb-chain - [\#3717](https://github.com/bnb-chain/bsc/pull/3717) params: move Pasteur next to Mendel - [\#3721](https://github.com/bnb-chain/bsc/pull/3721) core/systemcontracts: introduce Pasteur hardfork system-contract upgrade - [\#3727](https://github.com/bnb-chain/bsc/pull/3727) core/systemcontracts: point Pasteur CommitUrl to genesis-contract v1.2.6 +- [\#3741](https://github.com/bnb-chain/bsc/pull/3741) miner: disable BidBlock on hard-fork activation blocks +- [\#3742](https://github.com/bnb-chain/bsc/pull/3742) miner: optimize BidBlock signing hash ### BUGFIX - [\#3668](https://github.com/bnb-chain/bsc/pull/3668) eth/handler.go: add verify bal @@ -41,6 +43,7 @@ v1.7.6 is for BSC Chapel testnet [Pasteur hardfork](https://github.com/bnb-chain ### IMPROVEMENT - [\#3669](https://github.com/bnb-chain/bsc/pull/3669) miner: reduce local mining time for last block in one turn - [\#3694](https://github.com/bnb-chain/bsc/pull/3694) consensus/parlia: extract VerifyUnsealedHeader from verifyHeader +- [\#3736](https://github.com/bnb-chain/bsc/pull/3736) miner: add BidBlock verify metrics ### CLEAN UP - [\#3670](https://github.com/bnb-chain/bsc/pull/3670) triedb/pathdb: remove legacy field JournalFilePath @@ -50,6 +53,7 @@ v1.7.6 is for BSC Chapel testnet [Pasteur hardfork](https://github.com/bnb-chain - [\#3720](https://github.com/bnb-chain/bsc/pull/3720) core/rawdb: cleanup bep-592 bal key related - [\#3722](https://github.com/bnb-chain/bsc/pull/3722) core/txpool/legacypool: remove overflowpool for txs - [\#3728](https://github.com/bnb-chain/bsc/pull/3728) beacon, cmd: remove fake-beacon op-stack shim (revert #2678) +- [\#3739](https://github.com/bnb-chain/bsc/pull/3739) core/types: extract bid and block mev info into builder subpackage #### Deprecated Flags & Config Fields The following flags and config fields are removed or deprecated in this release. Please update your node configuration accordingly before upgrading: