From 0a8bda751e2ed56bd0d8cf9e86ae749e8d9bb234 Mon Sep 17 00:00:00 2001 From: a Date: Mon, 23 Oct 2023 21:23:54 +0200 Subject: [PATCH 01/44] mbps (#8564) --- cl/phase1/stages/stage_history_download.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/cl/phase1/stages/stage_history_download.go b/cl/phase1/stages/stage_history_download.go index 7ab307901d8..f8cc5c99c3a 100644 --- a/cl/phase1/stages/stage_history_download.go +++ b/cl/phase1/stages/stage_history_download.go @@ -88,12 +88,16 @@ func SpawnStageHistoryDownload(cfg StageHistoryReconstructionCfg, ctx context.Co return err } defer tx.Rollback() + + bytesReadIn15Seconds := atomic.Uint64{} // Set up onNewBlock callback cfg.downloader.SetOnNewBlock(func(blk *cltypes.SignedBeaconBlock) (finished bool, err error) { if blk.Version() >= clparams.BellatrixVersion { currEth1Progress.Store(int64(blk.Block.Body.ExecutionPayload.BlockNumber)) } + bytesReadIn15Seconds.Add(uint64(blk.EncodingSizeSSZ())) + slot := blk.Block.Slot if destinationSlot <= blk.Block.Slot { if err := cfg.db.WriteBlock(ctx, tx, blk, true); err != nil { @@ -128,6 +132,18 @@ func SpawnStageHistoryDownload(cfg StageHistoryReconstructionCfg, ctx context.Co logInterval := time.NewTicker(logIntervalTime) finishCh := make(chan struct{}) // Start logging thread + + go func() { + t := time.NewTicker(15 * time.Second) + for { + select { + case <-t.C: + bytesReadIn15Seconds.Store(0) + case <-ctx.Done(): + return + } + } + }() go func() { for { select { @@ -143,7 +159,8 @@ func SpawnStageHistoryDownload(cfg StageHistoryReconstructionCfg, ctx context.Co } logArgs := []interface{}{} currProgress := cfg.downloader.Progress() - speed := float64(prevProgress-currProgress) / float64(logIntervalTime/time.Second) + blockProgress := float64(prevProgress - currProgress) + speed := blockProgress / float64(logIntervalTime/time.Second) prevProgress = currProgress peerCount, err := cfg.downloader.Peers() if err != nil { @@ -153,6 +170,7 @@ func SpawnStageHistoryDownload(cfg StageHistoryReconstructionCfg, ctx context.Co "slot", currProgress, "blockNumber", currEth1Progress.Load(), "blk/sec", fmt.Sprintf("%.1f", speed), + "mbps/sec", fmt.Sprintf("%.4f", float64(bytesReadIn15Seconds.Load())/(1000*1000*15)), "peers", peerCount) logger.Info("Downloading History", logArgs...) case <-finishCh: From dd8920008fd3fac35a3605aa34b922b3a8ae06a5 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Tue, 24 Oct 2023 12:55:22 +0700 Subject: [PATCH 02/44] readme: faq on public rpc api (#8541) --- README.md | 77 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 40 insertions(+), 37 deletions(-) diff --git a/README.md b/README.md index 1cb2ddcbb3e..1e390308131 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,8 @@ System Requirements * Gnosis Chain Archive: 370GB (January 2023). -* Polygon Mainnet Archive: 5TB. (April 2022). `--prune.*.older 15768000`: 5.1Tb (Sept 2023). Polygon Mumbai Archive: 1TB. (April 2022). +* Polygon Mainnet Archive: 5TB. (April 2022). `--prune.*.older 15768000`: 5.1Tb (Sept 2023). Polygon Mumbai Archive: + 1TB. (April 2022). SSD or NVMe. Do not recommend HDD - on HDD Erigon will always stay N blocks behind chain tip, but not fall behind. Bear in mind that SSD performance deteriorates when close to capacity. @@ -111,7 +112,8 @@ Running `make help` will list and describe the convenience commands available in ### Datadir structure - chaindata: recent blocks, state, recent state history. low-latency disk recommended. -- snapshots: old blocks, old state history. can symlink/mount it to cheaper disk. mostly immutable. must have ~100gb free space (for merge recent files to bigger one). +- snapshots: old blocks, old state history. can symlink/mount it to cheaper disk. mostly immutable. must have ~100gb + free space (for merge recent files to bigger one). - temp: can grow to ~100gb, but usually empty. can symlink/mount it to cheaper disk. - txpool: pending transactions. safe to remove. - nodes: p2p peers. safe to remove. @@ -141,7 +143,9 @@ int value specifying the highest output log level: LvlTrace = 5 ``` -To set an output dir for logs to be collected on disk, please set `--log.dir.path` If you want to change the filename produced from `erigon` you should also set the `--log.dir.prefix` flag to an alternate name. The flag `--log.dir.verbosity` is +To set an output dir for logs to be collected on disk, please set `--log.dir.path` If you want to change the filename +produced from `erigon` you should also set the `--log.dir.prefix` flag to an alternate name. The +flag `--log.dir.verbosity` is also available to control the verbosity of this logging, with the same int value as above, or the string value e.g. ' debug' or 'info'. Default verbosity is 'debug' (4), for disk logging. @@ -530,13 +534,10 @@ Detailed explanation: [./docs/programmers_guide/db_faq.md](./docs/programmers_gu ### Default Ports and Firewalls - - #### `erigon` ports - | Component | Port | Protocol | Purpose | Should Expose | -| --------- | ----- | --------- | --------------------------- | ------------- | +|-----------|-------|-----------|-----------------------------|---------------| | engine | 9090 | TCP | gRPC Server | Private | | engine | 42069 | TCP & UDP | Snap sync (Bittorrent) | Public | | engine | 8551 | TCP | Engine API (JWT auth) | Private | @@ -545,40 +546,31 @@ Detailed explanation: [./docs/programmers_guide/db_faq.md](./docs/programmers_gu | sentry | 9091 | TCP | incoming gRPC Connections | Private | | rpcdaemon | 8545 | TCP | HTTP & WebSockets & GraphQL | Private | - - - Typically, 30303 and 30304 are exposed to the internet to allow incoming peering connections. 9090 is exposed only internally for rpcdaemon or other connections, (e.g. rpcdaemon -> erigon). Port 8551 (JWT authenticated) is exposed only internally for [Engine API] JSON-RPC queries from the Consensus Layer node. - - - - #### `caplin` ports + | Component | Port | Protocol | Purpose | Should Expose | -| --------- | ---- | -------- | ---------------- | ------------- | +|-----------|------|----------|------------------|---------------| | sentinel | 4000 | UDP | Peering | Public | | sentinel | 4001 | TCP | Peering | Public | If you are using `--internalcl` aka `caplin` as your consensus client, then also look at the chart above - #### `shared` ports -| Component | Port | Protocol | Purpose | Should Expose | -| --------- | ----- | --------- | --------------------------- | ------------- | -| all | 6060 | TCP | pprof | Private | -| all | 6060 | TCP | metrics | Private | - +| Component | Port | Protocol | Purpose | Should Expose | +|-----------|------|----------|---------|---------------| +| all | 6060 | TCP | pprof | Private | +| all | 6060 | TCP | metrics | Private | Optional flags can be enabled that enable pprof or metrics (or both) - however, they both run on 6060 by default, so you'll have to change one if you want to run both at the same time. use `--help` with the binary for more info. - #### `other` ports Reserved for future use: **gRPC ports**: `9092` consensus engine, `9093` snapshot downloader, `9094` TxPool @@ -606,15 +598,16 @@ Device Benchmark Testing RFC 2544 RFC 922, Section 7 ``` -Same in [IpTables syntax](https://ethereum.stackexchange.com/questions/6386/how-to-prevent-being-blacklisted-for-running-an-ethereum-client/13068#13068) +Same +in [IpTables syntax](https://ethereum.stackexchange.com/questions/6386/how-to-prevent-being-blacklisted-for-running-an-ethereum-client/13068#13068) ### How to get diagnostic for bug report? - Get stack trace: `kill -SIGUSR1 `, get trace and stop: `kill -6 ` - Get CPU profiling: add `--pprof flag` - run `go tool pprof -png http://127.0.0.1:6060/debug/pprof/profile\?seconds\=20 > cpu.png` + run `go tool pprof -png http://127.0.0.1:6060/debug/pprof/profile\?seconds\=20 > cpu.png` - Get RAM profiling: add `--pprof flag` - run `go tool pprof -inuse_space -png http://127.0.0.1:6060/debug/pprof/heap > mem.png` + run `go tool pprof -inuse_space -png http://127.0.0.1:6060/debug/pprof/heap > mem.png` ### How to run local devnet? @@ -628,6 +621,13 @@ UID/GID (1000). More details in [post](https://www.fullstaq.com/knowledge-hub/blogs/docker-and-the-host-filesystem-owner-matching-problem) +### How to run public RPC api + +- `--txpool.nolocals=true` +- don't add `admin` in `--http.api` list +- to increase throughput may need + increase/decrease: `--db.read.concurrency`, `--rpc.batch.concurrency`, `--rpc.batch.limit` + ### Run RaspberyPI https://github.com/mathMakesArt/Erigon-on-RPi-4 @@ -642,7 +642,8 @@ Getting in touch ### Erigon Discord Server -The main discussions are happening on our Discord server. To get an invite, send an email to `bloxster [at] proton.me` with +The main discussions are happening on our Discord server. To get an invite, send an email to `bloxster [at] proton.me` +with your name, occupation, a brief explanation of why you want to join the Discord, and how you heard about Erigon. ### Reporting security issues/concerns @@ -669,20 +670,22 @@ Next tools show correct memory usage of Erigon: - `vmmap -summary PID | grep -i "Physical footprint"`. Without `grep` you can see details - `section MALLOC ZONE column Resident Size` shows App memory usage, `section REGION TYPE column Resident Size` - shows OS pages cache size. + shows OS pages cache size. - `Prometheus` dashboard shows memory of Go app without OS pages cache (`make prometheus`, open in - browser `localhost:3000`, credentials `admin/admin`) + browser `localhost:3000`, credentials `admin/admin`) - `cat /proc//smaps` - Erigon uses ~4Gb of RAM during genesis sync and ~1Gb during normal work. OS pages cache can utilize unlimited amount of - memory. - - **Warning:** Multiple instances of Erigon on same machine will touch Disk concurrently, it impacts performance - one of - main Erigon optimisations: "reduce Disk random access". - "Blocks Execution stage" still does many random reads - this is reason why it's slowest stage. We do not recommend - running - multiple genesis syncs on same Disk. If genesis sync passed, then it's fine to run multiple Erigon instances on same - Disk. + Erigon uses ~4Gb of RAM during genesis sync and ~1Gb during normal work. OS pages cache can utilize unlimited amount + of + memory. + + **Warning:** Multiple instances of Erigon on same machine will touch Disk concurrently, it impacts performance - one + of + main Erigon optimisations: "reduce Disk random access". + "Blocks Execution stage" still does many random reads - this is reason why it's slowest stage. We do not recommend + running + multiple genesis syncs on same Disk. If genesis sync passed, then it's fine to run multiple Erigon instances on same + Disk. ### Blocks Execution is slow on cloud-network-drives From e42642e353c82088f1887492268b94d0162a9904 Mon Sep 17 00:00:00 2001 From: lupin012 <58134934+lupin012@users.noreply.github.com> Date: Tue, 24 Oct 2023 07:55:33 +0200 Subject: [PATCH 03/44] rpctest: Fix error mgt from bench1 to bench9 (#8548) --- cmd/rpctest/main.go | 40 +++++++++++++---- cmd/rpctest/rpctest/bench1.go | 85 +++++++++++++---------------------- cmd/rpctest/rpctest/bench2.go | 21 ++++----- cmd/rpctest/rpctest/bench3.go | 38 ++++++---------- cmd/rpctest/rpctest/bench4.go | 12 +++-- cmd/rpctest/rpctest/bench5.go | 9 ++-- cmd/rpctest/rpctest/bench6.go | 18 +++----- cmd/rpctest/rpctest/bench7.go | 11 +++-- cmd/rpctest/rpctest/bench9.go | 18 +++----- 9 files changed, 112 insertions(+), 140 deletions(-) diff --git a/cmd/rpctest/main.go b/cmd/rpctest/main.go index 4c8af1cb808..5ce6a6c71ab 100644 --- a/cmd/rpctest/main.go +++ b/cmd/rpctest/main.go @@ -113,7 +113,10 @@ func main() { Short: "", Long: ``, Run: func(cmd *cobra.Command, args []string) { - rpctest.Bench1(erigonURL, gethURL, needCompare, fullTest, blockFrom, blockTo, recordFile) + err := rpctest.Bench1(erigonURL, gethURL, needCompare, fullTest, blockFrom, blockTo, recordFile) + if err != nil { + logger.Error(err.Error()) + } }, } with(bench1Cmd, withErigonUrl, withGethUrl, withNeedCompare, withBlockNum, withRecord) @@ -124,7 +127,10 @@ func main() { Short: "", Long: ``, Run: func(cmd *cobra.Command, args []string) { - rpctest.Bench2(erigonURL) + err := rpctest.Bench2(erigonURL) + if err != nil { + logger.Error(err.Error()) + } }, } var bench3Cmd = &cobra.Command{ @@ -132,7 +138,10 @@ func main() { Short: "", Long: ``, Run: func(cmd *cobra.Command, args []string) { - rpctest.Bench3(erigonURL, gethURL) + err := rpctest.Bench3(erigonURL, gethURL) + if err != nil { + logger.Error(err.Error()) + } }, } with(bench3Cmd, withErigonUrl, withGethUrl) @@ -142,7 +151,10 @@ func main() { Short: "", Long: ``, Run: func(cmd *cobra.Command, args []string) { - rpctest.Bench4(erigonURL) + err := rpctest.Bench4(erigonURL) + if err != nil { + logger.Error(err.Error()) + } }, } with(bench4Cmd, withErigonUrl) @@ -152,7 +164,10 @@ func main() { Short: "", Long: ``, Run: func(cmd *cobra.Command, args []string) { - rpctest.Bench5(erigonURL) + err := rpctest.Bench5(erigonURL) + if err != nil { + logger.Error(err.Error()) + } }, } with(bench5Cmd, withErigonUrl) @@ -161,7 +176,10 @@ func main() { Short: "", Long: ``, Run: func(cmd *cobra.Command, args []string) { - rpctest.Bench6(erigonURL) + err := rpctest.Bench6(erigonURL) + if err != nil { + logger.Error(err.Error()) + } }, } with(bench6Cmd, withErigonUrl) @@ -171,7 +189,10 @@ func main() { Short: "", Long: ``, Run: func(cmd *cobra.Command, args []string) { - rpctest.Bench7(erigonURL, gethURL) + err := rpctest.Bench7(erigonURL, gethURL) + if err != nil { + logger.Error(err.Error()) + } }, } with(bench7Cmd, withErigonUrl, withGethUrl) @@ -191,7 +212,10 @@ func main() { Short: "", Long: ``, Run: func(cmd *cobra.Command, args []string) { - rpctest.Bench9(erigonURL, gethURL, needCompare) + err := rpctest.Bench9(erigonURL, gethURL, needCompare) + if err != nil { + logger.Error(err.Error()) + } }, } with(bench9Cmd, withErigonUrl, withGethUrl, withNeedCompare) diff --git a/cmd/rpctest/rpctest/bench1.go b/cmd/rpctest/rpctest/bench1.go index 400e64c19de..bacadf422bf 100644 --- a/cmd/rpctest/rpctest/bench1.go +++ b/cmd/rpctest/rpctest/bench1.go @@ -24,7 +24,7 @@ var routes map[string]string // use false value - to generate vegeta files, it's faster but we can generate vegeta files for Geth and Erigon // // fullTest - if false - then call only methods which RPCDaemon currently supports -func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFrom uint64, blockTo uint64, recordFile string) { +func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFrom uint64, blockTo uint64, recordFileName string) error { setRoutes(erigonURL, gethURL) var client = &http.Client{ Timeout: time.Second * 600, @@ -44,12 +44,10 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Erigon("eth_blockNumber", reqGen.blockNumber(), &blockNumber) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not get block number: %v\n", res.Err) - return + return fmt.Errorf("Could not get block number: %v\n", res.Err) } if blockNumber.Error != nil { - fmt.Printf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message) - return + return fmt.Errorf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message) } fmt.Printf("Last block: %d\n", blockNumber.Number) accounts := make(map[libcommon.Address]struct{}) @@ -61,8 +59,7 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Erigon("eth_getBlockByNumber", reqGen.getBlockByNumber(bn, true /* withTxs */), &b) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not retrieve block (Erigon) %d: %v\n", bn, res.Err) - return + return fmt.Errorf("Could not retrieve block (Erigon) %d: %v\n", bn, res.Err) } if b.Error != nil { @@ -73,16 +70,13 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro var bg EthBlockByNumber res = reqGen.Geth("eth_getBlockByNumber", reqGen.getBlockByNumber(bn, true /* withTxs */), &bg) if res.Err != nil { - fmt.Printf("Could not retrieve block (geth) %d: %v\n", bn, res.Err) - return + return fmt.Errorf("Could not retrieve block (geth) %d: %v\n", bn, res.Err) } if bg.Error != nil { - fmt.Printf("Error retrieving block (geth): %d %s\n", bg.Error.Code, bg.Error.Message) - return + return fmt.Errorf("Error retrieving block (geth): %d %s\n", bg.Error.Code, bg.Error.Message) } if !compareBlocks(&b, &bg) { - fmt.Printf("Block difference for %d\n", bn) - return + return fmt.Errorf("Block difference for %d\n", bn) } } @@ -108,12 +102,10 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Erigon("debug_storageRangeAt", reqGen.storageRangeAt(b.Result.Hash, i, tx.To, *nextKey), &sr) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not get storageRange (Erigon): %s: %v\n", tx.Hash, res.Err) - return + return fmt.Errorf("Could not get storageRange (Erigon): %s: %v\n", tx.Hash, res.Err) } if sr.Error != nil { - fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message) - return + return fmt.Errorf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message) } for k, v := range sr.Result.Storage { @@ -132,8 +124,7 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Geth("debug_storageRangeAt", reqGen.storageRangeAt(b.Result.Hash, i, tx.To, *nextKeyG), &srGeth) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not get storageRange (geth): %s: %v\n", tx.Hash, res.Err) - return + return fmt.Errorf("Could not get storageRange (geth): %s: %v\n", tx.Hash, res.Err) } if srGeth.Error != nil { fmt.Printf("Error getting storageRange (geth): %d %s\n", srGeth.Error.Code, srGeth.Error.Message) @@ -154,7 +145,7 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro printStorageRange(sm) fmt.Printf("================smg\n") printStorageRange(smg) - return + return fmt.Errorf("Storage range different\n") } } } @@ -183,18 +174,15 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Geth("debug_traceTransaction", reqGen.traceTransaction(tx.Hash), &traceg) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not trace transaction (geth) %s: %v\n", tx.Hash, res.Err) print(client, routes[Geth], reqGen.traceTransaction(tx.Hash)) - return + return fmt.Errorf("Could not trace transaction (geth) %s: %v\n", tx.Hash, res.Err) } if traceg.Error != nil { - fmt.Printf("Error tracing transaction (geth): %d %s\n", traceg.Error.Code, traceg.Error.Message) - return + return fmt.Errorf("Error tracing transaction (geth): %d %s\n", traceg.Error.Code, traceg.Error.Message) } if res.Err == nil && trace.Error == nil { if !compareTraces(&trace, &traceg) { - fmt.Printf("Different traces block %d, tx %s\n", bn, tx.Hash) - return + return fmt.Errorf("Different traces block %d, tx %s\n", bn, tx.Hash) } } } @@ -204,32 +192,28 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Erigon("eth_getTransactionReceipt", reqGen.getTransactionReceipt(tx.Hash), &receipt) resultsCh <- res if res.Err != nil { - fmt.Printf("Count not get receipt (Erigon): %s: %v\n", tx.Hash, res.Err) print(client, routes[Erigon], reqGen.getTransactionReceipt(tx.Hash)) - return + return fmt.Errorf("Count not get receipt (Erigon): %s: %v\n", tx.Hash, res.Err) } if receipt.Error != nil { - fmt.Printf("Error getting receipt (Erigon): %d %s\n", receipt.Error.Code, receipt.Error.Message) - return + return fmt.Errorf("Error getting receipt (Erigon): %d %s\n", receipt.Error.Code, receipt.Error.Message) } if needCompare { var receiptg EthReceipt res = reqGen.Geth("eth_getTransactionReceipt", reqGen.getTransactionReceipt(tx.Hash), &receiptg) resultsCh <- res if res.Err != nil { - fmt.Printf("Count not get receipt (geth): %s: %v\n", tx.Hash, res.Err) print(client, routes[Geth], reqGen.getTransactionReceipt(tx.Hash)) - return + return fmt.Errorf("Count not get receipt (geth): %s: %v\n", tx.Hash, res.Err) } if receiptg.Error != nil { - fmt.Printf("Error getting receipt (geth): %d %s\n", receiptg.Error.Code, receiptg.Error.Message) - return + return fmt.Errorf("Error getting receipt (geth): %d %s\n", receiptg.Error.Code, receiptg.Error.Message) } if !compareReceipts(&receipt, &receiptg) { fmt.Printf("Different receipts block %d, tx %s\n", bn, tx.Hash) print(client, routes[Geth], reqGen.getTransactionReceipt(tx.Hash)) print(client, routes[Erigon], reqGen.getTransactionReceipt(tx.Hash)) - return + return fmt.Errorf("Receipts are different\n") } } } @@ -242,28 +226,23 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Erigon("eth_getBalance", reqGen.getBalance(b.Result.Miner, bn), &balance) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not get account balance (Erigon): %v\n", res.Err) - return + return fmt.Errorf("Could not get account balance (Erigon): %v\n", res.Err) } if balance.Error != nil { - fmt.Printf("Error getting account balance (Erigon): %d %s", balance.Error.Code, balance.Error.Message) - return + return fmt.Errorf("Error getting account balance (Erigon): %d %s", balance.Error.Code, balance.Error.Message) } if needCompare { var balanceg EthBalance res = reqGen.Geth("eth_getBalance", reqGen.getBalance(b.Result.Miner, bn), &balanceg) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not get account balance (geth): %v\n", res.Err) - return + return fmt.Errorf("Could not get account balance (geth): %v\n", res.Err) } if balanceg.Error != nil { - fmt.Printf("Error getting account balance (geth): %d %s\n", balanceg.Error.Code, balanceg.Error.Message) - return + return fmt.Errorf("Error getting account balance (geth): %d %s\n", balanceg.Error.Code, balanceg.Error.Message) } if !compareBalances(&balance, &balanceg) { - fmt.Printf("Miner %x balance difference for block %d\n", b.Result.Miner, bn) - return + return fmt.Errorf("Miner %x balance difference for block %d\n", b.Result.Miner, bn) } } @@ -274,12 +253,10 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Erigon("debug_getModifiedAccountsByNumber", reqGen.getModifiedAccountsByNumber(prevBn, bn), &mag) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not get modified accounts (Erigon): %v\n", res.Err) - return + return fmt.Errorf("Could not get modified accounts (Erigon): %v\n", res.Err) } if mag.Error != nil { - fmt.Printf("Error getting modified accounts (Erigon): %d %s\n", mag.Error.Code, mag.Error.Message) - return + return fmt.Errorf("Error getting modified accounts (Erigon): %d %s\n", mag.Error.Code, mag.Error.Message) } fmt.Printf("Done blocks %d-%d, modified accounts: %d\n", prevBn, bn, len(mag.Result)) @@ -298,8 +275,7 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro resultsCh <- res if res.Err != nil { - fmt.Printf("Could not get accountRange (Erigon): %v\n", res.Err) - return + return fmt.Errorf("Could not get accountRange (Erigon): %v\n", res.Err) } if sr.Error != nil { @@ -316,8 +292,7 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro res = reqGen.Geth("debug_accountRange", reqGen.accountRange(bn, pageGeth, 256), &srGeth) resultsCh <- res if res.Err != nil { - fmt.Printf("Could not get accountRange geth: %v\n", res.Err) - return + return fmt.Errorf("Could not get accountRange geth: %v\n", res.Err) } if srGeth.Error != nil { fmt.Printf("Error getting accountRange geth: %d %s\n", srGeth.Error.Code, srGeth.Error.Message) @@ -332,14 +307,14 @@ func Bench1(erigonURL, gethURL string, needCompare bool, fullTest bool, blockFro fmt.Printf("Different next page keys: %x geth %x", page, pageGeth) } if !compareAccountRanges(accRangeErigon, accRangeGeth) { - fmt.Printf("Different in account ranges tx\n") - return + return fmt.Errorf("Different in account ranges tx\n") } } } prevBn = bn } } + return nil } // vegetaWrite (to be run as a goroutine) writing results of server calls into several files: diff --git a/cmd/rpctest/rpctest/bench2.go b/cmd/rpctest/rpctest/bench2.go index 74165c14220..7dd73402800 100644 --- a/cmd/rpctest/rpctest/bench2.go +++ b/cmd/rpctest/rpctest/bench2.go @@ -10,7 +10,7 @@ import ( "github.com/ledgerwatch/erigon/crypto" ) -func Bench2(erigon_url string) { +func Bench2(erigon_url string) error { var client = &http.Client{ Timeout: time.Second * 600, } @@ -19,12 +19,10 @@ func Bench2(erigon_url string) { blockNumTemplate := `{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":%d}` var blockNumber EthBlockNumber if err := post(client, erigon_url, fmt.Sprintf(blockNumTemplate, req_id), &blockNumber); err != nil { - fmt.Printf("Could not get block number: %v\n", err) - return + return fmt.Errorf("Could not get block number: %v\n", err) } if blockNumber.Error != nil { - fmt.Printf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message) - return + return fmt.Errorf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message) } lastBlock := blockNumber.Number fmt.Printf("Last block: %d\n", lastBlock) @@ -35,8 +33,7 @@ func Bench2(erigon_url string) { blockByNumTemplate := `{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x%x",true],"id":%d}` //nolint var b EthBlockByNumber if err := post(client, erigon_url, fmt.Sprintf(blockByNumTemplate, bn, req_id), &b); err != nil { - fmt.Printf("Could not retrieve block %d: %v\n", bn, err) - return + return fmt.Errorf("Could not retrieve block %d: %v\n", bn, err) } if b.Error != nil { fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message) @@ -53,8 +50,7 @@ func Bench2(erigon_url string) { for nextKey != nil { var sr DebugStorageRange if err := post(client, erigon_url, fmt.Sprintf(storageRangeTemplate, b.Result.Hash, i, tx.To, *nextKey, 1024, req_id), &sr); err != nil { - fmt.Printf("Could not get storageRange: %x: %v\n", tx.Hash, err) - return + return fmt.Errorf("Could not get storageRange: %x: %v\n", tx.Hash, err) } if sr.Error != nil { fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message) @@ -83,15 +79,14 @@ func Bench2(erigon_url string) { accountRangeTemplate := `{"jsonrpc":"2.0","method":"debug_getModifiedAccountsByNumber","params":[%d, %d],"id":%d}` //nolint var ma DebugModifiedAccounts if err := post(client, erigon_url, fmt.Sprintf(accountRangeTemplate, prevBn, bn, req_id), &ma); err != nil { - fmt.Printf("Could not get modified accounts: %v\n", err) - return + return fmt.Errorf("Could not get modified accounts: %v\n", err) } if ma.Error != nil { - fmt.Printf("Error getting modified accounts: %d %s\n", ma.Error.Code, ma.Error.Message) - return + return fmt.Errorf("Error getting modified accounts: %d %s\n", ma.Error.Code, ma.Error.Message) } fmt.Printf("Done blocks %d-%d, modified accounts: %d\n", prevBn, bn, len(ma.Result)) prevBn = bn } } + return nil } diff --git a/cmd/rpctest/rpctest/bench3.go b/cmd/rpctest/rpctest/bench3.go index 317700750a5..5d4c959b809 100644 --- a/cmd/rpctest/rpctest/bench3.go +++ b/cmd/rpctest/rpctest/bench3.go @@ -11,7 +11,7 @@ import ( "github.com/ledgerwatch/erigon/core/state" ) -func Bench3(erigon_url, geth_url string) { +func Bench3(erigon_url, geth_url string) error { var client = &http.Client{ Timeout: time.Second * 600, } @@ -30,8 +30,7 @@ func Bench3(erigon_url, geth_url string) { encodedKey := base64.StdEncoding.EncodeToString(page) var sr DebugAccountRange if err := post(client, erigon_url, fmt.Sprintf(template, encodedKey, pageSize, req_id), &sr); err != nil { - fmt.Printf("Could not get accountRange: %v\n", err) - return + return fmt.Errorf("Could not get accountRange: %v\n", err) } if sr.Error != nil { fmt.Printf("Error getting accountRange: %d %s\n", sr.Error.Code, sr.Error.Message) @@ -51,9 +50,7 @@ func Bench3(erigon_url, geth_url string) { encodedKey := base64.StdEncoding.EncodeToString(page) var sr DebugAccountRange if err := post(client, geth_url, fmt.Sprintf(template, encodedKey, pageSize, req_id), &sr); err != nil { - - fmt.Printf("Could not get accountRange: %v\n", err) - return + return fmt.Errorf("Could not get accountRange: %v\n", err) } if sr.Error != nil { fmt.Printf("Error getting accountRange: %d %s\n", sr.Error.Code, sr.Error.Message) @@ -67,16 +64,14 @@ func Bench3(erigon_url, geth_url string) { } if !compareAccountRanges(accRangeTG, accRangeGeth) { - fmt.Printf("Different in account ranges tx\n") - return + return fmt.Errorf("Different in account ranges tx\n") } fmt.Println("debug_accountRanges... OK!") template = `{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x%x",true],"id":%d}` var b EthBlockByNumber if err := post(client, erigon_url, fmt.Sprintf(template, 1720000, req_id), &b); err != nil { - fmt.Printf("Could not retrieve block %d: %v\n", 1720000, err) - return + return fmt.Errorf("Could not retrieve block %d: %v\n", 1720000, err) } if b.Error != nil { fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message) @@ -89,27 +84,23 @@ func Bench3(erigon_url, geth_url string) { ` var trace EthTxTrace if err := post(client, erigon_url, fmt.Sprintf(template, txhash, req_id), &trace); err != nil { - fmt.Printf("Could not trace transaction %s: %v\n", txhash, err) print(client, erigon_url, fmt.Sprintf(template, txhash, req_id)) - return + return fmt.Errorf("Could not trace transaction %s: %v\n", txhash, err) } if trace.Error != nil { fmt.Printf("Error tracing transaction: %d %s\n", trace.Error.Code, trace.Error.Message) } var traceg EthTxTrace if err := post(client, geth_url, fmt.Sprintf(template, txhash, req_id), &traceg); err != nil { - fmt.Printf("Could not trace transaction g %s: %v\n", txhash, err) print(client, geth_url, fmt.Sprintf(template, txhash, req_id)) - return + return fmt.Errorf("Could not trace transaction g %s: %v\n", txhash, err) } if traceg.Error != nil { - fmt.Printf("Error tracing transaction g: %d %s\n", traceg.Error.Code, traceg.Error.Message) - return + return fmt.Errorf("Error tracing transaction g: %d %s\n", traceg.Error.Code, traceg.Error.Message) } //print(client, erigon_url, fmt.Sprintf(template, txhash, req_id)) if !compareTraces(&trace, &traceg) { - fmt.Printf("Different traces block %d, tx %s\n", 1720000, txhash) - return + return fmt.Errorf("Different traces block %d, tx %s\n", 1720000, txhash) } } to := libcommon.HexToAddress("0xbb9bc244d798123fde783fcc1c72d3bb8c189413") @@ -125,8 +116,7 @@ func Bench3(erigon_url, geth_url string) { for nextKey != nil { var sr DebugStorageRange if err := post(client, erigon_url, fmt.Sprintf(template, blockhash, i, to, *nextKey, 1024, req_id), &sr); err != nil { - fmt.Printf("Could not get storageRange: %v\n", err) - return + return fmt.Errorf("Could not get storageRange: %v\n", err) } if sr.Error != nil { fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message) @@ -144,8 +134,7 @@ func Bench3(erigon_url, geth_url string) { for nextKey != nil { var srg DebugStorageRange if err := post(client, geth_url, fmt.Sprintf(template, blockhash, i, to, *nextKey, 1024, req_id), &srg); err != nil { - fmt.Printf("Could not get storageRange g: %v\n", err) - return + return fmt.Errorf("Could not get storageRange g: %v\n", err) } if srg.Error != nil { fmt.Printf("Error getting storageRange g: %d %s\n", srg.Error.Code, srg.Error.Message) @@ -159,8 +148,9 @@ func Bench3(erigon_url, geth_url string) { } fmt.Printf("storageRange g: %d\n", len(smg)) if !compareStorageRanges(sm, smg) { - fmt.Printf("Different in storage ranges tx\n") - return + return fmt.Errorf("Different in storage ranges tx\n") } + return nil + } diff --git a/cmd/rpctest/rpctest/bench4.go b/cmd/rpctest/rpctest/bench4.go index 1d403049185..347490ce5a5 100644 --- a/cmd/rpctest/rpctest/bench4.go +++ b/cmd/rpctest/rpctest/bench4.go @@ -8,7 +8,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" ) -func Bench4(erigon_url string) { +func Bench4(erigon_url string) error { var client = &http.Client{ Timeout: time.Second * 600, } @@ -18,8 +18,7 @@ func Bench4(erigon_url string) { template := `{"jsonrpc":"2.0","method":"eth_getBlockByNumber","params":["0x%x",true],"id":%d}` var b EthBlockByNumber if err := post(client, erigon_url, fmt.Sprintf(template, 1720000, req_id), &b); err != nil { - fmt.Printf("Could not retrieve block %d: %v\n", 1720000, err) - return + return fmt.Errorf("Could not retrieve block %d: %v\n", 1720000, err) } if b.Error != nil { fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message) @@ -30,9 +29,8 @@ func Bench4(erigon_url string) { template = `{"jsonrpc":"2.0","method":"debug_traceTransaction","params":["%s"],"id":%d}` var trace EthTxTrace if err := post(client, erigon_url, fmt.Sprintf(template, txhash, req_id), &trace); err != nil { - fmt.Printf("Could not trace transaction %s: %v\n", txhash, err) print(client, erigon_url, fmt.Sprintf(template, txhash, req_id)) - return + return fmt.Errorf("Could not trace transaction %s: %v\n", txhash, err) } if trace.Error != nil { fmt.Printf("Error tracing transaction: %d %s\n", trace.Error.Code, trace.Error.Message) @@ -50,8 +48,7 @@ func Bench4(erigon_url string) { for nextKey != nil { var sr DebugStorageRange if err := post(client, erigon_url, fmt.Sprintf(template, blockhash, i, to, *nextKey, 1024, req_id), &sr); err != nil { - fmt.Printf("Could not get storageRange: %v\n", err) - return + return fmt.Errorf("Could not get storageRange: %v\n", err) } if sr.Error != nil { fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message) @@ -64,4 +61,5 @@ func Bench4(erigon_url string) { } } fmt.Printf("storageRange: %d\n", len(sm)) + return nil } diff --git a/cmd/rpctest/rpctest/bench5.go b/cmd/rpctest/rpctest/bench5.go index 2104bc9d6d2..4066df310dc 100644 --- a/cmd/rpctest/rpctest/bench5.go +++ b/cmd/rpctest/rpctest/bench5.go @@ -8,7 +8,7 @@ import ( "time" ) -func Bench5(erigonURL string) { +func Bench5(erigonURL string) error { var client = &http.Client{ Timeout: time.Second * 600, } @@ -24,16 +24,15 @@ func Bench5(erigonURL string) { for scanner.Scan() { req_id++ if err = post(client, erigonURL, fmt.Sprintf(template, scanner.Text(), req_id), &receipt); err != nil { - fmt.Printf("Count not get receipt: %s: %v\n", scanner.Text(), err) - return + return fmt.Errorf("Count not get receipt: %s: %v\n", scanner.Text(), err) } if receipt.Error != nil { - fmt.Printf("Error getting receipt: %d %s\n", receipt.Error.Code, receipt.Error.Message) - return + return fmt.Errorf("Error getting receipt: %d %s\n", receipt.Error.Code, receipt.Error.Message) } } err = scanner.Err() if err != nil { panic(err) } + return nil } diff --git a/cmd/rpctest/rpctest/bench6.go b/cmd/rpctest/rpctest/bench6.go index 825c8b5ebbc..f9fcc3c57ae 100644 --- a/cmd/rpctest/rpctest/bench6.go +++ b/cmd/rpctest/rpctest/bench6.go @@ -8,7 +8,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" ) -func Bench6(erigon_url string) { +func Bench6(erigon_url string) error { var client = &http.Client{ Timeout: time.Second * 600, } @@ -20,12 +20,10 @@ func Bench6(erigon_url string) { ` var blockNumber EthBlockNumber if err := post(client, erigon_url, fmt.Sprintf(template, req_id), &blockNumber); err != nil { - fmt.Printf("Could not get block number: %v\n", err) - return + return fmt.Errorf("Could not get block number: %v\n", err) } if blockNumber.Error != nil { - fmt.Printf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message) - return + return fmt.Errorf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message) } lastBlock := blockNumber.Number fmt.Printf("Last block: %d\n", lastBlock) @@ -38,8 +36,7 @@ func Bench6(erigon_url string) { ` var b EthBlockByNumber if err := post(client, erigon_url, fmt.Sprintf(template, bn, req_id), &b); err != nil { - fmt.Printf("Could not retrieve block %d: %v\n", bn, err) - return + return fmt.Errorf("Could not retrieve block %d: %v\n", bn, err) } if b.Error != nil { fmt.Printf("Error retrieving block: %d %s\n", b.Error.Code, b.Error.Message) @@ -56,14 +53,13 @@ func Bench6(erigon_url string) { ` var receipt EthReceipt if err := post(client, erigon_url, fmt.Sprintf(template, tx.Hash, req_id), &receipt); err != nil { - fmt.Printf("Count not get receipt: %s: %v\n", tx.Hash, err) print(client, erigon_url, fmt.Sprintf(template, tx.Hash, req_id)) - return + return fmt.Errorf("Count not get receipt: %s: %v\n", tx.Hash, err) } if receipt.Error != nil { - fmt.Printf("Error getting receipt: %d %s\n", receipt.Error.Code, receipt.Error.Message) - return + return fmt.Errorf("Error getting receipt: %d %s\n", receipt.Error.Code, receipt.Error.Message) } } } + return nil } diff --git a/cmd/rpctest/rpctest/bench7.go b/cmd/rpctest/rpctest/bench7.go index 29c5e49a7e8..2a6dd6b49d5 100644 --- a/cmd/rpctest/rpctest/bench7.go +++ b/cmd/rpctest/rpctest/bench7.go @@ -8,7 +8,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" ) -func Bench7(erigonURL, gethURL string) { +func Bench7(erigonURL, gethURL string) error { setRoutes(erigonURL, gethURL) var client = &http.Client{ Timeout: time.Second * 600, @@ -34,8 +34,7 @@ func Bench7(erigonURL, gethURL string) { for nextKey != nil { var sr DebugStorageRange if err := post(client, erigonURL, fmt.Sprintf(template, blockhash, i, to, *nextKey, 1024, reqID), &sr); err != nil { - fmt.Printf("Could not get storageRange: %v\n", err) - return + return fmt.Errorf("Could not get storageRange: %v\n", err) } if sr.Error != nil { fmt.Printf("Error getting storageRange: %d %s\n", sr.Error.Code, sr.Error.Message) @@ -54,8 +53,7 @@ func Bench7(erigonURL, gethURL string) { for nextKeyG != nil { var srg DebugStorageRange if err := post(client, gethURL, fmt.Sprintf(template, blockhash, i, to, *nextKeyG, 1024, reqID), &srg); err != nil { - fmt.Printf("Could not get storageRange: %v\n", err) - return + return fmt.Errorf("Could not get storageRange: %v\n", err) } if srg.Error != nil { fmt.Printf("Error getting storageRange: %d %s\n", srg.Error.Code, srg.Error.Message) @@ -76,7 +74,8 @@ func Bench7(erigonURL, gethURL string) { printStorageRange(sm) fmt.Printf("================smg\n") printStorageRange(smg) - return + return fmt.Errorf("storage are different") } fmt.Printf("storageRanges: %d\n", len(sm)) + return nil } diff --git a/cmd/rpctest/rpctest/bench9.go b/cmd/rpctest/rpctest/bench9.go index 7b2a4266ee4..9c06fef9697 100644 --- a/cmd/rpctest/rpctest/bench9.go +++ b/cmd/rpctest/rpctest/bench9.go @@ -11,7 +11,7 @@ import ( ) // bench9 tests eth_getProof -func Bench9(erigonURL, gethURL string, needCompare bool) { +func Bench9(erigonURL, gethURL string, needCompare bool) error { setRoutes(erigonURL, gethURL) var client = &http.Client{ Timeout: time.Second * 600, @@ -26,12 +26,10 @@ func Bench9(erigonURL, gethURL string, needCompare bool) { var blockNumber EthBlockNumber res = reqGen.Erigon("eth_blockNumber", reqGen.blockNumber(), &blockNumber) if res.Err != nil { - fmt.Printf("Could not get block number: %v\n", res.Err) - return + return fmt.Errorf("Could not get block number: %v\n", res.Err) } if blockNumber.Error != nil { - fmt.Printf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message) - return + return fmt.Errorf("Error getting block number: %d %s\n", blockNumber.Error.Code, blockNumber.Error.Message) } lastBlock := blockNumber.Number fmt.Printf("Last block: %d\n", lastBlock) @@ -46,8 +44,7 @@ func Bench9(erigonURL, gethURL string, needCompare bool) { res = reqGen.Erigon("debug_accountRange", reqGen.accountRange(bn, page, 256), &sr) if res.Err != nil { - fmt.Printf("Could not get accountRange (Erigon): %v\n", res.Err) - return + return fmt.Errorf("Could not get accountRange (Erigon): %v\n", res.Err) } if sr.Error != nil { @@ -74,8 +71,7 @@ func Bench9(erigonURL, gethURL string, needCompare bool) { } res = reqGen.Erigon("eth_getProof", reqGen.getProof(bn, address, storageList), &proof) if res.Err != nil { - fmt.Printf("Could not get getProof (Erigon): %v\n", res.Err) - return + return fmt.Errorf("Could not get getProof (Erigon): %v\n", res.Err) } if proof.Error != nil { fmt.Printf("Error getting getProof (Erigon): %d %s\n", proof.Error.Code, proof.Error.Message) @@ -86,8 +82,7 @@ func Bench9(erigonURL, gethURL string, needCompare bool) { reqGen.reqID++ res = reqGen.Geth("eth_getProof", reqGen.getProof(bn, address, storageList), &gethProof) if res.Err != nil { - fmt.Printf("Could not get getProof (geth): %v\n", res.Err) - return + return fmt.Errorf("Could not get getProof (geth): %v\n", res.Err) } if gethProof.Error != nil { fmt.Printf("Error getting getProof (geth): %d %s\n", gethProof.Error.Code, gethProof.Error.Message) @@ -100,4 +95,5 @@ func Bench9(erigonURL, gethURL string, needCompare bool) { } } } + return nil } From c1697caea3116bc667018c10193d6f87d4900549 Mon Sep 17 00:00:00 2001 From: Somnath Date: Tue, 24 Oct 2023 11:57:13 +0400 Subject: [PATCH 04/44] Update Readme - gnosis size (#8538) --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 1e390308131..5f6dafdce77 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ System Requirements * Goerli Full node (see `--prune*` flags): 189GB on Beta, 114GB on Alpha (April 2022). -* Gnosis Chain Archive: 370GB (January 2023). +* Gnosis Chain Archive: 600GB (October 2023). * Polygon Mainnet Archive: 5TB. (April 2022). `--prune.*.older 15768000`: 5.1Tb (Sept 2023). Polygon Mumbai Archive: 1TB. (April 2022). From b9a8c2d6e6b779f4cb983155257298696ca54558 Mon Sep 17 00:00:00 2001 From: Dmytro Date: Tue, 24 Oct 2023 11:49:48 +0300 Subject: [PATCH 05/44] sentry: error checking fix (#8566) --- cmd/sentry/sentry/sentry_grpc_server.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/sentry/sentry/sentry_grpc_server.go b/cmd/sentry/sentry/sentry_grpc_server.go index 6e908638cbb..7f535909489 100644 --- a/cmd/sentry/sentry/sentry_grpc_server.go +++ b/cmd/sentry/sentry/sentry_grpc_server.go @@ -627,7 +627,7 @@ func NewGrpcServer(ctx context.Context, dialCandidates func() enode.Iterator, re ss.GoodPeers.Store(peerID, peerInfo) ss.sendNewPeerToClients(gointerfaces.ConvertHashToH512(peerID)) getBlockHeadersErr := ss.getBlockHeaders(ctx, *peerBestHash, peerID) - if err != nil { + if getBlockHeadersErr != nil { return p2p.NewPeerError(p2p.PeerErrorFirstMessageSend, p2p.DiscNetworkError, getBlockHeadersErr, "p2p.Protocol.Run getBlockHeaders failure") } From d7448fdb3f9c3d9cefafcee7a7118ac324a5ae25 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Tue, 24 Oct 2023 21:32:29 +0200 Subject: [PATCH 06/44] Added functional beacon snapshots reader and generator to Caplin (#8570) This PR adds beacon blocks snapshots and beacon blocks snapshot generator to Caplin, plus a snapshot verifier CLI --- cl/cltypes/beacon_block.go | 6 +- .../format/chunk_encoding/chunks.go | 5 + .../format/snapshot_format/blocks.go | 79 +++- .../format/snapshot_format/blocks_test.go | 21 +- .../format/snapshot_format/snapshots.go | 87 ---- .../format/snapshot_format/test_util.go | 11 + cl/spectest/consensus_tests/ssz_static.go | 25 +- cmd/capcli/cli.go | 93 +++- .../freezeblocks/beacon_block_reader.go | 69 +++ .../freezeblocks/block_snapshots.go | 87 +--- .../freezeblocks/caplin_snapshots.go | 398 ++++++++++++++++++ 11 files changed, 693 insertions(+), 188 deletions(-) delete mode 100644 cl/persistence/format/snapshot_format/snapshots.go create mode 100644 cl/persistence/format/snapshot_format/test_util.go create mode 100644 turbo/snapshotsync/freezeblocks/beacon_block_reader.go create mode 100644 turbo/snapshotsync/freezeblocks/caplin_snapshots.go diff --git a/cl/cltypes/beacon_block.go b/cl/cltypes/beacon_block.go index d09f404f9e5..8125342241c 100644 --- a/cl/cltypes/beacon_block.go +++ b/cl/cltypes/beacon_block.go @@ -94,7 +94,9 @@ func NewBeaconBlock(beaconCfg *clparams.BeaconChainConfig) *BeaconBlock { } func NewBeaconBody(beaconCfg *clparams.BeaconChainConfig) *BeaconBody { - return &BeaconBody{beaconCfg: beaconCfg} + return &BeaconBody{ + beaconCfg: beaconCfg, + } } // Version returns beacon block version. @@ -172,6 +174,8 @@ func (b *BeaconBody) DecodeSSZ(buf []byte, version int) error { return fmt.Errorf("[BeaconBody] err: %s", ssz.ErrLowBufferSize) } + b.ExecutionPayload = NewEth1Block(b.Version, b.beaconCfg) + err := ssz2.UnmarshalSSZ(buf, version, b.getSchema(false)...) return err } diff --git a/cl/persistence/format/chunk_encoding/chunks.go b/cl/persistence/format/chunk_encoding/chunks.go index 05ba58e3c54..eeefb3962ee 100644 --- a/cl/persistence/format/chunk_encoding/chunks.go +++ b/cl/persistence/format/chunk_encoding/chunks.go @@ -35,6 +35,11 @@ func ReadChunk(r io.Reader) (buf []byte, t DataType, err error) { } t = DataType(prefix[0]) prefix[0] = 0 + + bufLen := binary.BigEndian.Uint64(prefix) + if bufLen == 0 { + return + } buf = make([]byte, binary.BigEndian.Uint64(prefix)) if _, err = r.Read(buf); err != nil { return diff --git a/cl/persistence/format/snapshot_format/blocks.go b/cl/persistence/format/snapshot_format/blocks.go index e1f7abac312..8029ef78407 100644 --- a/cl/persistence/format/snapshot_format/blocks.go +++ b/cl/persistence/format/snapshot_format/blocks.go @@ -86,25 +86,10 @@ func WriteBlockForSnapshot(block *cltypes.SignedBeaconBlock, w io.Writer) error // count in body for phase0 fields currentChunkLength += uint64(body.ProposerSlashings.EncodingSizeSSZ()) currentChunkLength += uint64(body.AttesterSlashings.EncodingSizeSSZ()) - - // Write the chunk and chunk attestations - if err := chunk_encoding.WriteChunk(w, encoded[:currentChunkLength], chunk_encoding.ChunkDataType); err != nil { - return err - } - encoded = encoded[currentChunkLength:] - snappyWriter := snappy.NewBufferedWriter(w) - if err := chunk_encoding.WriteChunk(snappyWriter, encoded[:uint64(body.Attestations.EncodingSizeSSZ())], chunk_encoding.ChunkDataType); err != nil { - return err - } - if err := snappyWriter.Close(); err != nil { - return err - } - encoded = encoded[body.Attestations.EncodingSizeSSZ():] - currentChunkLength = 0 - + currentChunkLength += uint64(body.Attestations.EncodingSizeSSZ()) currentChunkLength += uint64(body.Deposits.EncodingSizeSSZ()) currentChunkLength += uint64(body.VoluntaryExits.EncodingSizeSSZ()) - + // Write the chunk and chunk attestations if err := chunk_encoding.WriteChunk(w, encoded[:currentChunkLength], chunk_encoding.ChunkDataType); err != nil { return err } @@ -140,6 +125,60 @@ func ReadBlockFromSnapshot(r io.Reader, executionReader ExecutionBlockReaderByNu return nil, err } + // Read the first chunk + chunk1, dT1, err := chunk_encoding.ReadChunk(r) + if err != nil { + return nil, err + } + if dT1 != chunk_encoding.ChunkDataType { + return nil, fmt.Errorf("malformed beacon block, invalid chunk 1 type %d, expected: %d", dT1, chunk_encoding.ChunkDataType) + } + plainSSZ = append(plainSSZ, chunk1...) + + if v <= clparams.AltairVersion { + return block, block.DecodeSSZ(plainSSZ, int(v)) + } + // Read the block pointer and retrieve chunk4 from the execution reader + blockPointer, err := readExecutionBlockPtr(r) + if err != nil { + return nil, err + } + executionBlock, err := executionReader.BlockByNumber(blockPointer) + if err != nil { + return nil, err + } + // Read the 4th chunk + chunk2, err := executionBlock.EncodeSSZ(nil) + if err != nil { + return nil, err + } + plainSSZ = append(plainSSZ, chunk2...) + if v <= clparams.BellatrixVersion { + return block, block.DecodeSSZ(plainSSZ, int(v)) + } + + // Read the 5h chunk + chunk3, dT5, err := chunk_encoding.ReadChunk(r) + if err != nil { + return nil, err + } + if dT5 != chunk_encoding.ChunkDataType { + return nil, fmt.Errorf("malformed beacon block, invalid chunk 5 type %d, expected: %d", dT5, chunk_encoding.ChunkDataType) + } + plainSSZ = append(plainSSZ, chunk3...) + + return block, block.DecodeSSZ(plainSSZ, int(v)) +} + +func ReadRawBlockFromSnapshot(r io.Reader, executionReader ExecutionBlockReaderByNumber, cfg *clparams.BeaconChainConfig) ([]byte, error) { + plainSSZ := []byte{} + + // Metadata section is just the current hardfork of the block. TODO(give it a useful purpose) + v, err := readMetadataForBlock(r) + if err != nil { + return nil, err + } + // Read the first chunk chunk1, dT1, err := chunk_encoding.ReadChunk(r) if err != nil { @@ -168,7 +207,7 @@ func ReadBlockFromSnapshot(r io.Reader, executionReader ExecutionBlockReaderByNu } plainSSZ = append(plainSSZ, chunk3...) if v <= clparams.AltairVersion { - return block, block.DecodeSSZ(plainSSZ, int(v)) + return plainSSZ, nil } // Read the block pointer and retrieve chunk4 from the execution reader blockPointer, err := readExecutionBlockPtr(r) @@ -186,7 +225,7 @@ func ReadBlockFromSnapshot(r io.Reader, executionReader ExecutionBlockReaderByNu } plainSSZ = append(plainSSZ, chunk4...) if v <= clparams.BellatrixVersion { - return block, block.DecodeSSZ(plainSSZ, int(v)) + return plainSSZ, nil } // Read the 5h chunk @@ -199,5 +238,5 @@ func ReadBlockFromSnapshot(r io.Reader, executionReader ExecutionBlockReaderByNu } plainSSZ = append(plainSSZ, chunk5...) - return block, block.DecodeSSZ(plainSSZ, int(v)) + return plainSSZ, nil } diff --git a/cl/persistence/format/snapshot_format/blocks_test.go b/cl/persistence/format/snapshot_format/blocks_test.go index 5efc2963fe6..8021c3fcc38 100644 --- a/cl/persistence/format/snapshot_format/blocks_test.go +++ b/cl/persistence/format/snapshot_format/blocks_test.go @@ -27,8 +27,15 @@ var capellaBlockSSZSnappy []byte //go:embed test_data/deneb.ssz_snappy var denebBlockSSZSnappy []byte +var emptyBlock = cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig) + // obtain the test blocks func getTestBlocks(t *testing.T) []*cltypes.SignedBeaconBlock { + var emptyBlockCapella = cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig) + emptyBlockCapella.Block.Slot = clparams.MainnetBeaconConfig.CapellaForkEpoch * 32 + + emptyBlock.EncodingSizeSSZ() + emptyBlockCapella.EncodingSizeSSZ() denebBlock := cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig) capellaBlock := cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig) bellatrixBlock := cltypes.NewSignedBeaconBlock(&clparams.MainnetBeaconConfig) @@ -40,22 +47,14 @@ func getTestBlocks(t *testing.T) []*cltypes.SignedBeaconBlock { require.NoError(t, utils.DecodeSSZSnappy(bellatrixBlock, bellatrixBlockSSZSnappy, int(clparams.BellatrixVersion))) require.NoError(t, utils.DecodeSSZSnappy(altairBlock, altairBlockSSZSnappy, int(clparams.AltairVersion))) require.NoError(t, utils.DecodeSSZSnappy(phase0Block, phase0BlockSSZSnappy, int(clparams.Phase0Version))) - return []*cltypes.SignedBeaconBlock{phase0Block, altairBlock, bellatrixBlock, capellaBlock, denebBlock} -} - -type TestBlockReader struct { - Block *cltypes.Eth1Block -} - -func (t *TestBlockReader) BlockByNumber(number uint64) (*cltypes.Eth1Block, error) { - return t.Block, nil + return []*cltypes.SignedBeaconBlock{phase0Block, altairBlock, bellatrixBlock, capellaBlock, denebBlock, emptyBlock, emptyBlockCapella} } func TestBlockSnapshotEncoding(t *testing.T) { for _, blk := range getTestBlocks(t) { - var br TestBlockReader + var br snapshot_format.MockBlockReader if blk.Version() >= clparams.BellatrixVersion { - br = TestBlockReader{Block: blk.Block.Body.ExecutionPayload} + br = snapshot_format.MockBlockReader{Block: blk.Block.Body.ExecutionPayload} } var b bytes.Buffer require.NoError(t, snapshot_format.WriteBlockForSnapshot(blk, &b)) diff --git a/cl/persistence/format/snapshot_format/snapshots.go b/cl/persistence/format/snapshot_format/snapshots.go deleted file mode 100644 index 8cecbc8f1e0..00000000000 --- a/cl/persistence/format/snapshot_format/snapshots.go +++ /dev/null @@ -1,87 +0,0 @@ -package snapshot_format - -import ( - "bytes" - "context" - "fmt" - - "github.com/ledgerwatch/erigon-lib/common/background" - "github.com/ledgerwatch/erigon-lib/common/cmp" - "github.com/ledgerwatch/erigon-lib/compress" - "github.com/ledgerwatch/erigon-lib/downloader/snaptype" - "github.com/ledgerwatch/erigon-lib/kv" - "github.com/ledgerwatch/erigon/cl/persistence" - "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" - "github.com/ledgerwatch/log/v3" -) - -func dumpBeaconBlocksRange(ctx context.Context, db kv.RoDB, b persistence.BlockSource, fromSlot uint64, toSlot uint64, tmpDir, snapDir string, workers int, lvl log.Lvl, logger log.Logger) error { - segName := snaptype.SegmentFileName(fromSlot, toSlot, snaptype.BeaconBlocks) - f, _ := snaptype.ParseFileName(snapDir, segName) - - sn, err := compress.NewCompressor(ctx, "Snapshot BeaconBlocks", f.Path, tmpDir, compress.MinPatternScore, workers, lvl, logger) - if err != nil { - return err - } - defer sn.Close() - - tx, err := db.BeginRo(ctx) - if err != nil { - return err - } - defer tx.Rollback() - // Generate .seg file, which is just the list of beacon blocks. - var buf bytes.Buffer - for i := fromSlot; i <= toSlot; i++ { - obj, err := b.GetBlock(ctx, tx, i) - if err != nil { - return err - } - if obj == nil { - if err := sn.AddWord(nil); err != nil { - return err - } - continue - } - if err := WriteBlockForSnapshot(obj.Data, &buf); err != nil { - return err - } - if err := sn.AddWord(buf.Bytes()); err != nil { - return err - } - buf.Reset() - } - if err := sn.Compress(); err != nil { - return fmt.Errorf("compress: %w", err) - } - // Generate .idx file, which is the slot => offset mapping. - p := &background.Progress{} - - return freezeblocks.BeaconBlocksIdx(ctx, segName, fromSlot, toSlot, snapDir, tmpDir, p, lvl, logger) -} - -func chooseSegmentEnd(from, to, blocksPerFile uint64) uint64 { - next := (from/blocksPerFile + 1) * blocksPerFile - to = cmp.Min(next, to) - - if to < snaptype.Erigon2MinSegmentSize { - return to - } - - return to - (to % snaptype.Erigon2MinSegmentSize) // round down to the nearest 1k -} - -func DumpBeaconBlocks(ctx context.Context, db kv.RoDB, b persistence.BlockSource, fromSlot, toSlot, blocksPerFile uint64, tmpDir, snapDir string, workers int, lvl log.Lvl, logger log.Logger) error { - if blocksPerFile == 0 { - return nil - } - - for i := fromSlot; i < toSlot; i = chooseSegmentEnd(i, toSlot, blocksPerFile) { - to := chooseSegmentEnd(i, toSlot, blocksPerFile) - logger.Log(lvl, "Dumping beacon blocks", "from", i, "to", to) - if err := dumpBeaconBlocksRange(ctx, db, b, i, to, tmpDir, snapDir, workers, lvl, logger); err != nil { - return err - } - } - return nil -} diff --git a/cl/persistence/format/snapshot_format/test_util.go b/cl/persistence/format/snapshot_format/test_util.go new file mode 100644 index 00000000000..3993c1648b7 --- /dev/null +++ b/cl/persistence/format/snapshot_format/test_util.go @@ -0,0 +1,11 @@ +package snapshot_format + +import "github.com/ledgerwatch/erigon/cl/cltypes" + +type MockBlockReader struct { + Block *cltypes.Eth1Block +} + +func (t *MockBlockReader) BlockByNumber(number uint64) (*cltypes.Eth1Block, error) { + return t.Block, nil +} diff --git a/cl/spectest/consensus_tests/ssz_static.go b/cl/spectest/consensus_tests/ssz_static.go index f5621181344..b38e71df336 100644 --- a/cl/spectest/consensus_tests/ssz_static.go +++ b/cl/spectest/consensus_tests/ssz_static.go @@ -1,10 +1,15 @@ package consensus_tests import ( - "github.com/ledgerwatch/erigon/spectest" + "bytes" "io/fs" "testing" + "github.com/ledgerwatch/erigon/spectest" + + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cl/persistence/format/snapshot_format" "github.com/ledgerwatch/erigon/cl/phase1/core/state" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -59,6 +64,24 @@ func getSSZStaticConsensusTest[T unmarshalerMarshalerHashable](ref T) spectest.H haveEncoded, err := object.EncodeSSZ(nil) require.NoError(t, err) require.EqualValues(t, haveEncoded, encoded) + // Now let it do the encoding in snapshot format + if blk, ok := object.(*cltypes.SignedBeaconBlock); ok { + var b bytes.Buffer + require.NoError(t, snapshot_format.WriteBlockForSnapshot(blk, &b)) + var br snapshot_format.MockBlockReader + if blk.Version() >= clparams.BellatrixVersion { + br = snapshot_format.MockBlockReader{Block: blk.Block.Body.ExecutionPayload} + + } + + blk2, err := snapshot_format.ReadBlockFromSnapshot(&b, &br, &clparams.MainnetBeaconConfig) + require.NoError(t, err) + + haveRoot, err := blk2.HashSSZ() + require.NoError(t, err) + require.EqualValues(t, expectedRoot, haveRoot) + } + return nil }) } diff --git a/cmd/capcli/cli.go b/cmd/capcli/cli.go index e9c70f0629e..e593e4f4de9 100644 --- a/cmd/capcli/cli.go +++ b/cmd/capcli/cli.go @@ -7,11 +7,15 @@ import ( "strings" "time" + libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon/cl/abstract" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" persistence2 "github.com/ledgerwatch/erigon/cl/persistence" "github.com/ledgerwatch/erigon/cmd/caplin/caplin1" + "github.com/ledgerwatch/erigon/eth/ethconfig" + "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/downloader/snaptype" @@ -45,8 +49,9 @@ var CLI struct { Blocks Blocks `cmd:"" help:"download blocks from reqresp network"` Epochs Epochs `cmd:"" help:"download epochs from reqresp network"` - Chain Chain `cmd:"" help:"download the entire chain from reqresp network"` - DumpSnapshots DumpSnapshots `cmd:"" help:"generate caplin snapshots"` + Chain Chain `cmd:"" help:"download the entire chain from reqresp network"` + DumpSnapshots DumpSnapshots `cmd:"" help:"generate caplin snapshots"` + CheckSnapshots CheckSnapshots `cmd:"" help:"check snapshot folder against content of chain data"` } type chainCfg struct { @@ -425,5 +430,87 @@ func (c *DumpSnapshots) Run(ctx *Context) error { return }) - return snapshot_format.DumpBeaconBlocks(ctx, db, beaconDB, 0, to, snaptype.Erigon2SegmentSize, dirs.Tmp, dirs.Snap, 8, log.LvlInfo, log.Root()) + return freezeblocks.DumpBeaconBlocks(ctx, db, beaconDB, 0, to, snaptype.Erigon2SegmentSize, dirs.Tmp, dirs.Snap, 8, log.LvlInfo, log.Root()) +} + +type CheckSnapshots struct { + chainCfg + outputFolder + + Slot uint64 `name:"slot" help:"slot to check"` +} + +func (c *CheckSnapshots) Run(ctx *Context) error { + _, _, beaconConfig, _, err := clparams.GetConfigsByNetworkName(c.Chain) + if err != nil { + return err + } + log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StderrHandler)) + log.Info("Started the checking process", "chain", c.Chain) + + dirs := datadir.New(c.Datadir) + log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StderrHandler)) + + rawDB := persistence.AferoRawBeaconBlockChainFromOsPath(beaconConfig, dirs.CaplinHistory) + beaconDB, db, err := caplin1.OpenCaplinDatabase(ctx, db_config.DatabaseConfiguration{PruneDepth: math.MaxUint64}, beaconConfig, rawDB, dirs.CaplinIndexing, nil, false) + if err != nil { + return err + } + var to uint64 + tx, err := db.BeginRo(ctx) + if err != nil { + return err + } + defer tx.Rollback() + + to, err = beacon_indicies.ReadHighestFinalized(tx) + if err != nil { + return err + } + + to = (to / snaptype.Erigon2SegmentSize) * snaptype.Erigon2SegmentSize + + csn := freezeblocks.NewCaplinSnapshots(ethconfig.BlocksFreezing{}, dirs.Snap, log.Root()) + if err := csn.ReopenFolder(); err != nil { + return err + } + + br := &snapshot_format.MockBlockReader{} + snReader := freezeblocks.NewBeaconSnapshotReader(csn, br, beaconConfig) + for i := c.Slot; i < to; i++ { + // Read the original canonical slot + data, err := beaconDB.GetBlock(ctx, tx, i) + if err != nil { + return err + } + if data == nil { + continue + } + blk := data.Data + if blk == nil { + continue + } + // first thing if the block is bellatrix update the mock block reader + if blk.Version() >= clparams.BellatrixVersion { + br.Block = blk.Block.Body.ExecutionPayload + } + blk2, err := snReader.ReadBlock(i) + if err != nil { + log.Error("Error detected in decoding snapshots", "err", err, "slot", i) + return nil + } + if blk2 == nil { + log.Error("Block not found in snapshot", "slot", i) + return nil + } + + hash1, _ := blk.Block.HashSSZ() + hash2, _ := blk2.Block.HashSSZ() + if hash1 != hash2 { + log.Error("Mismatching blocks", "slot", i, "gotSlot", blk2.Block.Slot, "datadir", libcommon.Hash(hash1), "snapshot", libcommon.Hash(hash2)) + return nil + } + log.Info("Successfully checked", "slot", i) + } + return nil } diff --git a/turbo/snapshotsync/freezeblocks/beacon_block_reader.go b/turbo/snapshotsync/freezeblocks/beacon_block_reader.go new file mode 100644 index 00000000000..78ef3fa9cc4 --- /dev/null +++ b/turbo/snapshotsync/freezeblocks/beacon_block_reader.go @@ -0,0 +1,69 @@ +package freezeblocks + +import ( + "bytes" + + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/ledgerwatch/erigon/cl/cltypes" + "github.com/ledgerwatch/erigon/cl/persistence/format/snapshot_format" +) + +type BeaconSnapshotReader interface { + // ReadBlock reads the block at the given slot. + // If the block is not present, it returns nil. + ReadBlock(slot uint64) (*cltypes.SignedBeaconBlock, error) + RawBlockSSZ(slot uint64) ([]byte, error) + + FrozenSlots() uint64 +} + +type beaconSnapshotReader struct { + sn *CaplinSnapshots + + eth1Getter snapshot_format.ExecutionBlockReaderByNumber + cfg *clparams.BeaconChainConfig +} + +func NewBeaconSnapshotReader(snapshots *CaplinSnapshots, eth1Getter snapshot_format.ExecutionBlockReaderByNumber, cfg *clparams.BeaconChainConfig) BeaconSnapshotReader { + return &beaconSnapshotReader{sn: snapshots, eth1Getter: eth1Getter, cfg: cfg} +} + +func (r *beaconSnapshotReader) FrozenSlots() uint64 { + return r.sn.BlocksAvailable() +} + +func (r *beaconSnapshotReader) ReadBlock(slot uint64) (*cltypes.SignedBeaconBlock, error) { + buf, err := r.RawBlockSSZ(slot) + if err != nil { + return nil, err + } + if buf == nil { + return nil, nil + } + return snapshot_format.ReadBlockFromSnapshot(bytes.NewReader(buf), r.eth1Getter, r.cfg) +} + +func (r *beaconSnapshotReader) RawBlockSSZ(slot uint64) ([]byte, error) { + view := r.sn.View() + defer view.Close() + + var buf []byte + + seg, ok := view.BeaconBlocksSegment(slot) + if !ok { + return nil, nil + } + + if seg.idxSlot == nil { + return nil, nil + } + blockOffset := seg.idxSlot.OrdinalLookup(slot - seg.idxSlot.BaseDataID()) + + gg := seg.seg.MakeGetter() + gg.Reset(blockOffset) + if !gg.HasNext() { + return nil, nil + } + buf, _ = gg.Next(buf) + return buf, nil +} diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index cb1bf9f5af7..97e791128bb 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -1118,6 +1118,28 @@ func noOverlaps(in []snaptype.FileInfo) (res []snaptype.FileInfo) { return res } +func SegmentsCaplin(dir string) (res []snaptype.FileInfo, missingSnapshots []Range, err error) { + list, err := snaptype.Segments(dir) + if err != nil { + return nil, missingSnapshots, err + } + + { + var l []snaptype.FileInfo + var m []Range + for _, f := range list { + if f.T != snaptype.BeaconBlocks { + continue + } + l = append(l, f) + } + l, m = noGaps(noOverlaps(l)) + res = append(res, l...) + missingSnapshots = append(missingSnapshots, m...) + } + return res, missingSnapshots, nil +} + func Segments(dir string) (res []snaptype.FileInfo, missingSnapshots []Range, err error) { list, err := snaptype.Segments(dir) if err != nil { @@ -2014,71 +2036,6 @@ RETRY: return nil } -func BeaconBlocksIdx(ctx context.Context, segmentFilePath string, blockFrom, blockTo uint64, snapDir string, tmpDir string, p *background.Progress, lvl log.Lvl, logger log.Logger) (err error) { - defer func() { - if rec := recover(); rec != nil { - err = fmt.Errorf("BeaconBlocksIdx: at=%d-%d, %v, %s", blockFrom, blockTo, rec, dbg.Stack()) - } - }() - // Calculate how many records there will be in the index - d, err := compress.NewDecompressor(segmentFilePath) - if err != nil { - return err - } - defer d.Close() - g := d.MakeGetter() - var idxFilePath = filepath.Join(snapDir, snaptype.IdxFileName(blockFrom, blockTo, snaptype.BeaconBlocks.String())) - - var baseSpanId uint64 - if blockFrom > zerothSpanEnd { - baseSpanId = 1 + (blockFrom-zerothSpanEnd-1)/spanLength - } - - rs, err := recsplit.NewRecSplit(recsplit.RecSplitArgs{ - KeyCount: d.Count(), - Enums: d.Count() > 0, - BucketSize: 2000, - LeafSize: 8, - TmpDir: tmpDir, - IndexFile: idxFilePath, - BaseDataID: baseSpanId, - }, logger) - if err != nil { - return err - } - rs.LogLvl(log.LvlDebug) - - defer d.EnableMadvNormal().DisableReadAhead() -RETRY: - g.Reset(0) - var i, offset, nextPos uint64 - var key [8]byte - for g.HasNext() { - nextPos, _ = g.Skip() - binary.BigEndian.PutUint64(key[:], i) - i++ - if err = rs.AddKey(key[:], offset); err != nil { - return err - } - select { - case <-ctx.Done(): - return ctx.Err() - default: - } - offset = nextPos - } - if err = rs.Build(ctx); err != nil { - if errors.Is(err, recsplit.ErrCollision) { - logger.Info("Building recsplit. Collision happened. It's ok. Restarting with another salt...", "err", err) - rs.ResetNextSalt() - goto RETRY - } - return err - } - - return nil -} - // HeadersIdx - headerHash -> offset (analog of kv.HeaderNumber) func HeadersIdx(ctx context.Context, chainConfig *chain.Config, segmentFilePath string, firstBlockNumInSegment uint64, tmpDir string, p *background.Progress, lvl log.Lvl, logger log.Logger) (err error) { defer func() { diff --git a/turbo/snapshotsync/freezeblocks/caplin_snapshots.go b/turbo/snapshotsync/freezeblocks/caplin_snapshots.go new file mode 100644 index 00000000000..221cbe79301 --- /dev/null +++ b/turbo/snapshotsync/freezeblocks/caplin_snapshots.go @@ -0,0 +1,398 @@ +package freezeblocks + +import ( + "bytes" + "context" + "encoding/binary" + "errors" + "fmt" + "os" + "path" + "path/filepath" + "sync" + "sync/atomic" + + "github.com/ledgerwatch/erigon-lib/common/background" + "github.com/ledgerwatch/erigon-lib/common/cmp" + "github.com/ledgerwatch/erigon-lib/common/dbg" + "github.com/ledgerwatch/erigon-lib/compress" + "github.com/ledgerwatch/erigon-lib/downloader/snaptype" + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/recsplit" + "github.com/ledgerwatch/erigon/cl/persistence" + "github.com/ledgerwatch/erigon/cl/persistence/format/snapshot_format" + "github.com/ledgerwatch/erigon/eth/ethconfig" + "github.com/ledgerwatch/log/v3" +) + +type BeaconBlockSegment struct { + seg *compress.Decompressor // value: chunked(ssz(SignedBeaconBlocks)) + idxSlot *recsplit.Index // slot -> beacon_slot_segment_offset + ranges Range +} + +func (sn *BeaconBlockSegment) closeIdx() { + if sn.idxSlot != nil { + sn.idxSlot.Close() + sn.idxSlot = nil + } +} +func (sn *BeaconBlockSegment) closeSeg() { + if sn.seg != nil { + sn.seg.Close() + sn.seg = nil + } +} +func (sn *BeaconBlockSegment) close() { + sn.closeSeg() + sn.closeIdx() +} +func (sn *BeaconBlockSegment) reopenSeg(dir string) (err error) { + sn.closeSeg() + fileName := snaptype.SegmentFileName(sn.ranges.from, sn.ranges.to, snaptype.BeaconBlocks) + sn.seg, err = compress.NewDecompressor(path.Join(dir, fileName)) + if err != nil { + return fmt.Errorf("%w, fileName: %s", err, fileName) + } + return nil +} +func (sn *BeaconBlockSegment) reopenIdxIfNeed(dir string, optimistic bool) (err error) { + if sn.idxSlot != nil { + return nil + } + err = sn.reopenIdx(dir) + if err != nil { + if !errors.Is(err, os.ErrNotExist) { + if optimistic { + log.Warn("[snapshots] open index", "err", err) + } else { + return err + } + } + } + return nil +} + +func (sn *BeaconBlockSegment) reopenIdx(dir string) (err error) { + sn.closeIdx() + if sn.seg == nil { + return nil + } + fileName := snaptype.IdxFileName(sn.ranges.from, sn.ranges.to, snaptype.BeaconBlocks.String()) + sn.idxSlot, err = recsplit.OpenIndex(path.Join(dir, fileName)) + if err != nil { + return fmt.Errorf("%w, fileName: %s", err, fileName) + } + if sn.idxSlot.ModTime().Before(sn.seg.ModTime()) { + // Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent + sn.idxSlot.Close() + sn.idxSlot = nil + } + return nil +} + +type beaconBlockSegments struct { + lock sync.RWMutex + segments []*BeaconBlockSegment +} + +func (s *beaconBlockSegments) View(f func(segments []*BeaconBlockSegment) error) error { + s.lock.RLock() + defer s.lock.RUnlock() + return f(s.segments) +} + +func BeaconBlocksIdx(ctx context.Context, sn snaptype.FileInfo, segmentFilePath string, blockFrom, blockTo uint64, snapDir string, tmpDir string, p *background.Progress, lvl log.Lvl, logger log.Logger) (err error) { + defer func() { + if rec := recover(); rec != nil { + err = fmt.Errorf("BeaconBlocksIdx: at=%d-%d, %v, %s", blockFrom, blockTo, rec, dbg.Stack()) + } + }() + + // Calculate how many records there will be in the index + d, err := compress.NewDecompressor(path.Join(snapDir, segmentFilePath)) + if err != nil { + return err + } + defer d.Close() + + _, fname := filepath.Split(segmentFilePath) + p.Name.Store(&fname) + p.Total.Store(uint64(d.Count())) + + if err := Idx(ctx, d, sn.From, tmpDir, log.LvlDebug, func(idx *recsplit.RecSplit, i, offset uint64, word []byte) error { + if i%100_000 == 0 { + logger.Log(lvl, "Compressing beacon blocks", "progress", i) + } + p.Processed.Add(1) + num := make([]byte, 8) + n := binary.PutUvarint(num, i) + if err := idx.AddKey(num[:n], offset); err != nil { + return err + } + return nil + }, logger); err != nil { + return fmt.Errorf("BodyNumberIdx: %w", err) + } + + return nil +} + +type CaplinSnapshots struct { + indicesReady atomic.Bool + segmentsReady atomic.Bool + + BeaconBlocks *beaconBlockSegments + + dir string + segmentsMax atomic.Uint64 // all types of .seg files are available - up to this number + idxMax atomic.Uint64 // all types of .idx files are available - up to this number + cfg ethconfig.BlocksFreezing + logger log.Logger +} + +// NewCaplinSnapshots - opens all snapshots. But to simplify everything: +// - it opens snapshots only on App start and immutable after +// - all snapshots of given blocks range must exist - to make this blocks range available +// - gaps are not allowed +// - segment have [from:to) semantic +func NewCaplinSnapshots(cfg ethconfig.BlocksFreezing, snapDir string, logger log.Logger) *CaplinSnapshots { + return &CaplinSnapshots{dir: snapDir, cfg: cfg, BeaconBlocks: &beaconBlockSegments{}, logger: logger} +} + +func (s *CaplinSnapshots) IndicesMax() uint64 { return s.idxMax.Load() } +func (s *CaplinSnapshots) SegmentsMax() uint64 { return s.segmentsMax.Load() } +func (s *CaplinSnapshots) BlocksAvailable() uint64 { + return cmp.Min(s.segmentsMax.Load(), s.idxMax.Load()) +} + +// ReopenList stops on optimistic=false, continue opening files on optimistic=true +func (s *CaplinSnapshots) ReopenList(fileNames []string, optimistic bool) error { + s.BeaconBlocks.lock.Lock() + defer s.BeaconBlocks.lock.Unlock() + + s.closeWhatNotInList(fileNames) + var segmentsMax uint64 + var segmentsMaxSet bool +Loop: + for _, fName := range fileNames { + f, ok := snaptype.ParseFileName(s.dir, fName) + if !ok { + continue + } + var processed bool = true + + switch f.T { + case snaptype.BeaconBlocks: + var sn *BeaconBlockSegment + var exists bool + for _, sn2 := range s.BeaconBlocks.segments { + if sn2.seg == nil { // it's ok if some segment was not able to open + continue + } + if fName == sn2.seg.FileName() { + sn = sn2 + exists = true + break + } + } + if !exists { + sn = &BeaconBlockSegment{ranges: Range{f.From, f.To}} + } + if err := sn.reopenSeg(s.dir); err != nil { + if errors.Is(err, os.ErrNotExist) { + if optimistic { + continue Loop + } else { + break Loop + } + } + if optimistic { + s.logger.Warn("[snapshots] open segment", "err", err) + continue Loop + } else { + return err + } + } + + if !exists { + // it's possible to iterate over .seg file even if you don't have index + // then make segment available even if index open may fail + s.BeaconBlocks.segments = append(s.BeaconBlocks.segments, sn) + } + if err := sn.reopenIdxIfNeed(s.dir, optimistic); err != nil { + return err + } + } + + if processed { + if f.To > 0 { + segmentsMax = f.To - 1 + } else { + segmentsMax = 0 + } + segmentsMaxSet = true + } + } + if segmentsMaxSet { + s.segmentsMax.Store(segmentsMax) + } + s.segmentsReady.Store(true) + s.idxMax.Store(s.idxAvailability()) + s.indicesReady.Store(true) + + return nil +} + +func (s *CaplinSnapshots) idxAvailability() uint64 { + var beaconBlocks uint64 + for _, seg := range s.BeaconBlocks.segments { + if seg.idxSlot == nil { + break + } + beaconBlocks = seg.ranges.to - 1 + } + return beaconBlocks +} + +func (s *CaplinSnapshots) ReopenFolder() error { + files, _, err := SegmentsCaplin(s.dir) + if err != nil { + return err + } + list := make([]string, 0, len(files)) + for _, f := range files { + _, fName := filepath.Split(f.Path) + list = append(list, fName) + } + return s.ReopenList(list, false) +} + +func (s *CaplinSnapshots) closeWhatNotInList(l []string) { +Loop1: + for i, sn := range s.BeaconBlocks.segments { + if sn.seg == nil { + continue Loop1 + } + _, name := filepath.Split(sn.seg.FilePath()) + for _, fName := range l { + if fName == name { + continue Loop1 + } + } + sn.close() + s.BeaconBlocks.segments[i] = nil + } + var i int + for i = 0; i < len(s.BeaconBlocks.segments) && s.BeaconBlocks.segments[i] != nil && s.BeaconBlocks.segments[i].seg != nil; i++ { + } + tail := s.BeaconBlocks.segments[i:] + s.BeaconBlocks.segments = s.BeaconBlocks.segments[:i] + for i = 0; i < len(tail); i++ { + if tail[i] != nil { + tail[i].close() + tail[i] = nil + } + } +} + +type CaplinView struct { + s *CaplinSnapshots + closed bool +} + +func (s *CaplinSnapshots) View() *CaplinView { + v := &CaplinView{s: s} + v.s.BeaconBlocks.lock.RLock() + return v +} + +func (v *CaplinView) Close() { + if v.closed { + return + } + v.closed = true + v.s.BeaconBlocks.lock.RUnlock() + +} + +func (v *CaplinView) BeaconBlocks() []*BeaconBlockSegment { return v.s.BeaconBlocks.segments } + +func (v *CaplinView) BeaconBlocksSegment(slot uint64) (*BeaconBlockSegment, bool) { + for _, seg := range v.BeaconBlocks() { + if !(slot >= seg.ranges.from && slot < seg.ranges.to) { + continue + } + return seg, true + } + return nil, false +} + +func dumpBeaconBlocksRange(ctx context.Context, db kv.RoDB, b persistence.BlockSource, fromSlot uint64, toSlot uint64, tmpDir, snapDir string, workers int, lvl log.Lvl, logger log.Logger) error { + segName := snaptype.SegmentFileName(fromSlot, toSlot, snaptype.BeaconBlocks) + f, _ := snaptype.ParseFileName(snapDir, segName) + + sn, err := compress.NewCompressor(ctx, "Snapshot BeaconBlocks", f.Path, tmpDir, compress.MinPatternScore, workers, lvl, logger) + if err != nil { + return err + } + defer sn.Close() + + tx, err := db.BeginRo(ctx) + if err != nil { + return err + } + defer tx.Rollback() + // Generate .seg file, which is just the list of beacon blocks. + for i := fromSlot; i < toSlot; i++ { + obj, err := b.GetBlock(ctx, tx, i) + if err != nil { + return err + } + if i%20_000 == 0 { + logger.Log(lvl, "Dumping beacon blocks", "progress", i) + } + if obj == nil { + + if err := sn.AddWord(nil); err != nil { + return err + } + continue + } + var buf bytes.Buffer + if err := snapshot_format.WriteBlockForSnapshot(obj.Data, &buf); err != nil { + return err + } + word := buf.Bytes() + + if err := sn.AddWord(word); err != nil { + return err + } + + } + if err := sn.Compress(); err != nil { + return fmt.Errorf("compress: %w", err) + } + // Generate .idx file, which is the slot => offset mapping. + p := &background.Progress{} + + return BeaconBlocksIdx(ctx, f, segName, fromSlot, toSlot, snapDir, tmpDir, p, lvl, logger) +} + +func DumpBeaconBlocks(ctx context.Context, db kv.RoDB, b persistence.BlockSource, fromSlot, toSlot, blocksPerFile uint64, tmpDir, snapDir string, workers int, lvl log.Lvl, logger log.Logger) error { + if blocksPerFile == 0 { + return nil + } + + for i := fromSlot; i < toSlot; i = chooseSegmentEnd(i, toSlot, blocksPerFile) { + if toSlot-i < blocksPerFile { + break + } + to := chooseSegmentEnd(i, toSlot, blocksPerFile) + logger.Log(lvl, "Dumping beacon blocks", "from", i, "to", to) + if err := dumpBeaconBlocksRange(ctx, db, b, i, to, tmpDir, snapDir, workers, lvl, logger); err != nil { + return err + } + } + return nil +} From 3d3c0bec1805b44c814e427438d8dc86a7cda450 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 25 Oct 2023 11:35:22 +0700 Subject: [PATCH 07/44] downloader: log.Trace non-important log messages instead of skipping it (#8574) --- erigon-lib/downloader/downloadercfg/logger.go | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/erigon-lib/downloader/downloadercfg/logger.go b/erigon-lib/downloader/downloadercfg/logger.go index 49bee98dd42..a64a4993a39 100644 --- a/erigon-lib/downloader/downloadercfg/logger.go +++ b/erigon-lib/downloader/downloadercfg/logger.go @@ -73,6 +73,7 @@ func (b adapterHandler) Handle(r lg.Record) { strings.Contains(str, "EOF") || strings.Contains(str, "closed") || strings.Contains(str, "connection reset by peer") || strings.Contains(str, "use of closed network connection") || strings.Contains(str, "broken pipe") || strings.Contains(str, "inited with remoteAddr") if skip { + log.Trace(str) break } log.Debug(str) @@ -82,13 +83,14 @@ func (b adapterHandler) Handle(r lg.Record) { //strings.Contains(str, "banning ip ") || //strings.Contains(str, "spurious timer") { // suppress useless errors if skip { + log.Trace(str) break } - log.Info(str) case lg.Warning: str := r.String() - skip := strings.Contains(str, "EOF") + skip := strings.Contains(str, "EOF") || + strings.Contains(str, "requested chunk too long") //if strings.Contains(str, "could not find offer for id") { // suppress useless errors // break @@ -105,9 +107,6 @@ func (b adapterHandler) Handle(r lg.Record) { //if strings.Contains(str, "being sole dirtier of piece") { // suppress useless errors // break //} - if strings.Contains(str, "requested chunk too long") { // suppress useless errors - break - } //if strings.Contains(str, "reservation cancelled") { // suppress useless errors // break //} @@ -116,38 +115,35 @@ func (b adapterHandler) Handle(r lg.Record) { //} if skip { + log.Trace(str) break } log.Warn(str) case lg.Error: str := r.String() skip := strings.Contains(str, "EOF") - if skip { + log.Trace(str) break } log.Error(str) case lg.Critical: str := r.String() - skip := strings.Contains(str, "EOF") || strings.Contains(str, "torrent closed") - //if strings.Contains(str, "don't want conns") { // suppress useless errors - // break - //} - + skip := strings.Contains(str, "EOF") || + strings.Contains(str, "torrent closed") || + strings.Contains(str, "don't want conns") if skip { + log.Trace(str) break } log.Error(str) default: str := r.String() - skip := false - if strings.Contains(str, "unhandled response status") { // suppress useless errors - break - } + skip := strings.Contains(str, "EOF") || strings.Contains(str, "unhandled response status") if skip { + log.Trace(str) break } - log.Info("[downloader] "+r.String(), "torrent_log_type", "unknown", "or", lvl.LogString()) } } From 52c4489b04eba4947bbd6e7bd2ac839d2ce4037d Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 25 Oct 2023 11:35:45 +0700 Subject: [PATCH 08/44] sapshots: remove modtime protection (#8573) Historically we had several times when: - erigon downloaded new version of .seg file - or didn't finish download and start indexing this was a "quick-fix protection" against this cases but now we have other protections for this cases let's try to remove this one - because it's not compatible with "copy datadir" and "restore datadir from backup" scenarios --- .../freezeblocks/block_snapshots.go | 57 ++++++------------- .../freezeblocks/bor_snapshots.go | 10 ---- .../freezeblocks/caplin_snapshots.go | 5 -- 3 files changed, 16 insertions(+), 56 deletions(-) diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index 97e791128bb..d7d7ce35207 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -121,11 +121,7 @@ func (sn *HeaderSegment) reopenIdx(dir string) (err error) { if err != nil { return fmt.Errorf("%w, fileName: %s", err, fileName) } - if sn.idxHeaderHash.ModTime().Before(sn.seg.ModTime()) { - // Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent - sn.idxHeaderHash.Close() - sn.idxHeaderHash = nil - } + return nil } @@ -182,11 +178,6 @@ func (sn *BodySegment) reopenIdx(dir string) (err error) { if err != nil { return fmt.Errorf("%w, fileName: %s", err, fileName) } - if sn.idxBodyNumber.ModTime().Before(sn.seg.ModTime()) { - // Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent - sn.idxBodyNumber.Close() - sn.idxBodyNumber = nil - } return nil } @@ -229,24 +220,27 @@ func (sn *TxnSegment) reopenIdx(dir string) (err error) { if err != nil { return fmt.Errorf("%w, fileName: %s", err, fileName) } - if sn.IdxTxnHash.ModTime().Before(sn.Seg.ModTime()) { - log.Trace("[snapshots] skip index because it modify time is ahead before .seg file", "name", sn.IdxTxnHash.FileName()) - // Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent - sn.IdxTxnHash.Close() - sn.IdxTxnHash = nil - } + + /* + // Historically we had several times when: + // - erigon downloaded new version of .seg file + // - or didn't finish download and start indexing + // this was a "quick-fix protection" against this cases + // but now we have other protections for this cases + // let's try to remove this one - because it's not compatible with "copy datadir" and "restore datadir from backup" scenarios + if sn.IdxTxnHash.ModTime().Before(sn.Seg.ModTime()) { + log.Trace("[snapshots] skip index because it modify time is ahead before .seg file", "name", sn.IdxTxnHash.FileName()) + //Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent + sn.IdxTxnHash.Close() + sn.IdxTxnHash = nil + } + */ fileName = snaptype.IdxFileName(sn.ranges.from, sn.ranges.to, snaptype.Transactions2Block.String()) sn.IdxTxnHash2BlockNum, err = recsplit.OpenIndex(path.Join(dir, fileName)) if err != nil { return fmt.Errorf("%w, fileName: %s", err, fileName) } - if sn.IdxTxnHash2BlockNum.ModTime().Before(sn.Seg.ModTime()) { - log.Trace("[snapshots] skip index because it modify time is ahead before .seg file", "name", sn.IdxTxnHash2BlockNum.FileName()) - // Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent - sn.IdxTxnHash2BlockNum.Close() - sn.IdxTxnHash2BlockNum = nil - } return nil } @@ -1547,10 +1541,6 @@ func dumpBlocksRange(ctx context.Context, blockFrom, blockTo uint64, tmpDir, sna } func hasIdxFile(sn snaptype.FileInfo, logger log.Logger) bool { - stat, err := os.Stat(sn.Path) - if err != nil { - return false - } dir, _ := filepath.Split(sn.Path) fName := snaptype.IdxFileName(sn.From, sn.To, sn.T.String()) var result = true @@ -1560,22 +1550,12 @@ func hasIdxFile(sn snaptype.FileInfo, logger log.Logger) bool { if err != nil { return false } - // If index was created before the segment file, it needs to be ignored (and rebuilt) - if idx.ModTime().Before(stat.ModTime()) { - logger.Warn("Index file has timestamp before segment file, will be recreated", "segfile", sn.Path, "segtime", stat.ModTime(), "idxfile", fName, "idxtime", idx.ModTime()) - result = false - } idx.Close() case snaptype.Transactions: idx, err := recsplit.OpenIndex(path.Join(dir, fName)) if err != nil { return false } - // If index was created before the segment file, it needs to be ignored (and rebuilt) - if idx.ModTime().Before(stat.ModTime()) { - log.Warn("Index file has timestamp before segment file, will be recreated", "segfile", sn.Path, "segtime", stat.ModTime(), "idxfile", fName, "idxtime", idx.ModTime()) - result = false - } idx.Close() fName = snaptype.IdxFileName(sn.From, sn.To, snaptype.Transactions2Block.String()) @@ -1583,11 +1563,6 @@ func hasIdxFile(sn snaptype.FileInfo, logger log.Logger) bool { if err != nil { return false } - // If index was created before the segment file, it needs to be ignored (and rebuilt) - if idx.ModTime().Before(stat.ModTime()) { - logger.Warn("Index file has timestamp before segment file, will be recreated", "segfile", sn.Path, "segtime", stat.ModTime(), "idxfile", fName, "idxtime", idx.ModTime()) - result = false - } idx.Close() } return result diff --git a/turbo/snapshotsync/freezeblocks/bor_snapshots.go b/turbo/snapshotsync/freezeblocks/bor_snapshots.go index 6c06aad6a6d..bec3a359585 100644 --- a/turbo/snapshotsync/freezeblocks/bor_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/bor_snapshots.go @@ -83,11 +83,6 @@ func (sn *BorEventSegment) reopenIdx(dir string) (err error) { if err != nil { return fmt.Errorf("%w, fileName: %s", err, fileName) } - if sn.IdxBorTxnHash.ModTime().Before(sn.seg.ModTime()) { - // Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent - sn.IdxBorTxnHash.Close() - sn.IdxBorTxnHash = nil - } return nil } @@ -154,11 +149,6 @@ func (sn *BorSpanSegment) reopenIdx(dir string) (err error) { if err != nil { return fmt.Errorf("%w, fileName: %s", err, fileName) } - if sn.idx.ModTime().Before(sn.seg.ModTime()) { - // Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent - sn.idx.Close() - sn.idx = nil - } return nil } diff --git a/turbo/snapshotsync/freezeblocks/caplin_snapshots.go b/turbo/snapshotsync/freezeblocks/caplin_snapshots.go index 221cbe79301..54c9cd2c5dc 100644 --- a/turbo/snapshotsync/freezeblocks/caplin_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/caplin_snapshots.go @@ -83,11 +83,6 @@ func (sn *BeaconBlockSegment) reopenIdx(dir string) (err error) { if err != nil { return fmt.Errorf("%w, fileName: %s", err, fileName) } - if sn.idxSlot.ModTime().Before(sn.seg.ModTime()) { - // Index has been created before the segment file, needs to be ignored (and rebuilt) as inconsistent - sn.idxSlot.Close() - sn.idxSlot = nil - } return nil } From 95424b5ccc29d58003e3ad3724854fb4b351fc53 Mon Sep 17 00:00:00 2001 From: Anshal Shukla <53994948+anshalshukla@users.noreply.github.com> Date: Wed, 25 Oct 2023 14:46:43 +0530 Subject: [PATCH 09/44] fix nil error in bor devnet (#8578) --- eth/backend.go | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/eth/backend.go b/eth/backend.go index c8a07fc2d73..cd793545ae3 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -286,22 +286,6 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger logger: logger, } - // Check if we have an already initialized chain and fall back to - // that if so. Otherwise we need to generate a new genesis spec. - blockReader, blockWriter, allSnapshots, agg, err := setUpBlockReader(ctx, chainKv, config.Dirs, config.Snapshot, config.HistoryV3, config.Genesis.Config.Bor != nil, logger) - if err != nil { - return nil, err - } - backend.agg, backend.blockSnapshots, backend.blockReader, backend.blockWriter = agg, allSnapshots, blockReader, blockWriter - - if config.HistoryV3 { - backend.chainDB, err = temporal.New(backend.chainDB, agg, systemcontracts.SystemContractCodeLookup[config.Genesis.Config.ChainName]) - if err != nil { - return nil, err - } - chainKv = backend.chainDB //nolint - } - var chainConfig *chain.Config var genesis *types.Block if err := backend.chainDB.Update(context.Background(), func(tx kv.RwTx) error { @@ -329,6 +313,22 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger logger.Info("Initialised chain configuration", "config", chainConfig, "genesis", genesis.Hash()) + // Check if we have an already initialized chain and fall back to + // that if so. Otherwise we need to generate a new genesis spec. + blockReader, blockWriter, allSnapshots, agg, err := setUpBlockReader(ctx, chainKv, config.Dirs, config.Snapshot, config.HistoryV3, chainConfig.Bor != nil, logger) + if err != nil { + return nil, err + } + backend.agg, backend.blockSnapshots, backend.blockReader, backend.blockWriter = agg, allSnapshots, blockReader, blockWriter + + if config.HistoryV3 { + backend.chainDB, err = temporal.New(backend.chainDB, agg, systemcontracts.SystemContractCodeLookup[config.Genesis.Config.ChainName]) + if err != nil { + return nil, err + } + chainKv = backend.chainDB //nolint + } + if err := backend.setUpSnapDownloader(ctx, config.Downloader); err != nil { return nil, err } From 38e91809f971a2038900d033a5d7e2933888f303 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Wed, 25 Oct 2023 14:02:31 +0200 Subject: [PATCH 10/44] =?UTF-8?q?Revert=20"Move=20validator=20set=20snapsh?= =?UTF-8?q?ot=20computation=20to=20bor=5Fheimdall=20stage=E2=80=A6=20(#858?= =?UTF-8?q?0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PR #8202 might cause Issue #8550, so reverting it until Alexey's return. This reverts commit 2ce98f8337f15a07424b43f939def47d7a546778. --- cmd/integration/commands/stages.go | 18 +- cmd/rpcdaemon/rpcservices/eth_backend.go | 3 - cmd/state/exec3/state.go | 1 - consensus/bor/bor.go | 196 ++++++++--- consensus/bor/bor_test.go | 27 +- consensus/bor/heimdall/span/spanner.go | 15 +- consensus/bor/snapshot.go | 40 +-- consensus/bor/span.go | 4 +- consensus/bor/valset/validator_set.go | 1 - consensus/chain_reader.go | 8 - consensus/consensus.go | 2 - consensus/merge/merge_test.go | 4 - core/chain_makers.go | 1 - erigon-lib/tools/golangci_lint.sh | 2 +- eth/backend.go | 20 +- eth/stagedsync/chain_reader.go | 3 - eth/stagedsync/stage_bor_heimdall.go | 323 +----------------- eth/stagedsync/stage_headers.go | 8 - turbo/services/interfaces.go | 5 - .../snapshotsync/freezeblocks/block_reader.go | 71 ---- .../freezeblocks/bor_snapshots.go | 4 +- turbo/stages/mock/mock_sentry.go | 17 +- turbo/stages/stageloop.go | 7 +- 23 files changed, 212 insertions(+), 568 deletions(-) diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index c86e70f465b..8896ae7b27d 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -11,8 +11,6 @@ import ( "time" "github.com/c2h5oh/datasize" - lru "github.com/hashicorp/golang-lru/arc/v2" - "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/bor/heimdall" "github.com/ledgerwatch/erigon/consensus/bor/heimdallgrpc" "github.com/ledgerwatch/erigon/core/rawdb/blockio" @@ -27,7 +25,6 @@ import ( chain2 "github.com/ledgerwatch/erigon-lib/chain" "github.com/ledgerwatch/erigon-lib/commitment" common2 "github.com/ledgerwatch/erigon-lib/common" - libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/cmp" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/common/dir" @@ -1556,18 +1553,7 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig, notifications := &shards.Notifications{} blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, db, notifications.Events, logger) - var ( - snapDb kv.RwDB - recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot] - signatures *lru.ARCCache[libcommon.Hash, libcommon.Address] - ) - if bor, ok := engine.(*bor.Bor); ok { - snapDb = bor.DB - recents = bor.Recents - signatures = bor.Signatures - } - stages := stages2.NewDefaultStages(context.Background(), db, snapDb, p2p.Config{}, &cfg, sentryControlServer, notifications, nil, blockReader, blockRetire, agg, nil, nil, - heimdallClient, recents, signatures, logger) + stages := stages2.NewDefaultStages(context.Background(), db, p2p.Config{}, &cfg, sentryControlServer, notifications, nil, blockReader, blockRetire, agg, nil, nil, heimdallClient, logger) sync := stagedsync.New(stages, stagedsync.DefaultUnwindOrder, stagedsync.DefaultPruneOrder, logger) miner := stagedsync.NewMiningState(&cfg.Miner) @@ -1580,7 +1566,7 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig, miningSync := stagedsync.New( stagedsync.MiningStages(ctx, stagedsync.StageMiningCreateBlockCfg(db, miner, *chainConfig, engine, nil, nil, dirs.Tmp, blockReader), - stagedsync.StageBorHeimdallCfg(db, snapDb, miner, *chainConfig, heimdallClient, blockReader, nil, nil, recents, signatures), + stagedsync.StageBorHeimdallCfg(db, miner, *chainConfig, heimdallClient, blockReader, nil, nil), stagedsync.StageMiningExecCfg(db, miner, events, *chainConfig, engine, &vm.Config{}, dirs.Tmp, nil, 0, nil, nil, blockReader), stagedsync.StageHashStateCfg(db, dirs, historyV3), stagedsync.StageTrieCfg(db, false, true, false, dirs.Tmp, blockReader, nil, historyV3, agg), diff --git a/cmd/rpcdaemon/rpcservices/eth_backend.go b/cmd/rpcdaemon/rpcservices/eth_backend.go index aa4f8192ee0..44f1d91e61d 100644 --- a/cmd/rpcdaemon/rpcservices/eth_backend.go +++ b/cmd/rpcdaemon/rpcservices/eth_backend.go @@ -271,9 +271,6 @@ func (back *RemoteBackend) EventLookup(ctx context.Context, tx kv.Getter, txnHas func (back *RemoteBackend) EventsByBlock(ctx context.Context, tx kv.Tx, hash common.Hash, blockNum uint64) ([]rlp.RawValue, error) { return back.blockReader.EventsByBlock(ctx, tx, hash, blockNum) } -func (back *RemoteBackend) Span(ctx context.Context, tx kv.Getter, spanId uint64) ([]byte, error) { - return back.blockReader.Span(ctx, tx, spanId) -} func (back *RemoteBackend) NodeInfo(ctx context.Context, limit uint32) ([]p2p.NodeInfo, error) { nodes, err := back.remoteEthBackend.NodeInfo(ctx, &remote.NodesInfoRequest{Limit: limit}) diff --git a/cmd/state/exec3/state.go b/cmd/state/exec3/state.go index 4e3297219d0..a5f61b03bda 100644 --- a/cmd/state/exec3/state.go +++ b/cmd/state/exec3/state.go @@ -286,7 +286,6 @@ func (cr ChainReader) HasBlock(hash libcommon.Hash, number uint64) bool { func (cr ChainReader) BorEventsByBlock(hash libcommon.Hash, number uint64) []rlp.RawValue { panic("") } -func (cr ChainReader) BorSpan(spanId uint64) []byte { panic("") } func NewWorkersPool(lock sync.Locker, ctx context.Context, background bool, chainDb kv.RoDB, rs *state.StateV3, in *exec22.QueueWithRetry, blockReader services.FullBlockReader, chainConfig *chain.Config, genesis *types.Genesis, engine consensus.Engine, workerCount int) (reconWorkers []*Worker, applyWorker *Worker, rws *exec22.ResultsQueue, clear func(), wait func()) { reconWorkers = make([]*Worker, workerCount) diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 5014c715524..103e9d32aa3 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -4,7 +4,6 @@ import ( "bytes" "context" "encoding/hex" - "encoding/json" "errors" "fmt" "io" @@ -16,6 +15,7 @@ import ( "sync/atomic" "time" + "github.com/google/btree" lru "github.com/hashicorp/golang-lru/arc/v2" "github.com/ledgerwatch/erigon/eth/ethconfig/estimate" "github.com/ledgerwatch/log/v3" @@ -116,7 +116,7 @@ var ( // errInvalidSpanValidators is returned if a block contains an // invalid list of validators (i.e. non divisible by 40 bytes). - ErrInvalidSpanValidators = errors.New("invalid validator list on sprint end block") + errInvalidSpanValidators = errors.New("invalid validator list on sprint end block") // errInvalidMixDigest is returned if a block's mix digest is non-zero. errInvalidMixDigest = errors.New("non-zero mix digest") @@ -146,7 +146,7 @@ var ( type SignerFn func(signer libcommon.Address, mimeType string, message []byte) ([]byte, error) // ecrecover extracts the Ethereum account address from a signed header. -func Ecrecover(header *types.Header, sigcache *lru.ARCCache[libcommon.Hash, libcommon.Address], c *chain.BorConfig) (libcommon.Address, error) { +func ecrecover(header *types.Header, sigcache *lru.ARCCache[libcommon.Hash, libcommon.Address], c *chain.BorConfig) (libcommon.Address, error) { // If the signature's already cached, return that hash := header.Hash() if address, known := sigcache.Get(hash); known { @@ -250,8 +250,8 @@ type Bor struct { DB kv.RwDB // Database to store and retrieve snapshot checkpoints blockReader services.FullBlockReader - Recents *lru.ARCCache[libcommon.Hash, *Snapshot] // Snapshots for recent block to speed up reorgs - Signatures *lru.ARCCache[libcommon.Hash, libcommon.Address] // Signatures of recent blocks to speed up mining + recents *lru.ARCCache[libcommon.Hash, *Snapshot] // Snapshots for recent block to speed up reorgs + signatures *lru.ARCCache[libcommon.Hash, libcommon.Address] // Signatures of recent blocks to speed up mining authorizedSigner atomic.Pointer[signer] // Ethereum address and sign function of the signing key @@ -263,7 +263,8 @@ type Bor struct { // scope event.SubscriptionScope // The fields below are for testing only - fakeDiff bool // Skip difficulty verifications + fakeDiff bool // Skip difficulty verifications + spanCache *btree.BTree closeOnce sync.Once logger log.Logger @@ -394,11 +395,12 @@ func New( config: borConfig, DB: db, blockReader: blockReader, - Recents: recents, - Signatures: signatures, + recents: recents, + signatures: signatures, spanner: spanner, GenesisContractsClient: genesisContracts, HeimdallClient: heimdallClient, + spanCache: btree.New(32), execCtx: context.Background(), logger: logger, closeCh: make(chan struct{}), @@ -462,8 +464,9 @@ func NewRo(chainConfig *chain.Config, db kv.RoDB, blockReader services.FullBlock DB: rwWrapper{db}, blockReader: blockReader, logger: logger, - Recents: recents, - Signatures: signatures, + recents: recents, + signatures: signatures, + spanCache: btree.New(32), execCtx: context.Background(), closeCh: make(chan struct{}), } @@ -487,7 +490,7 @@ func (c *Bor) HeaderProgress(p HeaderProgress) { // This is thread-safe (only access the header and config (which is never updated), // as well as signatures, which are lru.ARCCache, which is thread-safe) func (c *Bor) Author(header *types.Header) (libcommon.Address, error) { - return Ecrecover(header, c.Signatures, c.config) + return ecrecover(header, c.signatures, c.config) } // VerifyHeader checks whether a header conforms to the consensus rules. @@ -547,7 +550,7 @@ func (c *Bor) verifyHeader(chain consensus.ChainHeaderReader, header *types.Head } if isSprintEnd && signersBytes%validatorHeaderBytesLength != 0 { - return ErrInvalidSpanValidators + return errInvalidSpanValidators } // Ensure that the mix digest is zero as we don't have fork protection currently @@ -641,7 +644,67 @@ func (c *Bor) verifyCascadingFields(chain consensus.ChainHeaderReader, header *t if parent.Time+c.config.CalculatePeriod(number) > header.Time { return ErrInvalidTimestamp } - return nil + + sprintLength := c.config.CalculateSprint(number) + + // Verify the validator list match the local contract + // + // Note: Here we fetch the data from span instead of contract + // as done in bor client. The contract (validator set) returns + // a fixed span for 0th span i.e. 0 - 255 blocks. Hence, the + // contract data and span data won't match for that. Skip validating + // for 0th span. TODO: Remove `number > zerothSpanEnd` check + // once we start fetching validator data from contract. + if number > zerothSpanEnd && isSprintStart(number+1, sprintLength) { + producerSet, err := c.spanner.GetCurrentProducers(number+1, c.authorizedSigner.Load().signer, c.getSpanForBlock) + + if err != nil { + return err + } + + sort.Sort(valset.ValidatorsByAddress(producerSet)) + + headerVals, err := valset.ParseValidators(header.Extra[extraVanity : len(header.Extra)-extraSeal]) + + if err != nil { + return err + } + + if len(producerSet) != len(headerVals) { + return errInvalidSpanValidators + } + + for i, val := range producerSet { + if !bytes.Equal(val.HeaderBytes(), headerVals[i].HeaderBytes()) { + return errInvalidSpanValidators + } + } + } + snap, err := c.snapshot(chain, number-1, header.ParentHash, parents) + if err != nil { + return err + } + + // verify the validator list in the last sprint block + if isSprintStart(number, sprintLength) { + // Retrieve the snapshot needed to verify this header and cache it + parentValidatorBytes := parent.Extra[extraVanity : len(parent.Extra)-extraSeal] + validatorsBytes := make([]byte, len(snap.ValidatorSet.Validators)*validatorHeaderBytesLength) + + currentValidators := snap.ValidatorSet.Copy().Validators + // sort validator by address + sort.Sort(valset.ValidatorsByAddress(currentValidators)) + for i, validator := range currentValidators { + copy(validatorsBytes[i*validatorHeaderBytesLength:], validator.HeaderBytes()) + } + // len(header.Extra) >= extraVanity+extraSeal has already been validated in ValidateHeaderExtraField, so this won't result in a panic + if !bytes.Equal(parentValidatorBytes, validatorsBytes) { + return &MismatchingValidatorsError{number - 1, validatorsBytes, parentValidatorBytes} + } + } + + // All basic checks passed, verify the seal and return + return c.verifySeal(chain, header, parents, snap) } func (c *Bor) initFrozenSnapshot(chain consensus.ChainHeaderReader, number uint64, logEvery *time.Ticker) (snap *Snapshot, err error) { @@ -660,16 +723,16 @@ func (c *Bor) initFrozenSnapshot(chain consensus.ChainHeaderReader, number uint6 // get validators and current span var validators []*valset.Validator - validators, err = c.spanner.GetCurrentValidators(0, c.authorizedSigner.Load().signer, chain) + validators, err = c.spanner.GetCurrentValidators(1, c.authorizedSigner.Load().signer, c.getSpanForBlock) if err != nil { return nil, err } // new snap shot - snap = NewSnapshot(c.config, c.Signatures, 0, hash, validators, c.logger) + snap = newSnapshot(c.config, c.signatures, 0, hash, validators, c.logger) - if err = snap.Store(c.DB); err != nil { + if err = snap.store(c.DB); err != nil { return nil, err } @@ -690,13 +753,13 @@ func (c *Bor) initFrozenSnapshot(chain consensus.ChainHeaderReader, number uint6 // `batchSize` < `inmemorySignatures`: means all current batch will fit in cache - and `snap.apply` will find it there. snap := snap g.Go(func() error { - _, _ = Ecrecover(header, snap.sigcache, snap.config) + _, _ = ecrecover(header, snap.sigcache, snap.config) return nil }) } initialHeaders = append(initialHeaders, header) if len(initialHeaders) == cap(initialHeaders) { - snap, err = snap.Apply(nil, initialHeaders, c.logger) + snap, err = snap.apply(initialHeaders, c.logger) if err != nil { return nil, err @@ -711,7 +774,7 @@ func (c *Bor) initFrozenSnapshot(chain consensus.ChainHeaderReader, number uint6 } } - if snap, err = snap.Apply(nil, initialHeaders, c.logger); err != nil { + if snap, err = snap.apply(initialHeaders, c.logger); err != nil { return nil, err } } @@ -731,14 +794,14 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash li //nolint:govet for snap == nil { // If an in-memory snapshot was found, use that - if s, ok := c.Recents.Get(hash); ok { + if s, ok := c.recents.Get(hash); ok { snap = s break } // If an on-disk snapshot can be found, use that if number%snapshotPersistInterval == 0 { - if s, err := LoadSnapshot(c.config, c.Signatures, c.DB, hash); err == nil { + if s, err := loadSnapshot(c.config, c.signatures, c.DB, hash); err == nil { c.logger.Trace("Loaded snapshot from disk", "number", number, "hash", hash) snap = s @@ -789,6 +852,7 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash li if snap == nil && chain != nil && number <= chain.FrozenBlocks() { var err error + c.frozenSnapshotsInit.Do(func() { snap, err = c.initFrozenSnapshot(chain, number, logEvery) }) @@ -809,15 +873,15 @@ func (c *Bor) snapshot(chain consensus.ChainHeaderReader, number uint64, hash li } var err error - if snap, err = snap.Apply(nil, headers, c.logger); err != nil { + if snap, err = snap.apply(headers, c.logger); err != nil { return nil, err } - c.Recents.Add(snap.Hash, snap) + c.recents.Add(snap.Hash, snap) // If we've generated a new persistent snapshot, save to disk if snap.Number%snapshotPersistInterval == 0 && len(headers) > 0 { - if err = snap.Store(c.DB); err != nil { + if err = snap.store(c.DB); err != nil { return nil, err } @@ -858,7 +922,7 @@ func (c *Bor) verifySeal(chain consensus.ChainHeaderReader, header *types.Header return errUnknownBlock } // Resolve the authorization key and check against signers - signer, err := Ecrecover(header, c.Signatures, c.config) + signer, err := ecrecover(header, c.signatures, c.config) if err != nil { return err } @@ -929,11 +993,7 @@ func (c *Bor) Prepare(chain consensus.ChainHeaderReader, header *types.Header, s // where it fetches producers internally. As we fetch data from span // in Erigon, use directly the `GetCurrentProducers` function. if isSprintStart(number+1, c.config.CalculateSprint(number)) { - var spanID uint64 - if number+1 > zerothSpanEnd { - spanID = 1 + (number+1-zerothSpanEnd-1)/spanLength - } - newValidators, err := c.spanner.GetCurrentProducers(spanID, c.authorizedSigner.Load().signer, chain) + newValidators, err := c.spanner.GetCurrentProducers(number+1, c.authorizedSigner.Load().signer, c.getSpanForBlock) if err != nil { return errUnknownValidators } @@ -994,13 +1054,13 @@ func (c *Bor) Finalize(config *chain.Config, header *types.Header, state *state. if isSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { cx := statefull.ChainContext{Chain: chain, Bor: c} + // check and commit span + if err := c.checkAndCommitSpan(state, header, cx, syscall); err != nil { + c.logger.Error("Error while committing span", "err", err) + return nil, types.Receipts{}, err + } if c.blockReader != nil { - // check and commit span - if err := c.checkAndCommitSpan(state, header, cx, syscall); err != nil { - c.logger.Error("Error while committing span", "err", err) - return nil, types.Receipts{}, err - } // commit states if err := c.CommitStates(state, header, cx, syscall); err != nil { c.logger.Error("Error while committing states", "err", err) @@ -1059,14 +1119,16 @@ func (c *Bor) FinalizeAndAssemble(chainConfig *chain.Config, header *types.Heade if isSprintStart(headerNumber, c.config.CalculateSprint(headerNumber)) { cx := statefull.ChainContext{Chain: chain, Bor: c} - if c.blockReader != nil { - // check and commit span - if err := c.checkAndCommitSpan(state, header, cx, syscall); err != nil { - c.logger.Error("Error while committing span", "err", err) - return nil, nil, types.Receipts{}, err - } + // check and commit span + err := c.checkAndCommitSpan(state, header, cx, syscall) + if err != nil { + c.logger.Error("Error while committing span", "err", err) + return nil, nil, types.Receipts{}, err + } + + if c.HeimdallClient != nil { // commit states - if err := c.CommitStates(state, header, cx, syscall); err != nil { + if err = c.CommitStates(state, header, cx, syscall); err != nil { c.logger.Error("Error while committing states", "err", err) return nil, nil, types.Receipts{}, err } @@ -1365,6 +1427,46 @@ func (c *Bor) needToCommitSpan(currentSpan *span.Span, headerNumber uint64) bool return false } +func (c *Bor) getSpanForBlock(blockNum uint64) (*span.HeimdallSpan, error) { + c.logger.Debug("Getting span", "for block", blockNum) + var borSpan *span.HeimdallSpan + c.spanCache.AscendGreaterOrEqual(&span.HeimdallSpan{Span: span.Span{EndBlock: blockNum}}, func(item btree.Item) bool { + borSpan = item.(*span.HeimdallSpan) + return false + }) + + if borSpan != nil && borSpan.StartBlock <= blockNum && borSpan.EndBlock >= blockNum { + return borSpan, nil + } + + // Span with given block block number is not loaded + // As span has fixed set of blocks (except 0th span), we can + // formulate it and get the exact ID we'd need to fetch. + var spanID uint64 + if blockNum > zerothSpanEnd { + spanID = 1 + (blockNum-zerothSpanEnd-1)/spanLength + } + + if c.HeimdallClient == nil { + return nil, fmt.Errorf("span with given block number is not loaded: %d", spanID) + } + + c.logger.Debug("Span with given block number is not loaded", "fetching span", spanID) + + response, err := c.HeimdallClient.Span(c.execCtx, spanID) + if err != nil { + return nil, err + } + borSpan = response + c.spanCache.ReplaceOrInsert(borSpan) + + for c.spanCache.Len() > 128 { + c.spanCache.DeleteMin() + } + + return borSpan, nil +} + func (c *Bor) fetchAndCommitSpan( newSpanID uint64, state *state.IntraBlockState, @@ -1383,10 +1485,12 @@ func (c *Bor) fetchAndCommitSpan( heimdallSpan = *s } else { - spanJson := chain.Chain.BorSpan(newSpanID) - if err := json.Unmarshal(spanJson, &heimdallSpan); err != nil { + response, err := c.HeimdallClient.Span(c.execCtx, newSpanID) + if err != nil { return err } + + heimdallSpan = *response } // check if chain id matches with heimdall span @@ -1496,6 +1600,10 @@ func (c *Bor) SetHeimdallClient(h heimdall.IHeimdallClient) { c.HeimdallClient = h } +func (c *Bor) GetCurrentValidators(blockNumber uint64, signer libcommon.Address, getSpanForBlock func(blockNum uint64) (*span.HeimdallSpan, error)) ([]*valset.Validator, error) { + return c.spanner.GetCurrentValidators(blockNumber, signer, getSpanForBlock) +} + // // Private methods // diff --git a/consensus/bor/bor_test.go b/consensus/bor/bor_test.go index 352686e5034..937868cab29 100644 --- a/consensus/bor/bor_test.go +++ b/consensus/bor/bor_test.go @@ -2,13 +2,11 @@ package bor_test import ( "context" - "encoding/json" "fmt" "math/big" "testing" "github.com/ledgerwatch/erigon-lib/chain" - "github.com/ledgerwatch/erigon-lib/common" libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/gointerfaces/sentry" "github.com/ledgerwatch/erigon-lib/kv/memdb" @@ -175,15 +173,9 @@ func (r headerReader) GetTd(libcommon.Hash, uint64) *big.Int { return nil } -func (r headerReader) BorSpan(spanId uint64) []byte { - b, _ := json.Marshal(&r.validator.heimdall.currentSpan) - return b -} - type spanner struct { *span.ChainSpanner - validatorAddress common.Address - currentSpan span.Span + currentSpan span.Span } func (c spanner) GetCurrentSpan(_ consensus.SystemCall) (*span.Span, error) { @@ -195,16 +187,6 @@ func (c *spanner) CommitSpan(heimdallSpan span.HeimdallSpan, syscall consensus.S return nil } -func (c *spanner) GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) { - return []*valset.Validator{ - { - ID: 1, - Address: c.validatorAddress, - VotingPower: 1000, - ProposerPriority: 1, - }}, nil -} - type validator struct { *mock.MockSentry heimdall *test_heimdall @@ -266,18 +248,19 @@ func (v validator) verifyBlocks(blocks []*types.Block) error { func newValidator(t *testing.T, heimdall *test_heimdall, blocks map[uint64]*types.Block) validator { logger := log.Root() - validatorKey, _ := crypto.GenerateKey() - validatorAddress := crypto.PubkeyToAddress(validatorKey.PublicKey) bor := bor.New( heimdall.chainConfig, memdb.New(""), nil, /* blockReader */ - &spanner{span.NewChainSpanner(contract.ValidatorSet(), heimdall.chainConfig, false, logger), validatorAddress, span.Span{}}, + &spanner{span.NewChainSpanner(contract.ValidatorSet(), heimdall.chainConfig, false, logger), span.Span{}}, heimdall, test_genesisContract{}, logger, ) + validatorKey, _ := crypto.GenerateKey() + validatorAddress := crypto.PubkeyToAddress(validatorKey.PublicKey) + /*fmt.Printf("Private: 0x%s\nPublic: 0x%s\nAddress: %s\n", hex.EncodeToString(crypto.FromECDSA(validatorKey)), hex.EncodeToString(crypto.MarshalPubkey(&validatorKey.PublicKey)), diff --git a/consensus/bor/heimdall/span/spanner.go b/consensus/bor/heimdall/span/spanner.go index 968aeff65bf..b7f50ff796b 100644 --- a/consensus/bor/heimdall/span/spanner.go +++ b/consensus/bor/heimdall/span/spanner.go @@ -2,7 +2,6 @@ package span import ( "encoding/hex" - "encoding/json" "math/big" "github.com/ledgerwatch/erigon-lib/chain" @@ -68,30 +67,28 @@ func (c *ChainSpanner) GetCurrentSpan(syscall consensus.SystemCall) (*Span, erro return &span, nil } -func (c *ChainSpanner) GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) { +func (c *ChainSpanner) GetCurrentValidators(blockNumber uint64, signer libcommon.Address, getSpanForBlock func(blockNum uint64) (*HeimdallSpan, error)) ([]*valset.Validator, error) { // Use hardcoded bor devnet valset if chain-name = bor-devnet if NetworkNameVals[c.chainConfig.ChainName] != nil && c.withoutHeimdall { return NetworkNameVals[c.chainConfig.ChainName], nil } - spanBytes := chain.BorSpan(spanId) - var span HeimdallSpan - if err := json.Unmarshal(spanBytes, &span); err != nil { + span, err := getSpanForBlock(blockNumber) + if err != nil { return nil, err } return span.ValidatorSet.Validators, nil } -func (c *ChainSpanner) GetCurrentProducers(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) { +func (c *ChainSpanner) GetCurrentProducers(blockNumber uint64, signer libcommon.Address, getSpanForBlock func(blockNum uint64) (*HeimdallSpan, error)) ([]*valset.Validator, error) { // Use hardcoded bor devnet valset if chain-name = bor-devnet if NetworkNameVals[c.chainConfig.ChainName] != nil && c.withoutHeimdall { return NetworkNameVals[c.chainConfig.ChainName], nil } - spanBytes := chain.BorSpan(spanId) - var span HeimdallSpan - if err := json.Unmarshal(spanBytes, &span); err != nil { + span, err := getSpanForBlock(blockNumber) + if err != nil { return nil, err } diff --git a/consensus/bor/snapshot.go b/consensus/bor/snapshot.go index 5edaf596efc..8a60b4bd683 100644 --- a/consensus/bor/snapshot.go +++ b/consensus/bor/snapshot.go @@ -37,7 +37,7 @@ const BorSeparate = "BorSeparate" // newSnapshot creates a new snapshot with the specified startup parameters. This // method does not initialize the set of recent signers, so only ever use if for // the genesis block. -func NewSnapshot( +func newSnapshot( config *chain.BorConfig, sigcache *lru.ARCCache[common.Hash, common.Address], number uint64, @@ -57,7 +57,7 @@ func NewSnapshot( } // loadSnapshot loads an existing snapshot from the database. -func LoadSnapshot(config *chain.BorConfig, sigcache *lru.ARCCache[common.Hash, common.Address], db kv.RwDB, hash common.Hash) (*Snapshot, error) { +func loadSnapshot(config *chain.BorConfig, sigcache *lru.ARCCache[common.Hash, common.Address], db kv.RwDB, hash common.Hash) (*Snapshot, error) { tx, err := db.BeginRo(context.Background()) if err != nil { return nil, err @@ -90,7 +90,7 @@ func LoadSnapshot(config *chain.BorConfig, sigcache *lru.ARCCache[common.Hash, c } // store inserts the snapshot into the database. -func (s *Snapshot) Store(db kv.RwDB) error { +func (s *Snapshot) store(db kv.RwDB) error { blob, err := json.Marshal(s) if err != nil { return err @@ -118,7 +118,7 @@ func (s *Snapshot) copy() *Snapshot { return cpy } -func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger log.Logger) (*Snapshot, error) { +func (s *Snapshot) apply(headers []*types.Header, logger log.Logger) (*Snapshot, error) { // Allow passing in no headers for cleaner code if len(headers) == 0 { return s, nil @@ -146,36 +146,30 @@ func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger l delete(snap.Recents, number-sprintLen) } // Resolve the authorization key and check against signers - signer, err := Ecrecover(header, s.sigcache, s.config) + signer, err := ecrecover(header, s.sigcache, s.config) if err != nil { return nil, err } var validSigner bool - var succession int // check if signer is in validator set - if !snap.ValidatorSet.HasAddress(signer) { - return snap, &UnauthorizedSignerError{number, signer.Bytes()} - } - if succession, err = snap.GetSignerSuccessionNumber(signer); err != nil { - return snap, err - } - - // add recents - snap.Recents[number] = signer + if snap.ValidatorSet.HasAddress(signer) { + if _, err = snap.GetSignerSuccessionNumber(signer); err != nil { + return nil, err + } - validSigner = true + // add recents + snap.Recents[number] = signer - if parent != nil && header.Time < parent.Time+CalcProducerDelay(number, succession, s.config) { - return snap, &BlockTooSoonError{number, succession} + validSigner = true } // change validator set and change proposer if number > 0 && (number+1)%sprintLen == 0 { if err := ValidateHeaderExtraField(header.Extra); err != nil { - return snap, err + return nil, err } validatorBytes := header.Extra[extraVanity : len(header.Extra)-extraSeal] @@ -187,13 +181,13 @@ func (s *Snapshot) Apply(parent *types.Header, headers []*types.Header, logger l } if number > 64 && !validSigner { - return snap, &UnauthorizedSignerError{number, signer.Bytes()} + return nil, &UnauthorizedSignerError{number, signer.Bytes()} } - parent = header - snap.Number = number - snap.Hash = header.Hash() } + snap.Number += uint64(len(headers)) + snap.Hash = headers[len(headers)-1].Hash() + return snap, nil } diff --git a/consensus/bor/span.go b/consensus/bor/span.go index 41e8abec8db..7365fd10c80 100644 --- a/consensus/bor/span.go +++ b/consensus/bor/span.go @@ -10,7 +10,7 @@ import ( //go:generate mockgen -destination=./span_mock.go -package=bor . Spanner type Spanner interface { GetCurrentSpan(syscall consensus.SystemCall) (*span.Span, error) - GetCurrentValidators(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) - GetCurrentProducers(spanId uint64, signer libcommon.Address, chain consensus.ChainHeaderReader) ([]*valset.Validator, error) + GetCurrentValidators(blockNumber uint64, signer libcommon.Address, getSpanForBlock func(blockNum uint64) (*span.HeimdallSpan, error)) ([]*valset.Validator, error) + GetCurrentProducers(blockNumber uint64, signer libcommon.Address, getSpanForBlock func(blockNum uint64) (*span.HeimdallSpan, error)) ([]*valset.Validator, error) CommitSpan(heimdallSpan span.HeimdallSpan, syscall consensus.SystemCall) error } diff --git a/consensus/bor/valset/validator_set.go b/consensus/bor/valset/validator_set.go index 505d513a206..de2792d5285 100644 --- a/consensus/bor/valset/validator_set.go +++ b/consensus/bor/valset/validator_set.go @@ -320,7 +320,6 @@ func (vals *ValidatorSet) TotalVotingPower(logger log.Logger) int64 { // is returned. func (vals *ValidatorSet) GetProposer() (proposer *Validator) { if len(vals.Validators) == 0 { - fmt.Printf("GetProposer - no validator\n") return nil } diff --git a/consensus/chain_reader.go b/consensus/chain_reader.go index f79de40c4cc..795e2a856e4 100644 --- a/consensus/chain_reader.go +++ b/consensus/chain_reader.go @@ -78,11 +78,3 @@ func (cr ChainReaderImpl) GetTd(hash libcommon.Hash, number uint64) *big.Int { func (cr ChainReaderImpl) FrozenBlocks() uint64 { return cr.BlockReader.FrozenBlocks() } - -func (cr ChainReaderImpl) BorSpan(spanId uint64) []byte { - spanBytes, err := cr.BlockReader.Span(context.Background(), cr.Db, spanId) - if err != nil { - log.Error("BorSpan failed", "err", err) - } - return spanBytes -} diff --git a/consensus/consensus.go b/consensus/consensus.go index 32bcb8cbe72..1165c95bbef 100644 --- a/consensus/consensus.go +++ b/consensus/consensus.go @@ -55,8 +55,6 @@ type ChainHeaderReader interface { // Number of blocks frozen in the block snapshots FrozenBlocks() uint64 - - BorSpan(spanId uint64) []byte } // ChainReader defines a small collection of methods needed to access the local diff --git a/consensus/merge/merge_test.go b/consensus/merge/merge_test.go index aee7810cd2f..bf0558211d3 100644 --- a/consensus/merge/merge_test.go +++ b/consensus/merge/merge_test.go @@ -41,10 +41,6 @@ func (r readerMock) FrozenBlocks() uint64 { return 0 } -func (r readerMock) BorSpan(spanId uint64) []byte { - return nil -} - // The thing only that changes beetwen normal ethash checks other than POW, is difficulty // and nonce so we are gonna test those func TestVerifyHeaderDifficulty(t *testing.T) { diff --git a/core/chain_makers.go b/core/chain_makers.go index 25a96626be9..a2d7221e29a 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -653,4 +653,3 @@ func (cr *FakeChainReader) FrozenBlocks() uint64 func (cr *FakeChainReader) BorEventsByBlock(hash libcommon.Hash, number uint64) []rlp.RawValue { return nil } -func (cr *FakeChainReader) BorSpan(spanId uint64) []byte { return nil } diff --git a/erigon-lib/tools/golangci_lint.sh b/erigon-lib/tools/golangci_lint.sh index 0b27a507523..f3fb6befce8 100755 --- a/erigon-lib/tools/golangci_lint.sh +++ b/erigon-lib/tools/golangci_lint.sh @@ -13,7 +13,7 @@ fi if ! which golangci-lint > /dev/null then echo "golangci-lint tool is not found, install it with:" - echo " make lint-deps" + echo " make lintci-deps" echo "or follow https://golangci-lint.run/usage/install/" exit 2 fi diff --git a/eth/backend.go b/eth/backend.go index cd793545ae3..eb6deac2c3f 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -31,7 +31,6 @@ import ( "sync" "time" - lru "github.com/hashicorp/golang-lru/arc/v2" "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon-lib/downloader/downloadergrpc" "github.com/ledgerwatch/erigon-lib/kv/kvcfg" @@ -485,6 +484,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger } } + fmt.Println(blockReader.FrozenBlocks()) inMemoryExecution := func(batch kv.RwTx, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, notifications *shards.Notifications) error { terseLogger := log.New() @@ -578,20 +578,10 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger backend.minedBlocks = miner.MiningResultCh // proof-of-work mining - var ( - snapDb kv.RwDB - recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot] - signatures *lru.ARCCache[libcommon.Hash, libcommon.Address] - ) - if bor, ok := backend.engine.(*bor.Bor); ok { - snapDb = bor.DB - recents = bor.Recents - signatures = bor.Signatures - } mining := stagedsync.New( stagedsync.MiningStages(backend.sentryCtx, stagedsync.StageMiningCreateBlockCfg(backend.chainDB, miner, *backend.chainConfig, backend.engine, backend.txPoolDB, nil, tmpdir, backend.blockReader), - stagedsync.StageBorHeimdallCfg(backend.chainDB, snapDb, miner, *backend.chainConfig, heimdallClient, backend.blockReader, nil, nil, recents, signatures), + stagedsync.StageBorHeimdallCfg(backend.chainDB, miner, *backend.chainConfig, heimdallClient, backend.blockReader, nil, nil), stagedsync.StageMiningExecCfg(backend.chainDB, miner, backend.notifications.Events, *backend.chainConfig, backend.engine, &vm.Config{}, tmpdir, nil, 0, backend.txPool, backend.txPoolDB, blockReader), stagedsync.StageHashStateCfg(backend.chainDB, dirs, config.HistoryV3), stagedsync.StageTrieCfg(backend.chainDB, false, true, true, tmpdir, blockReader, nil, config.HistoryV3, backend.agg), @@ -611,7 +601,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger proposingSync := stagedsync.New( stagedsync.MiningStages(backend.sentryCtx, stagedsync.StageMiningCreateBlockCfg(backend.chainDB, miningStatePos, *backend.chainConfig, backend.engine, backend.txPoolDB, param, tmpdir, backend.blockReader), - stagedsync.StageBorHeimdallCfg(backend.chainDB, snapDb, miningStatePos, *backend.chainConfig, heimdallClient, backend.blockReader, nil, nil, recents, signatures), + stagedsync.StageBorHeimdallCfg(backend.chainDB, miningStatePos, *backend.chainConfig, heimdallClient, backend.blockReader, nil, nil), stagedsync.StageMiningExecCfg(backend.chainDB, miningStatePos, backend.notifications.Events, *backend.chainConfig, backend.engine, &vm.Config{}, tmpdir, interrupt, param.PayloadId, backend.txPool, backend.txPoolDB, blockReader), stagedsync.StageHashStateCfg(backend.chainDB, dirs, config.HistoryV3), stagedsync.StageTrieCfg(backend.chainDB, false, true, true, tmpdir, blockReader, nil, config.HistoryV3, backend.agg), @@ -744,8 +734,8 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger backend.ethBackendRPC, backend.miningRPC, backend.stateChangesClient = ethBackendRPC, miningRPC, stateDiffClient - backend.syncStages = stages2.NewDefaultStages(backend.sentryCtx, backend.chainDB, snapDb, stack.Config().P2P, config, backend.sentriesClient, backend.notifications, backend.downloaderClient, - blockReader, blockRetire, backend.agg, backend.silkworm, backend.forkValidator, heimdallClient, recents, signatures, logger) + backend.syncStages = stages2.NewDefaultStages(backend.sentryCtx, backend.chainDB, stack.Config().P2P, config, backend.sentriesClient, backend.notifications, backend.downloaderClient, + blockReader, blockRetire, backend.agg, backend.silkworm, backend.forkValidator, heimdallClient, logger) backend.syncUnwindOrder = stagedsync.DefaultUnwindOrder backend.syncPruneOrder = stagedsync.DefaultPruneOrder backend.stagedSync = stagedsync.New(backend.syncStages, backend.syncUnwindOrder, backend.syncPruneOrder, logger) diff --git a/eth/stagedsync/chain_reader.go b/eth/stagedsync/chain_reader.go index 046c7b24e64..d86f7c3f2ff 100644 --- a/eth/stagedsync/chain_reader.go +++ b/eth/stagedsync/chain_reader.go @@ -84,6 +84,3 @@ func (cr ChainReader) FrozenBlocks() uint64 { func (cr ChainReader) BorEventsByBlock(hash libcommon.Hash, number uint64) []rlp.RawValue { panic("") } -func (cr ChainReader) BorSpan(spanId uint64) []byte { - panic("") -} diff --git a/eth/stagedsync/stage_bor_heimdall.go b/eth/stagedsync/stage_bor_heimdall.go index dfe8389a11f..d6343f0c67b 100644 --- a/eth/stagedsync/stage_bor_heimdall.go +++ b/eth/stagedsync/stage_bor_heimdall.go @@ -1,54 +1,37 @@ package stagedsync import ( - "bytes" "context" "encoding/binary" "encoding/json" "fmt" "math/big" - "sort" "strconv" "time" - lru "github.com/hashicorp/golang-lru/arc/v2" "github.com/ledgerwatch/erigon-lib/chain" - "github.com/ledgerwatch/erigon-lib/common" - libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon/accounts/abi" - "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/bor/contract" "github.com/ledgerwatch/erigon/consensus/bor/finality/generics" "github.com/ledgerwatch/erigon/consensus/bor/finality/whitelist" "github.com/ledgerwatch/erigon/consensus/bor/heimdall" - "github.com/ledgerwatch/erigon/consensus/bor/heimdall/span" - "github.com/ledgerwatch/erigon/consensus/bor/valset" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/dataflow" - "github.com/ledgerwatch/erigon/eth/ethconfig/estimate" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/stages/headerdownload" "github.com/ledgerwatch/log/v3" - "golang.org/x/sync/errgroup" ) const ( - spanLength = 6400 // Number of blocks in a span - zerothSpanEnd = 255 // End block of 0th span - inmemorySnapshots = 128 // Number of recent vote snapshots to keep in memory - inmemorySignatures = 4096 // Number of recent block signatures to keep in memory - snapshotPersistInterval = 1024 // Number of blocks after which to persist the vote snapshot to the database - extraVanity = 32 // Fixed number of extra-data prefix bytes reserved for signer vanity - extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal + spanLength = 6400 // Number of blocks in a span + zerothSpanEnd = 255 // End block of 0th span ) type BorHeimdallCfg struct { db kv.RwDB - snapDb kv.RwDB // Database to store and retrieve snapshot checkpoints miningState MiningState chainConfig chain.Config heimdallClient heimdall.IHeimdallClient @@ -56,25 +39,19 @@ type BorHeimdallCfg struct { hd *headerdownload.HeaderDownload penalize func(context.Context, []headerdownload.PenaltyItem) stateReceiverABI abi.ABI - recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot] - signatures *lru.ARCCache[libcommon.Hash, libcommon.Address] } func StageBorHeimdallCfg( db kv.RwDB, - snapDb kv.RwDB, miningState MiningState, chainConfig chain.Config, heimdallClient heimdall.IHeimdallClient, blockReader services.FullBlockReader, hd *headerdownload.HeaderDownload, penalize func(context.Context, []headerdownload.PenaltyItem), - recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], - signatures *lru.ARCCache[libcommon.Hash, libcommon.Address], ) BorHeimdallCfg { return BorHeimdallCfg{ db: db, - snapDb: snapDb, miningState: miningState, chainConfig: chainConfig, heimdallClient: heimdallClient, @@ -82,8 +59,6 @@ func StageBorHeimdallCfg( hd: hd, penalize: penalize, stateReceiverABI: contract.StateReceiver(), - recents: recents, - signatures: signatures, } } @@ -184,49 +159,21 @@ func BorHeimdallForward( if k != nil { lastEventId = binary.BigEndian.Uint64(k) } - type LastFrozen interface { + type LastFrozenEvent interface { LastFrozenEventID() uint64 - LastFrozenSpanID() uint64 } - snapshotLastEventId := cfg.blockReader.(LastFrozen).LastFrozenEventID() + snapshotLastEventId := cfg.blockReader.(LastFrozenEvent).LastFrozenEventID() if snapshotLastEventId > lastEventId { lastEventId = snapshotLastEventId } - sCursor, err := tx.Cursor(kv.BorSpans) - if err != nil { - return err - } - defer sCursor.Close() - k, _, err = sCursor.Last() - if err != nil { - return err - } - var nextSpanId uint64 - if k != nil { - nextSpanId = binary.BigEndian.Uint64(k) + 1 - } - snapshotLastSpanId := cfg.blockReader.(LastFrozen).LastFrozenSpanID() - if snapshotLastSpanId+1 > nextSpanId { - nextSpanId = snapshotLastSpanId + 1 - } - var endSpanID uint64 - if headNumber > zerothSpanEnd { - endSpanID = 2 + (headNumber-zerothSpanEnd)/spanLength - } - lastBlockNum := s.BlockNumber if cfg.blockReader.FrozenBorBlocks() > lastBlockNum { lastBlockNum = cfg.blockReader.FrozenBorBlocks() } - recents, err := lru.NewARC[libcommon.Hash, *bor.Snapshot](inmemorySnapshots) - if err != nil { - return err - } - signatures, err := lru.NewARC[libcommon.Hash, libcommon.Address](inmemorySignatures) - if err != nil { - return err + + if !mine { + logger.Info("["+s.LogPrefix()+"] Processng sync events...", "from", lastBlockNum+1) } - chain := NewChainReaderImpl(&cfg.chainConfig, tx, cfg.blockReader, logger) var blockNum uint64 var fetchTime time.Duration @@ -236,17 +183,6 @@ func BorHeimdallForward( logTimer := time.NewTicker(30 * time.Second) defer logTimer.Stop() - if endSpanID >= nextSpanId { - logger.Info("["+s.LogPrefix()+"] Processing spans...", "from", nextSpanId, "to", endSpanID) - } - for spanID := nextSpanId; spanID <= endSpanID; spanID++ { - if lastSpanId, err = fetchAndWriteSpans(ctx, spanID, tx, cfg.heimdallClient, s.LogPrefix(), logger); err != nil { - return err - } - } - if !mine { - logger.Info("["+s.LogPrefix()+"] Processing sync events...", "from", lastBlockNum+1, "to", headNumber) - } for blockNum = lastBlockNum + 1; blockNum <= headNumber; blockNum++ { select { default: @@ -285,15 +221,9 @@ func BorHeimdallForward( fetchTime += callTime } - if err = PersistValidatorSets(u, ctx, tx, cfg.blockReader, cfg.chainConfig.Bor, chain, blockNum, header.Hash(), recents, signatures, cfg.snapDb, logger); err != nil { - return fmt.Errorf("persistValidatorSets: %w", err) - } - if !mine && header != nil { - sprintLength := cfg.chainConfig.Bor.CalculateSprint(blockNum) - if blockNum > zerothSpanEnd && ((blockNum+1)%sprintLength == 0) { - if err = checkHeaderExtraData(u, ctx, chain, blockNum, header); err != nil { - return err - } + if blockNum == 1 || (blockNum > zerothSpanEnd && ((blockNum-zerothSpanEnd-1)%spanLength) == 0) { + if lastSpanId, err = fetchAndWriteSpans(ctx, blockNum, tx, cfg.heimdallClient, s.LogPrefix(), logger); err != nil { + return err } } } @@ -313,46 +243,6 @@ func BorHeimdallForward( return } -func checkHeaderExtraData( - u Unwinder, - ctx context.Context, - chain consensus.ChainHeaderReader, - blockNum uint64, - header *types.Header, -) error { - var spanID uint64 - if blockNum+1 > zerothSpanEnd { - spanID = 1 + (blockNum+1-zerothSpanEnd-1)/spanLength - } - spanBytes := chain.BorSpan(spanID) - var sp span.HeimdallSpan - if err := json.Unmarshal(spanBytes, &sp); err != nil { - return err - } - producerSet := make([]*valset.Validator, len(sp.SelectedProducers)) - for i := range sp.SelectedProducers { - producerSet[i] = &sp.SelectedProducers[i] - } - - sort.Sort(valset.ValidatorsByAddress(producerSet)) - - headerVals, err := valset.ParseValidators(header.Extra[extraVanity : len(header.Extra)-extraSeal]) - if err != nil { - return err - } - - if len(producerSet) != len(headerVals) { - return bor.ErrInvalidSpanValidators - } - - for i, val := range producerSet { - if !bytes.Equal(val.HeaderBytes(), headerVals[i].HeaderBytes()) { - return bor.ErrInvalidSpanValidators - } - } - return nil -} - func fetchAndWriteBorEvents( ctx context.Context, blockReader services.FullBlockReader, @@ -458,12 +348,17 @@ func fetchAndWriteBorEvents( func fetchAndWriteSpans( ctx context.Context, - spanId uint64, + blockNum uint64, tx kv.RwTx, heimdallClient heimdall.IHeimdallClient, logPrefix string, logger log.Logger, ) (uint64, error) { + var spanId uint64 + if blockNum > zerothSpanEnd { + spanId = 1 + (blockNum-zerothSpanEnd-1)/spanLength + } + logger.Debug(fmt.Sprintf("[%s] Fetching span", logPrefix), "id", spanId) response, err := heimdallClient.Span(ctx, spanId) if err != nil { return 0, err @@ -477,195 +372,9 @@ func fetchAndWriteSpans( if err = tx.Put(kv.BorSpans, spanIDBytes[:], spanBytes); err != nil { return 0, err } - logger.Debug(fmt.Sprintf("[%s] Wrote span", logPrefix), "id", spanId) return spanId, nil } -// Not used currently -func PersistValidatorSets( - u Unwinder, - ctx context.Context, - tx kv.Tx, - blockReader services.FullBlockReader, - config *chain.BorConfig, - chain consensus.ChainHeaderReader, - blockNum uint64, - hash libcommon.Hash, - recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], - signatures *lru.ARCCache[libcommon.Hash, libcommon.Address], - snapDb kv.RwDB, - logger log.Logger) error { - - logEvery := time.NewTicker(logInterval) - defer logEvery.Stop() - // Search for a snapshot in memory or on disk for checkpoints - var snap *bor.Snapshot - - headers := make([]*types.Header, 0, 16) - var parent *types.Header - - //nolint:govet - for snap == nil { - // If an in-memory snapshot was found, use that - if s, ok := recents.Get(hash); ok { - snap = s - - break - } - - // If an on-disk snapshot can be found, use that - if blockNum%snapshotPersistInterval == 0 { - if s, err := bor.LoadSnapshot(config, signatures, snapDb, hash); err == nil { - logger.Trace("Loaded snapshot from disk", "number", blockNum, "hash", hash) - - snap = s - - break - } - } - - // No snapshot for this header, gather the header and move backward - var header *types.Header - // No explicit parents (or no more left), reach out to the database - if parent != nil { - header = parent - } else if chain != nil { - header = chain.GetHeader(hash, blockNum) - //logger.Info(fmt.Sprintf("header %d %x => %+v\n", header.Number.Uint64(), header.Hash(), header)) - } - - if header == nil { - return consensus.ErrUnknownAncestor - } - - if blockNum == 0 { - break - } - - headers = append(headers, header) - blockNum, hash = blockNum-1, header.ParentHash - if chain != nil { - parent = chain.GetHeader(hash, blockNum) - } - - if chain != nil && blockNum < chain.FrozenBlocks() { - break - } - - select { - case <-logEvery.C: - logger.Info("Gathering headers for validator proposer prorities (backwards)", "blockNum", blockNum) - default: - } - } - if snap == nil && chain != nil && blockNum <= chain.FrozenBlocks() { - // Special handling of the headers in the snapshot - zeroHeader := chain.GetHeaderByNumber(0) - if zeroHeader != nil { - // get checkpoint data - hash := zeroHeader.Hash() - - // get validators and current span - zeroSpanBytes, err := blockReader.Span(ctx, tx, 0) - if err != nil { - return err - } - var zeroSpan span.HeimdallSpan - if err = json.Unmarshal(zeroSpanBytes, &zeroSpan); err != nil { - return err - } - - // new snap shot - snap = bor.NewSnapshot(config, signatures, 0, hash, zeroSpan.ValidatorSet.Validators, logger) - if err := snap.Store(snapDb); err != nil { - return fmt.Errorf("snap.Store (0): %w", err) - } - logger.Info("Stored proposer snapshot to disk", "number", 0, "hash", hash) - g := errgroup.Group{} - g.SetLimit(estimate.AlmostAllCPUs()) - defer g.Wait() - - batchSize := 128 // must be < inmemorySignatures - initialHeaders := make([]*types.Header, 0, batchSize) - parentHeader := zeroHeader - for i := uint64(1); i <= blockNum; i++ { - header := chain.GetHeaderByNumber(i) - { - // `snap.apply` bottleneck - is recover of signer. - // to speedup: recover signer in background goroutines and save in `sigcache` - // `batchSize` < `inmemorySignatures`: means all current batch will fit in cache - and `snap.apply` will find it there. - g.Go(func() error { - _, _ = bor.Ecrecover(header, signatures, config) - return nil - }) - } - initialHeaders = append(initialHeaders, header) - if len(initialHeaders) == cap(initialHeaders) { - if snap, err = snap.Apply(parentHeader, initialHeaders, logger); err != nil { - return fmt.Errorf("snap.Apply (inside loop): %w", err) - } - parentHeader = initialHeaders[len(initialHeaders)-1] - initialHeaders = initialHeaders[:0] - } - select { - case <-logEvery.C: - logger.Info("Computing validator proposer prorities (forward)", "blockNum", i) - default: - } - } - if snap, err = snap.Apply(parentHeader, initialHeaders, logger); err != nil { - return fmt.Errorf("snap.Apply (outside loop): %w", err) - } - } - } - - // check if snapshot is nil - if snap == nil { - return fmt.Errorf("unknown error while retrieving snapshot at block number %v", blockNum) - } - - // Previous snapshot found, apply any pending headers on top of it - for i := 0; i < len(headers)/2; i++ { - headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i] - } - - prevSnap := snap.Number - if len(headers) > 0 { - var err error - if snap, err = snap.Apply(parent, headers, logger); err != nil { - if snap != nil { - var badHash common.Hash - for _, header := range headers { - if header.Number.Uint64() == snap.Number+1 { - badHash = header.Hash() - break - } - } - u.UnwindTo(snap.Number, BadBlock(badHash, err)) - } else { - return fmt.Errorf("snap.Apply %d, headers %d-%d: %w", blockNum, headers[0].Number.Uint64(), headers[len(headers)-1].Number.Uint64(), err) - } - } - } - - if prevSnap == snap.Number { - return nil - } - - recents.Add(snap.Hash, snap) - - // If we've generated a new persistent snapshot, save to disk - if snap.Number%snapshotPersistInterval == 0 && len(headers) > 0 { - if err := snap.Store(snapDb); err != nil { - return fmt.Errorf("snap.Store: %w", err) - } - - logger.Info("Stored proposer snapshot to disk", "number", snap.Number, "hash", snap.Hash) - } - - return nil -} - func BorHeimdallUnwind(u *UnwindState, ctx context.Context, s *StageState, tx kv.RwTx, cfg BorHeimdallCfg) (err error) { if cfg.chainConfig.Bor == nil { return diff --git a/eth/stagedsync/stage_headers.go b/eth/stagedsync/stage_headers.go index e8f968938cb..ea99b6c3943 100644 --- a/eth/stagedsync/stage_headers.go +++ b/eth/stagedsync/stage_headers.go @@ -568,11 +568,3 @@ func (cr ChainReaderImpl) BorEventsByBlock(hash libcommon.Hash, number uint64) [ } return events } -func (cr ChainReaderImpl) BorSpan(spanId uint64) []byte { - span, err := cr.blockReader.Span(context.Background(), cr.tx, spanId) - if err != nil { - log.Error("BorSpan failed", "err", err) - return nil - } - return span -} diff --git a/turbo/services/interfaces.go b/turbo/services/interfaces.go index 18350e0d9c6..592006477d2 100644 --- a/turbo/services/interfaces.go +++ b/turbo/services/interfaces.go @@ -38,10 +38,6 @@ type BorEventReader interface { EventsByBlock(ctx context.Context, tx kv.Tx, hash common.Hash, blockNum uint64) ([]rlp.RawValue, error) } -type BorSpanReader interface { - Span(ctx context.Context, tx kv.Getter, spanNum uint64) ([]byte, error) -} - type CanonicalReader interface { CanonicalHash(ctx context.Context, tx kv.Getter, blockNum uint64) (common.Hash, error) BadHeaderNumber(ctx context.Context, tx kv.Getter, hash common.Hash) (blockHeight *uint64, err error) @@ -75,7 +71,6 @@ type FullBlockReader interface { BodyReader HeaderReader BorEventReader - BorSpanReader TxnReader CanonicalReader diff --git a/turbo/snapshotsync/freezeblocks/block_reader.go b/turbo/snapshotsync/freezeblocks/block_reader.go index d1b67cc6404..430e9f5ab95 100644 --- a/turbo/snapshotsync/freezeblocks/block_reader.go +++ b/turbo/snapshotsync/freezeblocks/block_reader.go @@ -235,10 +235,6 @@ func (r *RemoteBlockReader) EventsByBlock(ctx context.Context, tx kv.Tx, hash co return result, nil } -func (r *RemoteBlockReader) Span(ctx context.Context, tx kv.Getter, spanId uint64) ([]byte, error) { - return nil, nil -} - // BlockReader can read blocks from db and snapshots type BlockReader struct { sn *RoSnapshots @@ -1082,73 +1078,6 @@ func (r *BlockReader) LastFrozenEventID() uint64 { return lastEventID } -func (r *BlockReader) LastFrozenSpanID() uint64 { - view := r.borSn.View() - defer view.Close() - segments := view.Spans() - if len(segments) == 0 { - return 0 - } - lastSegment := segments[len(segments)-1] - var lastSpanID uint64 - if lastSegment.ranges.to > zerothSpanEnd { - lastSpanID = (lastSegment.ranges.to - zerothSpanEnd - 1) / spanLength - } - return lastSpanID -} - -func (r *BlockReader) Span(ctx context.Context, tx kv.Getter, spanId uint64) ([]byte, error) { - // Compute starting block of the span - var endBlock uint64 - if spanId > 0 { - endBlock = (spanId)*spanLength + zerothSpanEnd - } - var buf [8]byte - binary.BigEndian.PutUint64(buf[:], spanId) - if endBlock >= r.FrozenBorBlocks() { - v, err := tx.GetOne(kv.BorSpans, buf[:]) - if err != nil { - return nil, err - } - if v == nil { - return nil, fmt.Errorf("span %d not found (db)", spanId) - } - return common.Copy(v), nil - } - view := r.borSn.View() - defer view.Close() - segments := view.Spans() - for i := len(segments) - 1; i >= 0; i-- { - sn := segments[i] - if sn.idx == nil { - continue - } - var spanFrom uint64 - if sn.ranges.from > zerothSpanEnd { - spanFrom = 1 + (sn.ranges.from-zerothSpanEnd-1)/spanLength - } - if spanId < spanFrom { - continue - } - var spanTo uint64 - if sn.ranges.to > zerothSpanEnd { - spanTo = 1 + (sn.ranges.to-zerothSpanEnd-1)/spanLength - } - if spanId >= spanTo { - continue - } - if sn.idx.KeyCount() == 0 { - continue - } - offset := sn.idx.OrdinalLookup(spanId - sn.idx.BaseDataID()) - gg := sn.seg.MakeGetter() - gg.Reset(offset) - result, _ := gg.Next(nil) - return common.Copy(result), nil - } - return nil, fmt.Errorf("span %d not found (snapshots)", spanId) -} - // ---- Data Integrity part ---- func (r *BlockReader) ensureHeaderNumber(n uint64, seg *HeaderSegment) error { diff --git a/turbo/snapshotsync/freezeblocks/bor_snapshots.go b/turbo/snapshotsync/freezeblocks/bor_snapshots.go index bec3a359585..1caf5abdba8 100644 --- a/turbo/snapshotsync/freezeblocks/bor_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/bor_snapshots.go @@ -373,7 +373,7 @@ func DumpBorEvents(ctx context.Context, db kv.RoDB, blockFrom, blockTo uint64, w return nil } -// DumpBorSpans - [from, to) +// DumpBorEvents - [from, to) func DumpBorSpans(ctx context.Context, db kv.RoDB, blockFrom, blockTo uint64, workers int, lvl log.Lvl, logger log.Logger, collect func([]byte) error) error { logEvery := time.NewTicker(20 * time.Second) defer logEvery.Stop() @@ -1150,7 +1150,7 @@ func (m *BorMerger) Merge(ctx context.Context, snapshots *BorRoSnapshots, mergeR m.notifier.OnNewSnapshot() time.Sleep(1 * time.Second) // i working on blocking API - to ensure client does not use old snapsthos - and then delete them } - for _, t := range []snaptype.Type{snaptype.BorEvents, snaptype.BorSpans} { + for _, t := range []snaptype.Type{snaptype.BorEvents} { m.removeOldFiles(toMerge[t], snapDir) } } diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index 11e4860666d..df9e7df5f54 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -11,7 +11,6 @@ import ( "time" "github.com/c2h5oh/datasize" - lru "github.com/hashicorp/golang-lru/arc/v2" "github.com/holiman/uint256" "github.com/ledgerwatch/log/v3" "google.golang.org/protobuf/types/known/emptypb" @@ -396,16 +395,6 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK var snapshotsDownloader proto_downloader.DownloaderClient - var ( - snapDb kv.RwDB - recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot] - signatures *lru.ARCCache[libcommon.Hash, libcommon.Address] - ) - if bor, ok := engine.(*bor.Bor); ok { - snapDb = bor.DB - recents = bor.Recents - signatures = bor.Signatures - } // proof-of-stake mining assembleBlockPOS := func(param *core.BlockBuilderParameters, interrupt *int32) (*types.BlockWithReceipts, error) { miningStatePos := stagedsync.NewProposingState(&cfg.Miner) @@ -413,7 +402,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK proposingSync := stagedsync.New( stagedsync.MiningStages(mock.Ctx, stagedsync.StageMiningCreateBlockCfg(mock.DB, miningStatePos, *mock.ChainConfig, mock.Engine, mock.txPoolDB, param, tmpdir, mock.BlockReader), - stagedsync.StageBorHeimdallCfg(mock.DB, snapDb, miningStatePos, *mock.ChainConfig, nil, mock.BlockReader, nil, nil, recents, signatures), + stagedsync.StageBorHeimdallCfg(mock.DB, miningStatePos, *mock.ChainConfig, nil, mock.BlockReader, nil, nil), stagedsync.StageMiningExecCfg(mock.DB, miningStatePos, mock.Notifications.Events, *mock.ChainConfig, mock.Engine, &vm.Config{}, tmpdir, interrupt, param.PayloadId, mock.TxPool, mock.txPoolDB, mock.BlockReader), stagedsync.StageHashStateCfg(mock.DB, dirs, cfg.HistoryV3), stagedsync.StageTrieCfg(mock.DB, false, true, true, tmpdir, mock.BlockReader, nil, histV3, mock.agg), @@ -433,7 +422,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK stagedsync.DefaultStages(mock.Ctx, stagedsync.StageSnapshotsCfg(mock.DB, *mock.ChainConfig, dirs, blockRetire, snapshotsDownloader, mock.BlockReader, mock.Notifications.Events, mock.HistoryV3, mock.agg, nil), stagedsync.StageHeadersCfg(mock.DB, mock.sentriesClient.Hd, mock.sentriesClient.Bd, *mock.ChainConfig, sendHeaderRequest, propagateNewBlockHashes, penalize, cfg.BatchSize, false, mock.BlockReader, blockWriter, dirs.Tmp, mock.Notifications, engine_helpers.NewForkValidatorMock(1), nil), - stagedsync.StageBorHeimdallCfg(mock.DB, snapDb, stagedsync.MiningState{}, *mock.ChainConfig, nil /* heimdallClient */, mock.BlockReader, nil, nil, recents, signatures), + stagedsync.StageBorHeimdallCfg(mock.DB, stagedsync.MiningState{}, *mock.ChainConfig, nil /* heimdallClient */, mock.BlockReader, nil, nil), stagedsync.StageBlockHashesCfg(mock.DB, mock.Dirs.Tmp, mock.ChainConfig, blockWriter), stagedsync.StageBodiesCfg(mock.DB, mock.sentriesClient.Bd, sendBodyRequest, penalize, blockPropagator, cfg.Sync.BodyDownloadTimeoutSeconds, *mock.ChainConfig, mock.BlockReader, cfg.HistoryV3, blockWriter), stagedsync.StageSendersCfg(mock.DB, mock.ChainConfig, false, dirs.Tmp, prune, mock.BlockReader, mock.sentriesClient.Hd), @@ -496,7 +485,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK mock.MiningSync = stagedsync.New( stagedsync.MiningStages(mock.Ctx, stagedsync.StageMiningCreateBlockCfg(mock.DB, miner, *mock.ChainConfig, mock.Engine, nil, nil, dirs.Tmp, mock.BlockReader), - stagedsync.StageBorHeimdallCfg(mock.DB, snapDb, miner, *mock.ChainConfig, nil /*heimdallClient*/, mock.BlockReader, nil, nil, recents, signatures), + stagedsync.StageBorHeimdallCfg(mock.DB, miner, *mock.ChainConfig, nil /*heimdallClient*/, mock.BlockReader, nil, nil), stagedsync.StageMiningExecCfg(mock.DB, miner, nil, *mock.ChainConfig, mock.Engine, &vm.Config{}, dirs.Tmp, nil, 0, mock.TxPool, nil, mock.BlockReader), stagedsync.StageHashStateCfg(mock.DB, dirs, cfg.HistoryV3), stagedsync.StageTrieCfg(mock.DB, false, true, false, dirs.Tmp, mock.BlockReader, mock.sentriesClient.Hd, cfg.HistoryV3, mock.agg), diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go index 5a0ac96f24a..3ee7d432fe3 100644 --- a/turbo/stages/stageloop.go +++ b/turbo/stages/stageloop.go @@ -7,7 +7,6 @@ import ( "math/big" "time" - lru "github.com/hashicorp/golang-lru/arc/v2" "github.com/holiman/uint256" "github.com/ledgerwatch/log/v3" @@ -22,7 +21,6 @@ import ( "github.com/ledgerwatch/erigon/cmd/sentry/sentry" "github.com/ledgerwatch/erigon/consensus" - "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" "github.com/ledgerwatch/erigon/consensus/bor/heimdall" "github.com/ledgerwatch/erigon/consensus/misc" @@ -447,7 +445,6 @@ func StateStep(ctx context.Context, chainReader consensus.ChainReader, engine co func NewDefaultStages(ctx context.Context, db kv.RwDB, - snapDb kv.RwDB, p2pCfg p2p.Config, cfg *ethconfig.Config, controlServer *sentry.MultiClient, @@ -459,8 +456,6 @@ func NewDefaultStages(ctx context.Context, silkworm *silkworm.Silkworm, forkValidator *engine_helpers.ForkValidator, heimdallClient heimdall.IHeimdallClient, - recents *lru.ARCCache[libcommon.Hash, *bor.Snapshot], - signatures *lru.ARCCache[libcommon.Hash, libcommon.Address], logger log.Logger, ) []*stagedsync.Stage { dirs := cfg.Dirs @@ -479,7 +474,7 @@ func NewDefaultStages(ctx context.Context, return stagedsync.DefaultStages(ctx, stagedsync.StageSnapshotsCfg(db, *controlServer.ChainConfig, dirs, blockRetire, snapDownloader, blockReader, notifications.Events, cfg.HistoryV3, agg, silkworm), stagedsync.StageHeadersCfg(db, controlServer.Hd, controlServer.Bd, *controlServer.ChainConfig, controlServer.SendHeaderRequest, controlServer.PropagateNewBlockHashes, controlServer.Penalize, cfg.BatchSize, p2pCfg.NoDiscovery, blockReader, blockWriter, dirs.Tmp, notifications, forkValidator, loopBreakCheck), - stagedsync.StageBorHeimdallCfg(db, snapDb, stagedsync.MiningState{}, *controlServer.ChainConfig, heimdallClient, blockReader, controlServer.Hd, controlServer.Penalize, recents, signatures), + stagedsync.StageBorHeimdallCfg(db, stagedsync.MiningState{}, *controlServer.ChainConfig, heimdallClient, blockReader, controlServer.Hd, controlServer.Penalize), stagedsync.StageBlockHashesCfg(db, dirs.Tmp, controlServer.ChainConfig, blockWriter), stagedsync.StageBodiesCfg(db, controlServer.Bd, controlServer.SendBodyRequest, controlServer.Penalize, controlServer.BroadcastNewBlock, cfg.Sync.BodyDownloadTimeoutSeconds, *controlServer.ChainConfig, blockReader, cfg.HistoryV3, blockWriter), stagedsync.StageSendersCfg(db, controlServer.ChainConfig, false, dirs.Tmp, cfg.Prune, blockReader, controlServer.Hd), From 656c3d239ea6e14ebd350a8694c8a145b14bb5d3 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Wed, 25 Oct 2023 15:05:05 +0200 Subject: [PATCH 11/44] params: remove dev from v2.53.0 (#8581) --- params/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/params/version.go b/params/version.go index b8041f72db7..e5f3a428bb1 100644 --- a/params/version.go +++ b/params/version.go @@ -31,10 +31,10 @@ var ( // see https://calver.org const ( - VersionMajor = 2 // Major version component of the current release - VersionMinor = 53 // Minor version component of the current release - VersionMicro = 0 // Patch version component of the current release - VersionModifier = "dev" // Modifier component of the current release + VersionMajor = 2 // Major version component of the current release + VersionMinor = 53 // Minor version component of the current release + VersionMicro = 0 // Patch version component of the current release + VersionModifier = "" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" ) From 7aa79a5bbb80b25b1d236de4665cf45d66c3d9db Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 25 Oct 2023 20:08:50 +0700 Subject: [PATCH 12/44] TestState: share db (#8576) --- tests/state_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/state_test.go b/tests/state_test.go index 711294ef653..844288364c2 100644 --- a/tests/state_test.go +++ b/tests/state_test.go @@ -28,9 +28,9 @@ import ( "testing" "github.com/ledgerwatch/erigon-lib/common/datadir" + "github.com/ledgerwatch/erigon/core/state/temporal" "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/core/state/temporal" "github.com/ledgerwatch/erigon/core/vm" "github.com/ledgerwatch/erigon/eth/tracers/logger" ) @@ -38,7 +38,7 @@ import ( func TestState(t *testing.T) { defer log.Root().SetHandler(log.Root().GetHandler()) log.Root().SetHandler(log.LvlFilterHandler(log.LvlError, log.StderrHandler)) - if runtime.GOOS == "windows" || runtime.GOOS == "darwin" { + if runtime.GOOS == "windows" { t.Skip("fix me on win please") // it's too slow on win and stops on macos, need generally improve speed of this tests } //t.Parallel() @@ -49,12 +49,12 @@ func TestState(t *testing.T) { st.skipLoad(`^stTimeConsuming/`) st.skipLoad(`.*vmPerformance/loop.*`) + _, db, _ := temporal.NewTestDB(t, datadir.New(t.TempDir()), nil) st.walk(t, stateTestDir, func(t *testing.T, name string, test *StateTest) { for _, subtest := range test.Subtests() { subtest := subtest key := fmt.Sprintf("%s/%d", subtest.Fork, subtest.Index) t.Run(key, func(t *testing.T) { - _, db, _ := temporal.NewTestDB(t, datadir.New(t.TempDir()), nil) withTrace(t, func(vmconfig vm.Config) error { tx, err := db.BeginRw(context.Background()) if err != nil { From 0e1fa8dc3e948bf0ca1675878b23eb5e71c14ee5 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 25 Oct 2023 20:09:09 +0700 Subject: [PATCH 13/44] blocksReadAheadFunc: to calc `engine.Author` in background (#8499) Bor consensus: this calc is heavy and has cache --- eth/stagedsync/stage_execute.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/eth/stagedsync/stage_execute.go b/eth/stagedsync/stage_execute.go index 7c159cc005f..d6fa05570de 100644 --- a/eth/stagedsync/stage_execute.go +++ b/eth/stagedsync/stage_execute.go @@ -616,6 +616,8 @@ func blocksReadAheadFunc(ctx context.Context, tx kv.Tx, cfg *ExecuteBlockCfg, bl if block == nil { return nil } + _, _ = cfg.engine.Author(block.HeaderNoCopy()) // Bor consensus: this calc is heavy and has cache + senders := block.Body().SendersFromTxs() //TODO: BlockByNumber can return senders stateReader := state.NewPlainStateReader(tx) //TODO: can do on batch! if make batch thread-safe for _, sender := range senders { From e1c71bda2ee98d7c701b0c3b89f2e35e371dc9fd Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Wed, 25 Oct 2023 15:51:58 +0200 Subject: [PATCH 14/44] params: begin 2.54 release cycle (#8582) --- params/version.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/params/version.go b/params/version.go index e5f3a428bb1..b03f148a8a4 100644 --- a/params/version.go +++ b/params/version.go @@ -31,10 +31,10 @@ var ( // see https://calver.org const ( - VersionMajor = 2 // Major version component of the current release - VersionMinor = 53 // Minor version component of the current release - VersionMicro = 0 // Patch version component of the current release - VersionModifier = "" // Modifier component of the current release + VersionMajor = 2 // Major version component of the current release + VersionMinor = 54 // Minor version component of the current release + VersionMicro = 0 // Patch version component of the current release + VersionModifier = "dev" // Modifier component of the current release VersionKeyCreated = "ErigonVersionCreated" VersionKeyFinished = "ErigonVersionFinished" ) From 043ccef4ca2eb220c05c9c94109a8c7da7488e0f Mon Sep 17 00:00:00 2001 From: Somnath Date: Thu, 26 Oct 2023 09:56:27 +0400 Subject: [PATCH 15/44] Fix null ptr in debug_traceTx (#8585) Newly introduced `t.logGaps` was being set to `nil` and still accessed within `clearFailedLogs`. This PR changes the ordering, moving the nil setting to `CaptureTxEnd`. --- eth/tracers/native/call.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go index d12b108fd9f..9971d5517f5 100644 --- a/eth/tracers/native/call.go +++ b/eth/tracers/native/call.go @@ -145,15 +145,11 @@ func (t *callTracer) CaptureStart(env *vm.EVM, from libcommon.Address, to libcom if create { t.callstack[0].Type = vm.CREATE } - t.logIndex = 0 - t.logGaps = make(map[uint64]int) } // CaptureEnd is called after the call finishes to finalize the tracing. func (t *callTracer) CaptureEnd(output []byte, gasUsed uint64, err error) { t.callstack[0].processOutput(output, err) - t.logIndex = 0 - t.logGaps = nil } // CaptureState implements the EVMLogger interface to trace a single step of VM execution. @@ -241,8 +237,9 @@ func (t *callTracer) CaptureExit(output []byte, gasUsed uint64, err error) { } func (t *callTracer) CaptureTxStart(gasLimit uint64) { - t.gasLimit = gasLimit + t.logIndex = 0 + t.logGaps = make(map[uint64]int) } func (t *callTracer) CaptureTxEnd(restGas uint64) { @@ -252,6 +249,8 @@ func (t *callTracer) CaptureTxEnd(restGas uint64) { clearFailedLogs(&t.callstack[0], false, 0, t.logGaps) fixLogIndexGap(&t.callstack[0], t.logGaps) } + t.logIndex = 0 + t.logGaps = nil } // GetResult returns the json-encoded nested list of call traces, and any @@ -282,7 +281,7 @@ func clearFailedLogs(cf *callFrame, parentFailed bool, gap int, logGaps map[uint gap += len(cf.Logs) if gap > 0 { lastIdx := len(cf.Logs) - 1 - if lastIdx > 0 { + if lastIdx > 0 && logGaps != nil { idx := cf.Logs[lastIdx].Index logGaps[idx] = gap } From f1c81dc14eca880bb29c8a300c430b55f2359403 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Thu, 26 Oct 2023 07:58:01 +0200 Subject: [PATCH 16/44] devnet: fix node startup on macOS (#8569) * call getEnode before NodeStarted to make sure it is ready for RPC calls * fix connection error detection on macOS * use a non-default p2p port to avoid conflicts * disable bor milestones on local heimdall * generate node keys for static peers config --- cmd/devnet/args/node.go | 56 +++++++++++++------- cmd/devnet/args/node_test.go | 44 ++++++++++++++-- cmd/devnet/devnet/network.go | 99 ++++++++++++------------------------ cmd/devnet/devnet/node.go | 19 +++++++ cmd/devnet/main.go | 31 ++++++----- p2p/server.go | 13 +++++ 6 files changed, 161 insertions(+), 101 deletions(-) diff --git a/cmd/devnet/args/node.go b/cmd/devnet/args/node.go index 1c8b7497851..0ab64a9e1ed 100644 --- a/cmd/devnet/args/node.go +++ b/cmd/devnet/args/node.go @@ -1,7 +1,11 @@ package args import ( + "crypto/ecdsa" + "encoding/hex" "fmt" + "github.com/ledgerwatch/erigon/crypto" + "github.com/ledgerwatch/erigon/p2p/enode" "math/big" "net" "path/filepath" @@ -44,7 +48,11 @@ type Node struct { StaticPeers string `arg:"--staticpeers" json:"staticpeers,omitempty"` WithoutHeimdall bool `arg:"--bor.withoutheimdall" flag:"" default:"false" json:"bor.withoutheimdall,omitempty"` HeimdallGRpc string `arg:"--bor.heimdallgRPC" json:"bor.heimdallgRPC,omitempty"` + WithHeimdallMilestones bool `arg:"--bor.milestone" json:"bor.milestone"` VMDebug bool `arg:"--vmdebug" flag:"" default:"false" json:"dmdebug"` + + NodeKey *ecdsa.PrivateKey `arg:"-"` + NodeKeyHex string `arg:"--nodekeyhex" json:"nodekeyhex,omitempty"` } func (node *Node) configure(base Node, nodeNumber int) error { @@ -62,14 +70,19 @@ func (node *Node) configure(base Node, nodeNumber int) error { node.StaticPeers = base.StaticPeers + var err error + node.NodeKey, err = crypto.GenerateKey() + if err != nil { + return err + } + node.NodeKeyHex = hex.EncodeToString(crypto.FromECDSA(node.NodeKey)) + node.Metrics = base.Metrics node.MetricsPort = base.MetricsPort node.MetricsAddr = base.MetricsAddr node.Snapshots = base.Snapshots - var err error - node.PrivateApiAddr, _, err = portFromBase(base.PrivateApiAddr, nodeNumber, 1) if err != nil { @@ -86,13 +99,24 @@ func (node *Node) configure(base Node, nodeNumber int) error { node.Port = base.Port + nodeNumber + node.WithHeimdallMilestones = base.WithHeimdallMilestones + return nil } -func (node Node) ChainID() *big.Int { +func (node *Node) ChainID() *big.Int { return &big.Int{} } +func (node *Node) GetHttpPort() int { + return node.HttpPort +} + +func (node *Node) GetEnodeURL() string { + port := node.Port + return enode.NewV4(&node.NodeKey.PublicKey, net.ParseIP("127.0.0.1"), port, port).URLv4() +} + type BlockProducer struct { Node Mine bool `arg:"--mine" flag:"true"` @@ -105,11 +129,10 @@ type BlockProducer struct { account *accounts.Account } -func (m BlockProducer) Configure(baseNode Node, nodeNumber int) (int, interface{}, error) { +func (m *BlockProducer) Configure(baseNode Node, nodeNumber int) (interface{}, error) { err := m.configure(baseNode, nodeNumber) - if err != nil { - return -1, nil, err + return nil, err } switch m.Chain { @@ -131,18 +154,18 @@ func (m BlockProducer) Configure(baseNode Node, nodeNumber int) (int, interface{ m.Etherbase = m.account.Address.Hex() } - return m.HttpPort, m, nil + return m, nil } -func (n BlockProducer) Name() string { +func (n *BlockProducer) Name() string { return n.Node.Name } -func (n BlockProducer) Account() *accounts.Account { +func (n *BlockProducer) Account() *accounts.Account { return n.account } -func (n BlockProducer) IsBlockProducer() bool { +func (n *BlockProducer) IsBlockProducer() bool { return true } @@ -153,25 +176,24 @@ type NonBlockProducer struct { NoDiscover string `arg:"--nodiscover" flag:"" default:"true" json:"nodiscover"` } -func (n NonBlockProducer) Configure(baseNode Node, nodeNumber int) (int, interface{}, error) { +func (n *NonBlockProducer) Configure(baseNode Node, nodeNumber int) (interface{}, error) { err := n.configure(baseNode, nodeNumber) - if err != nil { - return -1, nil, err + return nil, err } - return n.HttpPort, n, nil + return n, nil } -func (n NonBlockProducer) Name() string { +func (n *NonBlockProducer) Name() string { return n.Node.Name } -func (n NonBlockProducer) IsBlockProducer() bool { +func (n *NonBlockProducer) IsBlockProducer() bool { return false } -func (n NonBlockProducer) Account() *accounts.Account { +func (n *NonBlockProducer) Account() *accounts.Account { return nil } diff --git a/cmd/devnet/args/node_test.go b/cmd/devnet/args/node_test.go index ddd7de4c8c9..6b940c52d39 100644 --- a/cmd/devnet/args/node_test.go +++ b/cmd/devnet/args/node_test.go @@ -162,8 +162,26 @@ func producingNodeArgs(dataDir string, nodeNumber int) []string { authrpcPortArg, _ := parameterFromArgument("--authrpc.port", "8551") natArg, _ := parameterFromArgument("--nat", "none") accountSlotsArg, _ := parameterFromArgument("--txpool.accountslots", "16") - - return []string{buildDirArg, dataDirArg, chainType, privateApiAddr, httpPortArg, authrpcPortArg, mine, httpApi, ws, natArg, devPeriod, consoleVerbosity, p2pProtocol, downloaderArg, accountSlotsArg} + withHeimdallMilestonesArg, _ := parameterFromArgument("--bor.milestone", "false") + + return []string{ + buildDirArg, + dataDirArg, + chainType, + privateApiAddr, + httpPortArg, + authrpcPortArg, + mine, + httpApi, + ws, + natArg, + devPeriod, + consoleVerbosity, + p2pProtocol, + downloaderArg, + accountSlotsArg, + withHeimdallMilestonesArg, + } } // nonMiningNodeArgs returns custom args for starting a non-mining node @@ -182,6 +200,24 @@ func nonProducingNodeArgs(dataDir string, nodeNumber int, enode string) []string authrpcPortArg, _ := parameterFromArgument("--authrpc.port", "8551") natArg, _ := parameterFromArgument("--nat", "none") ws := wsArg - - return []string{buildDirArg, dataDirArg, chainType, privateApiAddr, httpPortArg, authrpcPortArg, httpApi, ws, natArg, staticPeers, noDiscover, consoleVerbosity, torrentPort, p2pProtocol, downloaderArg} + withHeimdallMilestonesArg, _ := parameterFromArgument("--bor.milestone", "false") + + return []string{ + buildDirArg, + dataDirArg, + chainType, + privateApiAddr, + httpPortArg, + authrpcPortArg, + httpApi, + ws, + natArg, + staticPeers, + noDiscover, + consoleVerbosity, + torrentPort, + p2pProtocol, + downloaderArg, + withHeimdallMilestonesArg, + } } diff --git a/cmd/devnet/devnet/network.go b/cmd/devnet/devnet/network.go index 701b71f763d..76997bf3cb6 100644 --- a/cmd/devnet/devnet/network.go +++ b/cmd/devnet/devnet/network.go @@ -4,9 +4,9 @@ import ( "context" "errors" "fmt" + "github.com/ledgerwatch/erigon/cmd/utils" "math/big" "net" - "net/url" "os" "reflect" "strings" @@ -40,6 +40,7 @@ type Network struct { BorStateSyncDelay time.Duration BorPeriod time.Duration BorMinBlockSize int + BorWithMilestones *bool wg sync.WaitGroup peers []string namedNodes map[string]Node @@ -55,11 +56,6 @@ func (nw *Network) ChainID() *big.Int { // Start starts the process for multiple erigon nodes running on the dev chain func (nw *Network) Start(ctx context.Context) error { - - type configurable interface { - Configure(baseNode args.Node, nodeNumber int) (int, interface{}, error) - } - for _, service := range nw.Services { if err := service.Start(ctx); err != nil { nw.Stop() @@ -76,28 +72,37 @@ func (nw *Network) Start(ctx context.Context) error { Snapshots: nw.Snapshots, } + if nw.BorWithMilestones != nil { + baseNode.WithHeimdallMilestones = *nw.BorWithMilestones + } else { + baseNode.WithHeimdallMilestones = utils.WithHeimdallMilestones.Value + } + cliCtx := CliContext(ctx) metricsEnabled := cliCtx.Bool("metrics") metricsNode := cliCtx.Int("metrics.node") nw.namedNodes = map[string]Node{} - for i, node := range nw.Nodes { - if configurable, ok := node.(configurable); ok { - + for i, nodeConfig := range nw.Nodes { + { base := baseNode - if metricsEnabled && metricsNode == i { base.Metrics = true base.MetricsPort = cliCtx.Int("metrics.port") } + base.StaticPeers = strings.Join(nw.peers, ",") - nodePort, args, err := configurable.Configure(base, i) - - if err == nil { - node, err = nw.createNode(fmt.Sprintf("%s:%d", nw.BaseRPCHost, nodePort), args) + argsObj, err := nodeConfig.Configure(base, i) + if err != nil { + nw.Stop() + return err } + nodePort := nodeConfig.GetHttpPort() + nodeAddr := fmt.Sprintf("%s:%d", nw.BaseRPCHost, nodePort) + + node, err := nw.createNode(nodeAddr, argsObj) if err != nil { nw.Stop() return err @@ -105,6 +110,7 @@ func (nw *Network) Start(ctx context.Context) error { nw.Nodes[i] = node nw.namedNodes[node.Name()] = node + nw.peers = append(nw.peers, nodeConfig.GetEnodeURL()) for _, service := range nw.Services { service.NodeCreated(ctx, node) @@ -114,7 +120,6 @@ func (nw *Network) Start(ctx context.Context) error { for _, node := range nw.Nodes { err := nw.startNode(node) - if err != nil { nw.Stop() return err @@ -123,25 +128,6 @@ func (nw *Network) Start(ctx context.Context) error { for _, service := range nw.Services { service.NodeStarted(ctx, node) } - - // get the enode of the node - // - note this has the side effect of waiting for the node to start - enode, err := getEnode(node) - - if err != nil { - if errors.Is(err, devnetutils.ErrInvalidEnodeString) { - continue - } - - nw.Stop() - return err - } - - nw.peers = append(nw.peers, enode) - - // TODO do we need to call AddPeer to the nodes to make them aware of this one - // the current model only works for an appending node network where the peers gossip - // connections - not sure if this is the case ? } return nil @@ -201,28 +187,10 @@ func (nw *Network) startNode(n Node) error { node := n.(*node) args, err := args.AsArgs(node.args) - if err != nil { return err } - if len(nw.peers) > 0 { - peersIndex := -1 - - for i, arg := range args { - if strings.HasPrefix(arg, "--staticpeers") { - peersIndex = i - break - } - } - - if peersIndex >= 0 { - args[peersIndex] = args[peersIndex] + "," + strings.Join(nw.peers, ",") - } else { - args = append(args, "--staticpeers="+strings.Join(nw.peers, ",")) - } - } - go func() { nw.Logger.Info("Running node", "name", node.Name(), "args", args) @@ -254,6 +222,14 @@ func (nw *Network) startNode(n Node) error { return nil } +func isConnectionError(err error) bool { + var opErr *net.OpError + if errors.As(err, &opErr) { + return opErr.Op == "dial" + } + return false +} + // getEnode returns the enode of the netowrk node func getEnode(n Node) (string, error) { reqCount := 0 @@ -268,21 +244,10 @@ func getEnode(n Node) (string, error) { } } - if reqCount < 10 { - var urlErr *url.Error - if errors.As(err, &urlErr) { - var opErr *net.OpError - if errors.As(urlErr.Err, &opErr) { - var callErr *os.SyscallError - if errors.As(opErr.Err, &callErr) { - if strings.HasPrefix(callErr.Syscall, "connect") { - reqCount++ - time.Sleep(time.Duration(devnetutils.RandomInt(5)) * time.Second) - continue - } - } - } - } + if isConnectionError(err) && (reqCount < 10) { + reqCount++ + time.Sleep(time.Duration(devnetutils.RandomInt(5)) * time.Second) + continue } return "", err diff --git a/cmd/devnet/devnet/node.go b/cmd/devnet/devnet/node.go index b45a098f063..053f45b8d70 100644 --- a/cmd/devnet/devnet/node.go +++ b/cmd/devnet/devnet/node.go @@ -2,8 +2,10 @@ package devnet import ( "context" + "errors" "fmt" "math/big" + "net" "net/http" "sync" @@ -14,6 +16,7 @@ import ( "github.com/ledgerwatch/erigon/diagnostics" "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/node/nodecfg" + p2p_enode "github.com/ledgerwatch/erigon/p2p/enode" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/turbo/debug" enode "github.com/ledgerwatch/erigon/turbo/node" @@ -25,8 +28,11 @@ type Node interface { requests.RequestGenerator Name() string ChainID() *big.Int + GetHttpPort() int + GetEnodeURL() string Account() *accounts.Account IsBlockProducer() bool + Configure(baseNode args.Node, nodeNumber int) (interface{}, error) } type NodeSelector interface { @@ -98,6 +104,10 @@ func (n *node) done() { } } +func (n *node) Configure(args.Node, int) (interface{}, error) { + return nil, errors.New("N/A") +} + func (n *node) IsBlockProducer() bool { _, isBlockProducer := n.args.(args.BlockProducer) return isBlockProducer @@ -127,6 +137,15 @@ func (n *node) ChainID() *big.Int { return nil } +func (n *node) GetHttpPort() int { + return n.nodeCfg.HTTPPort +} + +func (n *node) GetEnodeURL() string { + port := n.nodeCfg.P2P.ListenPort() + return p2p_enode.NewV4(&n.nodeCfg.P2P.PrivateKey.PublicKey, net.ParseIP("127.0.0.1"), port, port).URLv4() +} + // run configures, creates and serves an erigon node func (n *node) run(ctx *cli.Context) error { var logger log.Logger diff --git a/cmd/devnet/main.go b/cmd/devnet/main.go index f15a396dee9..fa944d61453 100644 --- a/cmd/devnet/main.go +++ b/cmd/devnet/main.go @@ -3,6 +3,7 @@ package main import ( "context" "fmt" + "github.com/ledgerwatch/erigon/cmd/utils" "os" "os/signal" "path/filepath" @@ -332,7 +333,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { DataDir: dataDir, Chain: networkname.BorDevnetChainName, Logger: logger, - BasePort: 30303, + BasePort: 40303, BasePrivateApiAddr: "localhost:10090", BaseRPCHost: baseRpcHost, BaseRPCPort: baseRpcPort, @@ -344,7 +345,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { account_services.NewFaucet(networkname.BorDevnetChainName, faucetSource), }, Nodes: []devnet.Node{ - args.BlockProducer{ + &args.BlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", @@ -352,7 +353,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { }, AccountSlots: 200, }, - args.NonBlockProducer{ + &args.NonBlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", @@ -364,11 +365,14 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { } else { var heimdallGrpc string var services []devnet.Service + var withMilestones = utils.WithHeimdallMilestones.Value checkpointOwner := accounts.NewAccount("checkpoint-owner") if ctx.Bool(LocalHeimdallFlag.Name) { config := *params.BorDevnetChainConfig + // milestones are not supported yet on the local heimdall + withMilestones = false if sprintSize := uint64(ctx.Int(BorSprintSizeFlag.Name)); sprintSize > 0 { config.Bor.Sprint = map[string]uint64{"0": sprintSize} @@ -389,17 +393,18 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { DataDir: dataDir, Chain: networkname.BorDevnetChainName, Logger: logger, - BasePort: 30303, + BasePort: 40303, BasePrivateApiAddr: "localhost:10090", BaseRPCHost: baseRpcHost, BaseRPCPort: baseRpcPort, BorStateSyncDelay: 5 * time.Second, + BorWithMilestones: &withMilestones, Services: append(services, account_services.NewFaucet(networkname.BorDevnetChainName, faucetSource)), Alloc: types.GenesisAlloc{ faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, }, Nodes: []devnet.Node{ - args.BlockProducer{ + &args.BlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", @@ -407,7 +412,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { }, AccountSlots: 200, }, - args.BlockProducer{ + &args.BlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", @@ -415,7 +420,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { }, AccountSlots: 200, }, - /*args.BlockProducer{ + /*&args.BlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", @@ -423,7 +428,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { }, AccountSlots: 200, },*/ - args.NonBlockProducer{ + &args.NonBlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", @@ -439,14 +444,14 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { BasePort: 30403, BasePrivateApiAddr: "localhost:10190", BaseRPCHost: baseRpcHost, - BaseRPCPort: baseRpcPort, + BaseRPCPort: baseRpcPort + 1000, Services: append(services, account_services.NewFaucet(networkname.DevChainName, faucetSource)), Alloc: types.GenesisAlloc{ faucetSource.Address: {Balance: accounts.EtherAmount(200_000)}, checkpointOwner.Address: {Balance: accounts.EtherAmount(10_000)}, }, Nodes: []devnet.Node{ - args.BlockProducer{ + &args.BlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", @@ -456,7 +461,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { DevPeriod: 5, AccountSlots: 200, }, - args.NonBlockProducer{ + &args.NonBlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "3", @@ -482,14 +487,14 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { account_services.NewFaucet(networkname.DevChainName, faucetSource), }, Nodes: []devnet.Node{ - args.BlockProducer{ + &args.BlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", }, AccountSlots: 200, }, - args.NonBlockProducer{ + &args.NonBlockProducer{ Node: args.Node{ ConsoleVerbosity: "0", DirVerbosity: "5", diff --git a/p2p/server.go b/p2p/server.go index c4d15a2060d..bba6dae4fc6 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -26,6 +26,7 @@ import ( "fmt" "net" "sort" + "strconv" "sync" "sync/atomic" "time" @@ -173,6 +174,18 @@ type Config struct { MetricsEnabled bool } +func (config *Config) ListenPort() int { + _, portStr, err := net.SplitHostPort(config.ListenAddr) + if err != nil { + return 0 + } + port, err := strconv.Atoi(portStr) + if err != nil { + return 0 + } + return port +} + // Server manages all peer connections. type Server struct { // Config fields may not be modified while the server is running. From f36d090f3987d1ea59b9a3c9fb2e3509e533362f Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Fri, 27 Oct 2023 11:01:11 +0700 Subject: [PATCH 17/44] make db-tools: suspend enum-int linter error (#8598) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ``` error: conflicting types for ‘mdbx_get_datacmp’ due to enum/integer mismatch; have ‘int (*(unsigned int))(const MDBX_val *, const MDBX_val *)’ {aka ‘int (*(unsigned int))(const struct iovec *, const struct iovec *)’} [-Werror=enum-int-mismatch] 26609 | __cold MDBX_cmp_func *mdbx_get_datacmp(unsigned flags) { | ^~~~~~~~~~~~~~~~ mdbx.h:4932:1: note: previous declaration of ‘mdbx_get_datacmp’ with type ‘int (*(MDBX_db_flags_t))(const MDBX_val *, const MDBX_val *)’ {aka ‘int (*(MDBX_db_flags_t))(const struct iovec *, const struct iovec *)’} ``` can't upgrade mdbx version for now --- Makefile | 3 +-- erigon-lib/go.mod | 4 ++-- erigon-lib/go.sum | 8 ++++---- go.mod | 2 +- go.sum | 4 ++-- 5 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index f54524ea22d..54270f7870f 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,7 @@ CGO_CFLAGS += -DMDBX_FORCE_ASSERTIONS=0 # Enable MDBX's asserts by default in 'd #CGO_CFLAGS += -DMDBX_ENV_CHECKPID=0 # Erigon doesn't do fork() syscall CGO_CFLAGS += -O CGO_CFLAGS += -D__BLST_PORTABLE__ -CGO_CFLAGS += -Wno-unknown-warning-option -Wno-enum-int-mismatch -Wno-strict-prototypes -#CGO_CFLAGS += -Wno-error=strict-prototypes # for Clang15, remove it when can https://github.com/ledgerwatch/erigon/issues/6113#issuecomment-1359526277 +CGO_CFLAGS += -Wno-unknown-warning-option -Wno-enum-int-mismatch -Wno-strict-prototypes -Wno-unused-but-set-variable # about netgo see: https://github.com/golang/go/issues/30310#issuecomment-471669125 and https://github.com/golang/go/issues/57757 BUILD_TAGS = nosqlite,noboltdb diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index cc153363bd0..c3558dbb1c9 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon-lib go 1.20 require ( - github.com/erigontech/mdbx-go v0.27.19 + github.com/erigontech/mdbx-go v0.27.20 github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3 github.com/ledgerwatch/interfaces v0.0.0-20231011121315-f58b806039f0 github.com/ledgerwatch/log/v3 v3.9.0 @@ -31,7 +31,7 @@ require ( github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 github.com/hashicorp/golang-lru/v2 v2.0.6 github.com/holiman/uint256 v1.2.3 - github.com/matryer/moq v0.3.2 + github.com/matryer/moq v0.3.3 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pelletier/go-toml/v2 v2.1.0 github.com/prometheus/client_golang v1.12.2 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 2da37fe6b1b..e93c0f75044 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -202,8 +202,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erigontech/mdbx-go v0.27.19 h1:3jugN7wNmVZ4zDk4heLMPAGuOXuCG/0/DfzjlGB48kk= -github.com/erigontech/mdbx-go v0.27.19/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= +github.com/erigontech/mdbx-go v0.27.20 h1:b6nhop/nEtXLR0s8Vu1NvoQeiI6GNRoPVA5YbUPUGU0= +github.com/erigontech/mdbx-go v0.27.20/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -371,8 +371,8 @@ github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf github.com/ledgerwatch/secp256k1 v1.0.0/go.mod h1:SPmqJFciiF/Q0mPt2jVs2dTr/1TZBTIA+kPMmKgBAak= github.com/ledgerwatch/victoria-metrics v0.0.4 h1:S9QWU1giEHi4MgZWGRllDlqPKWIm5oZAiDcIITDOM0w= github.com/ledgerwatch/victoria-metrics v0.0.4/go.mod h1:sQqXMfpfwYTLQVw/FsaKAwnOp6UhVkmaYSpl9gZ/K6w= -github.com/matryer/moq v0.3.2 h1:z7oltmpTxiQ9nKNg0Jc7z45TM+eO7OhCVohxRxwaudM= -github.com/matryer/moq v0.3.2/go.mod h1:RJ75ZZZD71hejp39j4crZLsEDszGk6iH4v4YsWFKH4s= +github.com/matryer/moq v0.3.3 h1:pScMH9VyrdT4S93yiLpVyU8rCDqGQr24uOyBxmktG5Q= +github.com/matryer/moq v0.3.3/go.mod h1:RJ75ZZZD71hejp39j4crZLsEDszGk6iH4v4YsWFKH4s= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= diff --git a/go.mod b/go.mod index 49c8069d38c..a16b18a67df 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon go 1.20 require ( - github.com/erigontech/mdbx-go v0.27.19 + github.com/erigontech/mdbx-go v0.28.1-0.20231027032558-7bc6afaf5e01 github.com/ledgerwatch/erigon-lib v1.0.0 github.com/ledgerwatch/log/v3 v3.9.0 github.com/ledgerwatch/secp256k1 v1.0.0 diff --git a/go.sum b/go.sum index ea818d7441a..9bf0275eff4 100644 --- a/go.sum +++ b/go.sum @@ -284,8 +284,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erigontech/mdbx-go v0.27.19 h1:3jugN7wNmVZ4zDk4heLMPAGuOXuCG/0/DfzjlGB48kk= -github.com/erigontech/mdbx-go v0.27.19/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= +github.com/erigontech/mdbx-go v0.28.1-0.20231027032558-7bc6afaf5e01 h1:KkUQQYMIL2DdpCUIjKVi2dvwUEuo/1oKp9D2BVUIIOY= +github.com/erigontech/mdbx-go v0.28.1-0.20231027032558-7bc6afaf5e01/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c h1:CndMRAH4JIwxbW8KYq6Q+cGWcGHz0FjGR3QqcInWcW0= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= From 9adf31b8ebc3a014f2b5e13de664aa3cc238487f Mon Sep 17 00:00:00 2001 From: Dmytro Date: Fri, 27 Oct 2023 22:30:28 +0300 Subject: [PATCH 18/44] bytes transfet separated by capability and category (#8568) Co-authored-by: Mark Holt --- cl/sentinel/service/service.go | 63 ++++++++---- cmd/sentry/sentry/sentry_grpc_server.go | 26 +++-- diagnostics/peers.go | 97 ++++++++++-------- erigon-lib/diagnostics/entities.go | 8 +- erigon-lib/diagnostics/network.go | 23 +++++ erigon-lib/diagnostics/provider.go | 129 ++++++++++++++++++++++++ erigon-lib/diagnostics/provider_test.go | 87 ++++++++++++++++ eth/backend.go | 10 +- p2p/peer.go | 97 ++++++++++++++++-- p2p/server.go | 16 +++ 10 files changed, 476 insertions(+), 80 deletions(-) create mode 100644 erigon-lib/diagnostics/network.go create mode 100644 erigon-lib/diagnostics/provider.go create mode 100644 erigon-lib/diagnostics/provider_test.go diff --git a/cl/sentinel/service/service.go b/cl/sentinel/service/service.go index c3c31fa4076..41b93354962 100644 --- a/cl/sentinel/service/service.go +++ b/cl/sentinel/service/service.go @@ -79,16 +79,7 @@ func (s *SentinelServer) PublishGossip(_ context.Context, msg *sentinelrpc.Gossi // Snappify payload before sending it to gossip compressedData := utils.CompressSnappy(msg.Data) - _, found := s.peerStatistics[msg.GetPeer().Pid] - - if found { - s.peerStatistics[msg.GetPeer().Pid].BytesOut += uint64(len(compressedData)) - } else { - s.peerStatistics[msg.GetPeer().Pid] = &diagnostics.PeerStatistics{ - BytesIn: 0, - BytesOut: uint64(len(compressedData)), - } - } + s.trackPeerStatistics(msg.GetPeer().Pid, false, msg.Type.String(), "unknown", len(compressedData)) var subscription *sentinel.GossipSubscription @@ -326,16 +317,8 @@ func (s *SentinelServer) handleGossipPacket(pkt *pubsub.Message) error { return err } - _, found := s.peerStatistics[string(textPid)] - - if found { - s.peerStatistics[string(textPid)].BytesIn += uint64(len(data)) - } else { - s.peerStatistics[string(textPid)] = &diagnostics.PeerStatistics{ - BytesIn: uint64(len(data)), - BytesOut: 0, - } - } + msgType, msgCap := parseTopic(pkt.GetTopic()) + s.trackPeerStatistics(string(textPid), true, msgType, msgCap, len(data)) // Check to which gossip it belongs to. if strings.Contains(*pkt.Topic, string(sentinel.BeaconBlockTopic)) { @@ -366,3 +349,43 @@ func (s *SentinelServer) GetPeersStatistics() map[string]*diagnostics.PeerStatis return stats } + +func (s *SentinelServer) trackPeerStatistics(peerID string, inbound bool, msgType string, msgCap string, bytes int) { + if s.peerStatistics == nil { + s.peerStatistics = make(map[string]*diagnostics.PeerStatistics) + } + + if _, exists := s.peerStatistics[peerID]; !exists { + s.peerStatistics[peerID] = &diagnostics.PeerStatistics{ + CapBytesIn: make(map[string]uint64), + CapBytesOut: make(map[string]uint64), + TypeBytesIn: make(map[string]uint64), + TypeBytesOut: make(map[string]uint64), + } + } + + stats := s.peerStatistics[peerID] + + if inbound { + stats.BytesIn += uint64(bytes) + stats.CapBytesIn[msgCap] += uint64(bytes) + stats.TypeBytesIn[msgType] += uint64(bytes) + } else { + stats.BytesOut += uint64(bytes) + stats.CapBytesOut[msgCap] += uint64(bytes) + stats.TypeBytesOut[msgType] += uint64(bytes) + } +} + +func parseTopic(input string) (string, string) { + parts := strings.Split(input, "/") + + if len(parts) < 4 { + return "unknown", "unknown" + } + + capability := parts[1] + topick := parts[3] + + return capability, topick +} diff --git a/cmd/sentry/sentry/sentry_grpc_server.go b/cmd/sentry/sentry/sentry_grpc_server.go index 7f535909489..2440838965a 100644 --- a/cmd/sentry/sentry/sentry_grpc_server.go +++ b/cmd/sentry/sentry/sentry_grpc_server.go @@ -27,6 +27,7 @@ import ( libcommon "github.com/ledgerwatch/erigon-lib/common" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/common/dir" + "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon-lib/direct" "github.com/ledgerwatch/erigon-lib/gointerfaces" "github.com/ledgerwatch/erigon-lib/gointerfaces/grpcutil" @@ -345,13 +346,14 @@ func handShake( func runPeer( ctx context.Context, peerID [64]byte, - protocol uint, + cap p2p.Cap, rw p2p.MsgReadWriter, peerInfo *PeerInfo, send func(msgId proto_sentry.MessageId, peerID [64]byte, b []byte), hasSubscribers func(msgId proto_sentry.MessageId) bool, logger log.Logger, ) *p2p.PeerError { + protocol := cap.Version printTime := time.Now().Add(time.Minute) peerPrinted := false defer func() { @@ -384,8 +386,6 @@ func runPeer( return p2p.NewPeerError(p2p.PeerErrorMessageReceive, p2p.DiscNetworkError, err, "sentry.runPeer: ReadMsg error") } - peerInfo.peer.BytesTransfered += int(msg.Size) - if msg.Size > eth.ProtocolMaxMsgSize { msg.Discard() return p2p.NewPeerError(p2p.PeerErrorMessageSizeLimit, p2p.DiscSubprotocolError, nil, fmt.Sprintf("sentry.runPeer: message is too large %d, limit %d", msg.Size, eth.ProtocolMaxMsgSize)) @@ -536,6 +536,11 @@ func runPeer( default: logger.Error(fmt.Sprintf("[p2p] Unknown message code: %d, peerID=%x", msg.Code, peerID)) } + + msgType := eth.ToProto[protocol][msg.Code] + msgCap := cap.String() + peerInfo.peer.CountBytesTransfered(msgType.String(), msgCap, uint64(msg.Size), true) + msg.Discard() peerInfo.ClearDeadlines(time.Now(), givePermit) } @@ -631,10 +636,12 @@ func NewGrpcServer(ctx context.Context, dialCandidates func() enode.Iterator, re return p2p.NewPeerError(p2p.PeerErrorFirstMessageSend, p2p.DiscNetworkError, getBlockHeadersErr, "p2p.Protocol.Run getBlockHeaders failure") } + cap := p2p.Cap{Name: eth.ProtocolName, Version: protocol} + err = runPeer( ctx, peerID, - protocol, + cap, rw, peerInfo, ss.send, @@ -733,6 +740,11 @@ func (ss *GrpcServer) removePeer(peerID [64]byte, reason *p2p.PeerError) { func (ss *GrpcServer) writePeer(logPrefix string, peerInfo *PeerInfo, msgcode uint64, data []byte, ttl time.Duration) { peerInfo.Async(func() { + + cap := p2p.Cap{Name: eth.ProtocolName, Version: peerInfo.protocol} + msgType := eth.ToProto[cap.Version][msgcode] + peerInfo.peer.CountBytesTransfered(msgType.String(), cap.String(), uint64(len(data)), false) + err := peerInfo.rw.WriteMsg(p2p.Msg{Code: msgcode, Size: uint32(len(data)), Payload: bytes.NewReader(data)}) if err != nil { peerInfo.Remove(p2p.NewPeerError(p2p.PeerErrorMessageSend, p2p.DiscNetworkError, err, fmt.Sprintf("%s writePeer msgcode=%d", logPrefix, msgcode))) @@ -1041,12 +1053,12 @@ func (ss *GrpcServer) Peers(_ context.Context, _ *emptypb.Empty) (*proto_sentry. return &reply, nil } -func (ss *GrpcServer) DiagnosticsPeersData() []*p2p.PeerInfo { +func (ss *GrpcServer) DiagnosticsPeersData() map[string]*diagnostics.PeerStatistics { if ss.P2pServer == nil { - return []*p2p.PeerInfo{} + return map[string]*diagnostics.PeerStatistics{} } - peers := ss.P2pServer.PeersInfo() + peers := ss.P2pServer.DiagnosticsPeersInfo() return peers } diff --git a/diagnostics/peers.go b/diagnostics/peers.go index 4d1a4b76847..260c60b3456 100644 --- a/diagnostics/peers.go +++ b/diagnostics/peers.go @@ -10,11 +10,17 @@ import ( ) type PeerNetworkInfo struct { - LocalAddress string `json:"localAddress"` // Local endpoint of the TCP data connection - RemoteAddress string `json:"remoteAddress"` // Remote endpoint of the TCP data connection - Inbound bool `json:"inbound"` - Trusted bool `json:"trusted"` - Static bool `json:"static"` + LocalAddress string `json:"localAddress"` // Local endpoint of the TCP data connection + RemoteAddress string `json:"remoteAddress"` // Remote endpoint of the TCP data connection + Inbound bool `json:"inbound"` + Trusted bool `json:"trusted"` + Static bool `json:"static"` + BytesIn uint64 `json:"bytesIn"` + BytesOut uint64 `json:"bytesOut"` + CapBytesIn map[string]uint64 `json:"capBytesIn"` + CapBytesOut map[string]uint64 `json:"capBytesOut"` + TypeBytesIn map[string]uint64 `json:"typeBytesIn"` + TypeBytesOut map[string]uint64 `json:"typeBytesOut"` } type PeerResponse struct { @@ -28,8 +34,6 @@ type PeerResponse struct { Caps []string `json:"caps"` // Protocols advertised by this peer Network PeerNetworkInfo `json:"network"` Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields - BytesIn int `json:"bytesIn"` // Number of bytes received from the peer - BytesOut int `json:"bytesOut"` // Number of bytes sent to the peer } func SetupPeersAccess(ctx *cli.Context, metricsMux *http.ServeMux, node *node.ErigonNode) { @@ -66,20 +70,24 @@ func sentinelPeers(node *node.ErigonNode) ([]*PeerResponse, error) { for key, value := range statisticsArray { peer := PeerResponse{ - ENR: "", //TODO: find a way how to get missing data - Enode: "", - ID: key, - Name: "", - BytesIn: int(value.BytesIn), - BytesOut: int(value.BytesOut), - Type: "Sentinel", - Caps: []string{}, + ENR: "", //TODO: find a way how to get missing data + Enode: "", + ID: key, + Name: "", + Type: "Sentinel", + Caps: []string{}, Network: PeerNetworkInfo{ LocalAddress: "", RemoteAddress: "", Inbound: false, Trusted: false, Static: false, + BytesIn: value.BytesIn, + BytesOut: value.BytesOut, + CapBytesIn: value.CapBytesIn, + CapBytesOut: value.CapBytesOut, + TypeBytesIn: value.TypeBytesIn, + TypeBytesOut: value.TypeBytesOut, }, Protocols: nil, } @@ -95,35 +103,30 @@ func sentinelPeers(node *node.ErigonNode) ([]*PeerResponse, error) { func sentryPeers(node *node.ErigonNode) ([]*PeerResponse, error) { - reply := node.Backend().DiagnosticsPeersData() + statisticsArray := node.Backend().DiagnosticsPeersData() - peers := make([]*PeerResponse, 0, len(reply)) - - for _, rpcPeer := range reply { - var bin = 0 - var bout = 0 - - if rpcPeer.Network.Inbound { - bin = rpcPeer.BytesTransfered - } else { - bout = rpcPeer.BytesTransfered - } + peers := make([]*PeerResponse, 0, len(statisticsArray)) + for key, value := range statisticsArray { peer := PeerResponse{ - ENR: rpcPeer.ENR, - Enode: rpcPeer.Enode, - ID: rpcPeer.ID, - Name: rpcPeer.Name, - BytesIn: bin, - BytesOut: bout, - Type: "Sentry", - Caps: rpcPeer.Caps, + ENR: "", //TODO: find a way how to get missing data + Enode: "", + ID: key, + Name: "", + Type: "Sentry", + Caps: []string{}, Network: PeerNetworkInfo{ - LocalAddress: rpcPeer.Network.LocalAddress, - RemoteAddress: rpcPeer.Network.RemoteAddress, - Inbound: rpcPeer.Network.Inbound, - Trusted: rpcPeer.Network.Trusted, - Static: rpcPeer.Network.Static, + LocalAddress: "", + RemoteAddress: "", + Inbound: false, + Trusted: false, + Static: false, + BytesIn: value.BytesIn, + BytesOut: value.BytesOut, + CapBytesIn: value.CapBytesIn, + CapBytesOut: value.CapBytesOut, + TypeBytesIn: value.TypeBytesIn, + TypeBytesOut: value.TypeBytesOut, }, Protocols: nil, } @@ -131,5 +134,17 @@ func sentryPeers(node *node.ErigonNode) ([]*PeerResponse, error) { peers = append(peers, &peer) } - return peers, nil + return filterPeersWithoutBytesIn(peers), nil +} + +func filterPeersWithoutBytesIn(peers []*PeerResponse) []*PeerResponse { + filteredPeers := make([]*PeerResponse, 0, len(peers)) + + for _, peer := range peers { + if peer.Network.BytesIn > 0 { + filteredPeers = append(filteredPeers, peer) + } + } + + return filteredPeers } diff --git a/erigon-lib/diagnostics/entities.go b/erigon-lib/diagnostics/entities.go index 7e8920e873f..9b03d7813f2 100644 --- a/erigon-lib/diagnostics/entities.go +++ b/erigon-lib/diagnostics/entities.go @@ -21,6 +21,10 @@ type PeerStatisticsGetter interface { } type PeerStatistics struct { - BytesIn uint64 - BytesOut uint64 + BytesIn uint64 + BytesOut uint64 + CapBytesIn map[string]uint64 + CapBytesOut map[string]uint64 + TypeBytesIn map[string]uint64 + TypeBytesOut map[string]uint64 } diff --git a/erigon-lib/diagnostics/network.go b/erigon-lib/diagnostics/network.go new file mode 100644 index 00000000000..08bfaed8d31 --- /dev/null +++ b/erigon-lib/diagnostics/network.go @@ -0,0 +1,23 @@ +/* + Copyright 2021 Erigon contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +package diagnostics + +import "reflect" + +func (p PeerStatistics) Type() Type { + return Type(reflect.TypeOf(p)) +} diff --git a/erigon-lib/diagnostics/provider.go b/erigon-lib/diagnostics/provider.go new file mode 100644 index 00000000000..2d80e13f473 --- /dev/null +++ b/erigon-lib/diagnostics/provider.go @@ -0,0 +1,129 @@ +package diagnostics + +import ( + "context" + "fmt" + "reflect" + "sync" + + "github.com/ledgerwatch/erigon-lib/common/dbg" + "github.com/ledgerwatch/log/v3" +) + +type ctxKey int + +const ( + ckChan ctxKey = iota +) + +type Type reflect.Type + +type Info interface { + Type() Type +} + +func TypeOf(i Info) Type { + t := reflect.TypeOf(i) + return Type(t) +} + +type Provider interface { + StartDiagnostics(ctx context.Context) error +} + +type ProviderFunc func(ctx context.Context) error + +func (f ProviderFunc) StartDiagnostics(ctx context.Context) error { + return f(ctx) +} + +type registry struct { + context context.Context + providers []Provider +} + +var providers = map[Type]*registry{} +var providerMutex sync.RWMutex + +func RegisterProvider(provider Provider, infoType Type, logger log.Logger) { + providerMutex.Lock() + defer providerMutex.Unlock() + + reg, _ := providers[infoType] + + if reg != nil { + for _, p := range reg.providers { + if p == provider { + return + } + } + } else { + reg = ®istry{} + providers[infoType] = reg + } + + reg.providers = append(reg.providers, provider) + + if reg.context != nil { + go startProvider(reg.context, infoType, provider, logger) + } +} + +func StartProviders(ctx context.Context, infoType Type, logger log.Logger) { + providerMutex.Lock() + + reg, _ := providers[infoType] + + toStart := make([]Provider, len(reg.providers)) + + for i, provider := range reg.providers { + toStart[i] = provider + } + + reg.context = ctx + + providerMutex.Unlock() + + for _, provider := range toStart { + go startProvider(ctx, infoType, provider, logger) + } +} + +func startProvider(ctx context.Context, infoType Type, provider Provider, logger log.Logger) { + defer func() { + if rec := recover(); rec != nil { + err := fmt.Errorf("%+v, trace: %s", rec, dbg.Stack()) + logger.Warn("Diagnostic provider failed", "type", infoType, "err", err) + } + }() + + if err := provider.StartDiagnostics(ctx); err != nil { + logger.Warn("Diagnostic provider failed", "type", infoType, "err", err) + } +} + +func Send[I Info](ctx context.Context, info I) error { + if ctx.Err() != nil { + return ctx.Err() + } + + cval := ctx.Value(ckChan) + if c, ok := cval.(chan I); ok { + c <- info + } else { + return fmt.Errorf("unexpected channel type: %T", cval) + } + + return nil +} + +func Context[I Info](ctx context.Context, buffer int) (context.Context, <-chan I, context.CancelFunc) { + ch := make(chan I, buffer) + ctx = context.WithValue(ctx, ckChan, ch) + ctx, cancel := context.WithCancel(ctx) + + return ctx, ch, func() { + close(ch) + cancel() + } +} diff --git a/erigon-lib/diagnostics/provider_test.go b/erigon-lib/diagnostics/provider_test.go new file mode 100644 index 00000000000..7d8ea6b10ec --- /dev/null +++ b/erigon-lib/diagnostics/provider_test.go @@ -0,0 +1,87 @@ +package diagnostics_test + +import ( + "context" + "testing" + "time" + + "github.com/ledgerwatch/erigon-lib/diagnostics" + "github.com/ledgerwatch/log/v3" +) + +type testInfo struct { + count int +} + +func (ti testInfo) Type() diagnostics.Type { + return diagnostics.TypeOf(ti) +} + +type testProvider struct { +} + +func (t *testProvider) StartDiagnostics(ctx context.Context) error { + timer := time.NewTicker(1 * time.Second) + defer timer.Stop() + + var count int + + for { + select { + case <-ctx.Done(): + return nil + case <-timer.C: + diagnostics.Send(ctx, testInfo{count}) + count++ + } + } +} + +func TestProviderRegistration(t *testing.T) { + + // diagnostics provider + provider := &testProvider{} + diagnostics.RegisterProvider(provider, diagnostics.TypeOf(testInfo{}), log.Root()) + + // diagnostics receiver + ctx, ch, cancel := diagnostics.Context[testInfo](context.Background(), 1) + diagnostics.StartProviders(ctx, diagnostics.TypeOf(testInfo{}), log.Root()) + + for info := range ch { + if info.count == 3 { + cancel() + } + } +} + +func TestProviderFuncRegistration(t *testing.T) { + + // diagnostics provider + diagnostics.RegisterProvider(diagnostics.ProviderFunc(func(ctx context.Context) error { + timer := time.NewTicker(1 * time.Second) + defer timer.Stop() + + var count int + + for { + select { + case <-ctx.Done(): + return nil + case <-timer.C: + diagnostics.Send(ctx, testInfo{count}) + count++ + } + } + }), diagnostics.TypeOf(testInfo{}), log.Root()) + + // diagnostics receiver + ctx, ch, cancel := diagnostics.Context[testInfo](context.Background(), 1) + + diagnostics.StartProviders(ctx, diagnostics.TypeOf(testInfo{}), log.Root()) + + for info := range ch { + if info.count == 3 { + cancel() + } + } +} diff --git a/eth/backend.go b/eth/backend.go index eb6deac2c3f..6c271596dd3 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -32,6 +32,7 @@ import ( "time" "github.com/ledgerwatch/erigon-lib/chain/networkname" + "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon-lib/downloader/downloadergrpc" "github.com/ledgerwatch/erigon-lib/kv/kvcfg" "github.com/ledgerwatch/erigon/cl/beacon" @@ -1205,11 +1206,14 @@ func (s *Ethereum) Peers(ctx context.Context) (*remote.PeersReply, error) { return &reply, nil } -func (s *Ethereum) DiagnosticsPeersData() []*p2p.PeerInfo { - var reply []*p2p.PeerInfo +func (s *Ethereum) DiagnosticsPeersData() map[string]*diagnostics.PeerStatistics { + var reply map[string]*diagnostics.PeerStatistics = make(map[string]*diagnostics.PeerStatistics) for _, sentryServer := range s.sentryServers { peers := sentryServer.DiagnosticsPeersData() - reply = append(reply, peers...) + + for key, value := range peers { + reply[key] = value + } } return reply diff --git a/p2p/peer.go b/p2p/peer.go index e47b9510574..0adf711d765 100644 --- a/p2p/peer.go +++ b/p2p/peer.go @@ -19,15 +19,18 @@ package p2p import ( "errors" "fmt" - "github.com/ledgerwatch/erigon-lib/metrics" "io" "net" "sort" + "strings" "sync" "time" + "github.com/ledgerwatch/erigon-lib/metrics" + "github.com/ledgerwatch/log/v3" + "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/erigon/common/debug" "github.com/ledgerwatch/erigon/common/mclock" "github.com/ledgerwatch/erigon/event" @@ -123,7 +126,12 @@ type Peer struct { metricsEnabled bool //diagnostics info - BytesTransfered int + BytesIn uint64 + BytesOut uint64 + CapBytesIn map[string]uint64 + CapBytesOut map[string]uint64 + TypeBytesIn map[string]uint64 + TypeBytesOut map[string]uint64 } // NewPeer returns a peer for testing purposes. @@ -227,6 +235,12 @@ func newPeer(logger log.Logger, conn *conn, protocols []Protocol, pubkey [64]byt log: logger.New("id", conn.node.ID(), "conn", conn.flags), pubkey: pubkey, metricsEnabled: metricsEnabled, + CapBytesIn: make(map[string]uint64), + CapBytesOut: make(map[string]uint64), + TypeBytesIn: make(map[string]uint64), + TypeBytesOut: make(map[string]uint64), + BytesIn: 0, + BytesOut: 0, } return p } @@ -235,6 +249,45 @@ func (p *Peer) Log() log.Logger { return p.log } +func makeFirstCharCap(input string) string { + // Convert the entire string to lowercase + input = strings.ToLower(input) + // Use strings.Title to capitalize the first letter of each word + input = strings.ToUpper(input[:1]) + input[1:] + return input +} + +func convertToCamelCase(input string) string { + parts := strings.Split(input, "_") + if len(parts) == 1 { + return input + } + + var result string + + for _, part := range parts { + if len(part) > 0 && part != parts[len(parts)-1] { + result += makeFirstCharCap(part) + } + } + + return result +} + +func (p *Peer) CountBytesTransfered(msgType string, msgCap string, bytes uint64, inbound bool) { + messageType := convertToCamelCase(msgType) + + if inbound { + p.BytesIn += bytes + p.CapBytesIn[msgCap] += bytes + p.TypeBytesIn[messageType] += bytes + } else { + p.BytesOut += bytes + p.CapBytesOut[msgCap] += bytes + p.TypeBytesOut[messageType] += bytes + } +} + func (p *Peer) run() (peerErr *PeerError) { var ( writeStart = make(chan struct{}, 1) @@ -312,7 +365,7 @@ func (p *Peer) readLoop(errc chan<- error) { errc <- err return } - msg.ReceivedAt = time.Now() + if err = p.handle(msg); err != nil { errc <- err return @@ -346,6 +399,17 @@ func (p *Peer) handle(msg Msg) error { if err != nil { return fmt.Errorf("msg code out of range: %v", msg.Code) } + //msgType := "unknown" + + //var dds uint64 = msg.Code + + //dds -= proto.offset + //msgCode := msg.Code - proto.offset + //msgType = eth.ToProto[proto.cap().Version][dds].String() + //msgType := eth.ToProto[proto.cap().Version][msgCode].String() + + //p.CountBytesTransfered(msgType, proto.cap().String(), uint64(msg.Size), true) + if p.metricsEnabled { m := fmt.Sprintf("%s_%s_%d_%#02x", ingressMeterName, proto.Name, proto.Version, msg.Code-proto.offset) metrics.GetOrCreateCounter(m).Set(uint64(msg.meterSize)) @@ -448,9 +512,9 @@ func (rw *protoRW) WriteMsg(msg Msg) (err error) { if msg.Code >= rw.Length { return NewPeerError(PeerErrorInvalidMessageCode, DiscProtocolError, nil, fmt.Sprintf("not handled code=%d", msg.Code)) } + msg.meterCap = rw.cap() msg.meterCode = msg.Code - msg.Code += rw.offset select { @@ -468,6 +532,7 @@ func (rw *protoRW) WriteMsg(msg Msg) (err error) { } func (rw *protoRW) ReadMsg() (Msg, error) { + select { case msg := <-rw.in: msg.Code -= rw.offset @@ -493,8 +558,7 @@ type PeerInfo struct { Trusted bool `json:"trusted"` Static bool `json:"static"` } `json:"network"` - Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields - BytesTransfered int `json:"bytesTransfered,omitempty"` + Protocols map[string]interface{} `json:"protocols"` // Sub-protocol specific metadata fields } // Info gathers and returns a collection of metadata known about a peer. @@ -520,7 +584,6 @@ func (p *Peer) Info() *PeerInfo { info.Network.Inbound = p.rw.is(inboundConn) info.Network.Trusted = p.rw.is(trustedConn) info.Network.Static = p.rw.is(staticDialedConn) - info.BytesTransfered = p.BytesTransfered // Gather all the running protocol infos for _, proto := range p.running { @@ -536,3 +599,23 @@ func (p *Peer) Info() *PeerInfo { } return info } + +func (p *Peer) DiagInfo() *diagnostics.PeerStatistics { + return &diagnostics.PeerStatistics{ + BytesIn: p.BytesIn, + BytesOut: p.BytesOut, + CapBytesIn: p.CapBytesIn, + CapBytesOut: p.CapBytesOut, + TypeBytesIn: p.TypeBytesIn, + TypeBytesOut: p.TypeBytesOut, + } +} + +func (p *Peer) ResetDiagnosticsCounters() { + p.BytesIn = 0 + p.BytesOut = 0 + p.CapBytesIn = make(map[string]uint64) + p.CapBytesOut = make(map[string]uint64) + p.TypeBytesIn = make(map[string]uint64) + p.TypeBytesOut = make(map[string]uint64) +} diff --git a/p2p/server.go b/p2p/server.go index bba6dae4fc6..b9b3ed456a5 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -33,6 +33,7 @@ import ( "golang.org/x/sync/semaphore" + "github.com/ledgerwatch/erigon-lib/diagnostics" "github.com/ledgerwatch/log/v3" "github.com/ledgerwatch/erigon/common" @@ -1180,6 +1181,7 @@ func (srv *Server) PeersInfo() []*PeerInfo { for _, peer := range srv.Peers() { if peer != nil { infos = append(infos, peer.Info()) + peer.ResetDiagnosticsCounters() } } // Sort the result array alphabetically by node identifier @@ -1192,3 +1194,17 @@ func (srv *Server) PeersInfo() []*PeerInfo { } return infos } + +// PeersInfo returns an array of metadata objects describing connected peers. +func (srv *Server) DiagnosticsPeersInfo() map[string]*diagnostics.PeerStatistics { + // Gather all the generic and sub-protocol specific infos + infos := make(map[string]*diagnostics.PeerStatistics) + for _, peer := range srv.Peers() { + if peer != nil { + infos[peer.ID().String()] = peer.DiagInfo() + peer.ResetDiagnosticsCounters() + } + } + + return infos +} From 0e5af0a69c9d852d257f5e65f539b48fd4cc6448 Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Sat, 28 Oct 2023 17:41:50 +0200 Subject: [PATCH 19/44] Added beacon snapshots download (#8601) --- cmd/capcli/cli.go | 78 +++++++++++++++++++++++++++-- erigon-lib/downloader/downloader.go | 2 +- erigon-lib/downloader/webseed.go | 1 - erigon-lib/go.mod | 2 +- erigon-lib/go.sum | 4 +- eth/stagedsync/stage_snapshots.go | 2 +- go.mod | 4 +- go.sum | 4 +- turbo/snapshotsync/snapshotsync.go | 18 ++++++- 9 files changed, 101 insertions(+), 14 deletions(-) diff --git a/cmd/capcli/cli.go b/cmd/capcli/cli.go index e593e4f4de9..4a0012e132d 100644 --- a/cmd/capcli/cli.go +++ b/cmd/capcli/cli.go @@ -7,7 +7,15 @@ import ( "strings" "time" + lg "github.com/anacrolix/log" + "github.com/ledgerwatch/erigon-lib/direct" + downloader3 "github.com/ledgerwatch/erigon-lib/downloader" + state2 "github.com/ledgerwatch/erigon-lib/state" + + "github.com/c2h5oh/datasize" + "github.com/ledgerwatch/erigon-lib/chain/snapcfg" libcommon "github.com/ledgerwatch/erigon-lib/common" + "github.com/ledgerwatch/erigon-lib/downloader" "github.com/ledgerwatch/erigon/cl/abstract" "github.com/ledgerwatch/erigon/cl/clparams" @@ -15,9 +23,12 @@ import ( persistence2 "github.com/ledgerwatch/erigon/cl/persistence" "github.com/ledgerwatch/erigon/cmd/caplin/caplin1" "github.com/ledgerwatch/erigon/eth/ethconfig" + "github.com/ledgerwatch/erigon/params" + "github.com/ledgerwatch/erigon/turbo/snapshotsync" "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" "github.com/ledgerwatch/erigon-lib/common/datadir" + "github.com/ledgerwatch/erigon-lib/downloader/downloadercfg" "github.com/ledgerwatch/erigon-lib/downloader/snaptype" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/mdbx" @@ -49,9 +60,10 @@ var CLI struct { Blocks Blocks `cmd:"" help:"download blocks from reqresp network"` Epochs Epochs `cmd:"" help:"download epochs from reqresp network"` - Chain Chain `cmd:"" help:"download the entire chain from reqresp network"` - DumpSnapshots DumpSnapshots `cmd:"" help:"generate caplin snapshots"` - CheckSnapshots CheckSnapshots `cmd:"" help:"check snapshot folder against content of chain data"` + Chain Chain `cmd:"" help:"download the entire chain from reqresp network"` + DumpSnapshots DumpSnapshots `cmd:"" help:"generate caplin snapshots"` + CheckSnapshots CheckSnapshots `cmd:"" help:"check snapshot folder against content of chain data"` + DownloadSnapshots DownloadSnapshots `cmd:"" help:"download snapshots from webseed"` } type chainCfg struct { @@ -514,3 +526,63 @@ func (c *CheckSnapshots) Run(ctx *Context) error { } return nil } + +type DownloadSnapshots struct { + chainCfg + outputFolder +} + +func (d *DownloadSnapshots) Run(ctx *Context) error { + webSeeds := snapcfg.KnownWebseeds[d.Chain] + dirs := datadir.New(d.Datadir) + + _, _, beaconConfig, _, err := clparams.GetConfigsByNetworkName(d.Chain) + if err != nil { + return err + } + + rawDB := persistence.AferoRawBeaconBlockChainFromOsPath(beaconConfig, dirs.CaplinHistory) + + log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StderrHandler)) + + _, db, err := caplin1.OpenCaplinDatabase(ctx, db_config.DatabaseConfiguration{PruneDepth: math.MaxUint64}, beaconConfig, rawDB, dirs.CaplinIndexing, nil, false) + if err != nil { + return err + } + tx, err := db.BeginRw(ctx) + if err != nil { + return err + } + defer tx.Rollback() + downloadRate, err := datasize.ParseString("16mb") + if err != nil { + return err + } + + uploadRate, err := datasize.ParseString("0mb") + if err != nil { + return err + } + version := "erigon: " + params.VersionWithCommit(params.GitCommit) + + downloaderCfg, err := downloadercfg.New(dirs, version, lg.Info, downloadRate, uploadRate, 42069, 10, 3, nil, webSeeds, d.Chain) + if err != nil { + return err + } + downloaderCfg.DownloadTorrentFilesFromWebseed = true + downlo, err := downloader.New(ctx, downloaderCfg, dirs, log.Root(), log.LvlInfo) + if err != nil { + return err + } + s, err := state2.NewAggregatorV3(ctx, dirs.Tmp, dirs.Tmp, 200000, db, log.Root()) + if err != nil { + return err + } + downlo.MainLoopInBackground(false) + bittorrentServer, err := downloader3.NewGrpcServer(downlo) + if err != nil { + return fmt.Errorf("new server: %w", err) + } + return snapshotsync.WaitForDownloader("CapCliDownloader", ctx, false, snapshotsync.OnlyCaplin, s, tx, freezeblocks.NewBlockReader(freezeblocks.NewRoSnapshots(ethconfig.NewSnapCfg(false, false, false), dirs.Snap, log.Root()), freezeblocks.NewBorRoSnapshots(ethconfig.NewSnapCfg(false, false, false), dirs.Snap, log.Root())), nil, params.ChainConfigByChainName(d.Chain), direct.NewDownloaderClient(bittorrentServer)) + +} diff --git a/erigon-lib/downloader/downloader.go b/erigon-lib/downloader/downloader.go index df0dd76ce73..9498479ce59 100644 --- a/erigon-lib/downloader/downloader.go +++ b/erigon-lib/downloader/downloader.go @@ -102,7 +102,7 @@ func New(ctx context.Context, cfg *downloadercfg.Cfg, dirs datadir.Dirs, logger folder: m, torrentClient: torrentClient, statsLock: &sync.RWMutex{}, - webseeds: &WebSeeds{logger: logger, verbosity: verbosity, downloadTorrentFile: cfg.DownloadTorrentFilesFromWebseed, chainName: cfg.ChainName}, + webseeds: &WebSeeds{logger: logger, verbosity: verbosity, downloadTorrentFile: cfg.DownloadTorrentFilesFromWebseed}, logger: logger, verbosity: verbosity, } diff --git a/erigon-lib/downloader/webseed.go b/erigon-lib/downloader/webseed.go index e1112499f76..45947dedae7 100644 --- a/erigon-lib/downloader/webseed.go +++ b/erigon-lib/downloader/webseed.go @@ -36,7 +36,6 @@ type WebSeeds struct { torrentUrls snaptype.TorrentUrls // HTTP urls of .torrent files downloadTorrentFile bool - chainName string logger log.Logger verbosity log.Lvl } diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index c3558dbb1c9..bb94dcd6683 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon-lib go 1.20 require ( - github.com/erigontech/mdbx-go v0.27.20 + github.com/erigontech/mdbx-go v0.27.19 github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3 github.com/ledgerwatch/interfaces v0.0.0-20231011121315-f58b806039f0 github.com/ledgerwatch/log/v3 v3.9.0 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index e93c0f75044..5c684a43837 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -202,8 +202,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erigontech/mdbx-go v0.27.20 h1:b6nhop/nEtXLR0s8Vu1NvoQeiI6GNRoPVA5YbUPUGU0= -github.com/erigontech/mdbx-go v0.27.20/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= +github.com/erigontech/mdbx-go v0.27.19 h1:3jugN7wNmVZ4zDk4heLMPAGuOXuCG/0/DfzjlGB48kk= +github.com/erigontech/mdbx-go v0.27.19/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/eth/stagedsync/stage_snapshots.go b/eth/stagedsync/stage_snapshots.go index 0ea782fba3f..5332ae54c89 100644 --- a/eth/stagedsync/stage_snapshots.go +++ b/eth/stagedsync/stage_snapshots.go @@ -120,7 +120,7 @@ func DownloadAndIndexSnapshotsIfNeed(s *StageState, ctx context.Context, tx kv.R return nil } - if err := snapshotsync.WaitForDownloader(s.LogPrefix(), ctx, cfg.historyV3, cfg.agg, tx, cfg.blockReader, cfg.dbEventNotifier, &cfg.chainConfig, cfg.snapshotDownloader); err != nil { + if err := snapshotsync.WaitForDownloader(s.LogPrefix(), ctx, cfg.historyV3, snapshotsync.NoCaplin, cfg.agg, tx, cfg.blockReader, cfg.dbEventNotifier, &cfg.chainConfig, cfg.snapshotDownloader); err != nil { return err } diff --git a/go.mod b/go.mod index a16b18a67df..fa42248c023 100644 --- a/go.mod +++ b/go.mod @@ -19,6 +19,7 @@ require ( github.com/VictoriaMetrics/fastcache v1.12.1 github.com/VictoriaMetrics/metrics v1.23.1 github.com/alecthomas/kong v0.8.0 + github.com/anacrolix/log v0.14.3-0.20230823030427-4b296d71a6b4 github.com/anacrolix/sync v0.4.0 github.com/anacrolix/torrent v1.52.6-0.20230926121951-11833b45cfbe github.com/benesch/cgosymbolizer v0.0.0-20190515212042-bec6fe6e597b @@ -112,7 +113,6 @@ require ( github.com/anacrolix/envpprof v1.3.0 // indirect github.com/anacrolix/generics v0.0.0-20230816105729-c755655aee45 // indirect github.com/anacrolix/go-libutp v1.3.1 // indirect - github.com/anacrolix/log v0.14.3-0.20230823030427-4b296d71a6b4 // indirect github.com/anacrolix/missinggo v1.3.0 // indirect github.com/anacrolix/missinggo/perf v1.0.0 // indirect github.com/anacrolix/missinggo/v2 v2.7.2-0.20230527121029-a582b4f397b9 // indirect @@ -186,7 +186,7 @@ require ( github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3 // indirect + github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231027092055-45ee9d86a6cb // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect diff --git a/go.sum b/go.sum index 9bf0275eff4..2f85410ceb2 100644 --- a/go.sum +++ b/go.sum @@ -539,8 +539,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3 h1:59TKwBsS+Fn4iGh+PCxw7s73+/0WmDeK6bskDe3tFzY= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231027092055-45ee9d86a6cb h1:Y6eZ4D8rMrAdDoy2za2Lkf8qSHbNNSPGnSdl/B78G4Y= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231027092055-45ee9d86a6cb/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= github.com/ledgerwatch/log/v3 v3.9.0/go.mod h1:EiAY6upmI/6LkNhOVxb4eVsmsP11HZCnZ3PlJMjYiqE= github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= diff --git a/turbo/snapshotsync/snapshotsync.go b/turbo/snapshotsync/snapshotsync.go index 0661bf84338..c1cfd628d1c 100644 --- a/turbo/snapshotsync/snapshotsync.go +++ b/turbo/snapshotsync/snapshotsync.go @@ -24,6 +24,16 @@ import ( "github.com/ledgerwatch/log/v3" ) +type CaplinMode int + +const ( + + // CaplinModeNone - no caplin mode + NoCaplin CaplinMode = 1 + OnlyCaplin CaplinMode = 2 + AlsoCaplin CaplinMode = 3 +) + func BuildProtoRequest(downloadRequest []services.DownloadRequest) *proto_downloader.DownloadRequest { req := &proto_downloader.DownloadRequest{Items: make([]*proto_downloader.DownloadItem, 0, len(snaptype.AllSnapshotTypes))} for _, r := range downloadRequest { @@ -72,7 +82,7 @@ func RequestSnapshotsDownload(ctx context.Context, downloadRequest []services.Do // WaitForDownloader - wait for Downloader service to download all expected snapshots // for MVP we sync with Downloader only once, in future will send new snapshots also -func WaitForDownloader(logPrefix string, ctx context.Context, histV3 bool, agg *state.AggregatorV3, tx kv.RwTx, blockReader services.FullBlockReader, notifier services.DBEventNotifier, cc *chain.Config, snapshotDownloader proto_downloader.DownloaderClient) error { +func WaitForDownloader(logPrefix string, ctx context.Context, histV3 bool, caplin CaplinMode, agg *state.AggregatorV3, tx kv.RwTx, blockReader services.FullBlockReader, notifier services.DBEventNotifier, cc *chain.Config, snapshotDownloader proto_downloader.DownloaderClient) error { snapshots := blockReader.Snapshots() borSnapshots := blockReader.BorSnapshots() if blockReader.FreezingCfg().NoDownloader { @@ -131,6 +141,12 @@ func WaitForDownloader(logPrefix string, ctx context.Context, histV3 bool, agg * continue } } + if caplin == NoCaplin && strings.Contains(p.Name, "beaconblocks") { + continue + } + if caplin == OnlyCaplin && !strings.Contains(p.Name, "beaconblocks") { + continue + } _, exists := existingFilesMap[p.Name] _, borExists := borExistingFilesMap[p.Name] From 5bb91bb77c5ee666c1cb70aaf84ba3b452343b1c Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Sun, 29 Oct 2023 12:33:31 +0700 Subject: [PATCH 20/44] "erigon snapshots retire": prune, then retire, then prune (#8606) --- turbo/app/snapshots_cmd.go | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/turbo/app/snapshots_cmd.go b/turbo/app/snapshots_cmd.go index 968ece0c4fc..24d4621e4f0 100644 --- a/turbo/app/snapshots_cmd.go +++ b/turbo/app/snapshots_cmd.go @@ -401,7 +401,7 @@ func doRetireCommand(cliCtx *cli.Context) error { db := mdbx.NewMDBX(logger).Label(kv.ChainDB).Path(dirs.Chaindata).MustOpen() defer db.Close() - cfg := ethconfig.NewSnapCfg(true, true, true) + cfg := ethconfig.NewSnapCfg(true, false, true) blockSnapshots := freezeblocks.NewRoSnapshots(cfg, dirs.Snap, logger) borSnapshots := freezeblocks.NewBorRoSnapshots(cfg, dirs.Snap, logger) if err := blockSnapshots.ReopenFolder(); err != nil { @@ -435,11 +435,41 @@ func doRetireCommand(cliCtx *cli.Context) error { } logger.Info("Params", "from", from, "to", to, "every", every) + { + logEvery := time.NewTicker(10 * time.Second) + defer logEvery.Stop() + + for j := 0; j < 10_000; j++ { // prune happens by small steps, so need many runs + if err := db.Update(ctx, func(tx kv.RwTx) error { + if err := br.PruneAncientBlocks(tx, 100, false /* includeBor */); err != nil { + return err + } + + select { + case <-ctx.Done(): + return ctx.Err() + case <-logEvery.C: + firstNonGenesisHeader, err := rawdbv3.SecondKey(tx, kv.Headers) + if err != nil { + return err + } + if len(firstNonGenesisHeader) > 0 { + logger.Info("Prunning old blocks", "progress", binary.BigEndian.Uint64(firstNonGenesisHeader)) + } + default: + } + return nil + }); err != nil { + return err + } + } + } + for i := from; i < to; i += every { if err := br.RetireBlocks(ctx, i, i+every, log.LvlInfo, nil); err != nil { panic(err) } - if err := db.UpdateNosync(ctx, func(tx kv.RwTx) error { + if err := db.Update(ctx, func(tx kv.RwTx) error { if err := rawdb.WriteSnapshots(tx, blockReader.FrozenFiles(), agg.Files()); err != nil { return err } From 216f20d5f8623413ad707bb7c5233e256b873ea8 Mon Sep 17 00:00:00 2001 From: yyjia Date: Sun, 29 Oct 2023 13:33:47 +0800 Subject: [PATCH 21/44] batch flush can without read tx (#8597) --- erigon-lib/kv/membatch/mapmutation.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/erigon-lib/kv/membatch/mapmutation.go b/erigon-lib/kv/membatch/mapmutation.go index 0a38f39feff..e29ed3efa5b 100644 --- a/erigon-lib/kv/membatch/mapmutation.go +++ b/erigon-lib/kv/membatch/mapmutation.go @@ -3,6 +3,7 @@ package membatch import ( "context" "encoding/binary" + "errors" "fmt" "sync" "time" @@ -222,8 +223,8 @@ func (m *Mapmutation) doCommit(tx kv.RwTx) error { } func (m *Mapmutation) Flush(ctx context.Context, tx kv.RwTx) error { - if m.db == nil { - return nil + if tx == nil { + return errors.New("rwTx needed") } m.mu.Lock() defer m.mu.Unlock() From 60b3f1e7f08a17c560186dd99b72ec42922d2aa4 Mon Sep 17 00:00:00 2001 From: a Date: Sun, 29 Oct 2023 06:34:03 +0100 Subject: [PATCH 22/44] bind-ipc (#8590) --- cmd/rpcdaemon/README.md | 20 +++- cmd/rpcdaemon/cli/config.go | 130 +++++++++++++++----------- cmd/rpcdaemon/cli/config_test.go | 21 +++++ cmd/rpcdaemon/cli/httpcfg/http_cfg.go | 59 ++++++------ cmd/utils/flags.go | 3 +- node/endpoints.go | 10 +- 6 files changed, 156 insertions(+), 87 deletions(-) create mode 100644 cmd/rpcdaemon/cli/config_test.go diff --git a/cmd/rpcdaemon/README.md b/cmd/rpcdaemon/README.md index 1af85e2ba1f..5ee769e25a8 100644 --- a/cmd/rpcdaemon/README.md +++ b/cmd/rpcdaemon/README.md @@ -117,7 +117,7 @@ If the healthcheck is successful it will return a 200 status code. If the healthcheck fails for any reason a status 500 will be returned. This is true if one of the criteria requested fails its check. -You can set any number of values on the `X-ERIGON-HEALTHCHECK` header. Ones that are not included are skipped in the +You can set any number of values on the `X-ERIGON-HEALTHCHECK` header. Ones that are not included are skipped in the checks. Available Options: @@ -186,6 +186,24 @@ By default data pruned after 90K blocks, can change it by flags like `--prune.hi Some methods, if not found historical data in DB, can fallback to old blocks re-execution - but it requires `h`. +### The --http.url flag + +the `--http.url` flag is an optional flag which allows one to bind the HTTP server to a socket, for example, `tcp6://:8545` or `unix:///erigon_http.socket` + +If the `--http.url` flag is set, then `--http.addr` and `--http.port` with both be ignored. + +note that this is NOT geth-style IPC. for that, read the next section, IPC endpoint(geth-compatible) + +### IPC endpoint (geth compatible) + +erigon supports the geth-style unix socket IPC. you can enable this with `--socket.enabled` flag, +and setting the `--socket.url` flag. For instance, if you wanted the socket to exist at `/var/run/erigon.ipc`, +you would do `--socket.url=unix:///var/run/erigon.ipc` + +you can also use `--socket.url=tcp://:` to serve the raw jsonrpc2 protocol over tcp + +the socket will inherit the namespaces from `http.api` + ### RPC Implementation Status Label "remote" means: `--private.api.addr` flag is required. diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index 51d72638a4c..ea15834adcb 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -7,6 +7,7 @@ import ( "fmt" "net" "net/http" + "net/url" "os" "path/filepath" "strings" @@ -92,15 +93,9 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) { rootCmd.PersistentFlags().StringVar(&cfg.TLSCertfile, "tls.cert", "", "certificate for client side TLS handshake") rootCmd.PersistentFlags().StringVar(&cfg.TLSKeyFile, "tls.key", "", "key file for client side TLS handshake") rootCmd.PersistentFlags().StringVar(&cfg.TLSCACert, "tls.cacert", "", "CA certificate for client side TLS handshake") - rootCmd.PersistentFlags().IntVar(&cfg.HttpPort, "http.port", nodecfg.DefaultHTTPPort, "HTTP-RPC server listening port") - rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpCORSDomain, "http.corsdomain", []string{}, "Comma separated list of domains from which to accept cross origin requests (browser enforced)") - rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpVirtualHost, "http.vhosts", nodecfg.DefaultConfig.HTTPVirtualHosts, "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.") - rootCmd.PersistentFlags().BoolVar(&cfg.HttpCompression, "http.compression", true, "Disable http compression") - rootCmd.PersistentFlags().StringSliceVar(&cfg.API, "http.api", []string{"eth", "erigon"}, "API's offered over the HTTP-RPC interface: eth,erigon,web3,net,debug,trace,txpool,db. Supported methods: https://github.com/ledgerwatch/erigon/tree/devel/cmd/rpcdaemon") rootCmd.PersistentFlags().Uint64Var(&cfg.Gascap, "rpc.gascap", 50_000_000, "Sets a cap on gas that can be used in eth_call/estimateGas") rootCmd.PersistentFlags().Uint64Var(&cfg.MaxTraces, "trace.maxtraces", 200, "Sets a limit on traces that can be returned in trace_filter") - rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets - Same port as HTTP") - rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketCompression, "ws.compression", false, "Enable Websocket compression (RFC 7692)") + rootCmd.PersistentFlags().StringVar(&cfg.RpcAllowListFilePath, utils.RpcAccessListFlag.Name, "", "Specify granular (method-by-method) API allowlist") rootCmd.PersistentFlags().UintVar(&cfg.RpcBatchConcurrency, utils.RpcBatchConcurrencyFlag.Name, 2, utils.RpcBatchConcurrencyFlag.Usage) rootCmd.PersistentFlags().BoolVar(&cfg.RpcStreamingDisable, utils.RpcStreamingDisableFlag.Name, false, utils.RpcStreamingDisableFlag.Usage) @@ -108,6 +103,7 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) { rootCmd.PersistentFlags().BoolVar(&cfg.TraceCompatibility, "trace.compat", false, "Bug for bug compatibility with OE for trace_ routines") rootCmd.PersistentFlags().StringVar(&cfg.TxPoolApiAddr, "txpool.api.addr", "", "txpool api network address, for example: 127.0.0.1:9090 (default: use value of --private.api.addr)") rootCmd.PersistentFlags().BoolVar(&cfg.Sync.UseSnapshots, "snapshot", true, utils.SnapshotFlag.Usage) + rootCmd.PersistentFlags().StringVar(&stateCacheStr, "state.cache", "0MB", "Amount of data to store in StateCache (enabled if no --datadir set). Set 0 to disable StateCache. Defaults to 0MB RAM") rootCmd.PersistentFlags().BoolVar(&cfg.GRPCServerEnabled, "grpc", false, "Enable GRPC server") rootCmd.PersistentFlags().StringVar(&cfg.GRPCListenAddress, "grpc.addr", nodecfg.DefaultGRPCHost, "GRPC server listening interface") @@ -115,9 +111,18 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) { rootCmd.PersistentFlags().BoolVar(&cfg.GRPCHealthCheckEnabled, "grpc.healthcheck", false, "Enable GRPC health check") rootCmd.PersistentFlags().Float64Var(ðconfig.Defaults.RPCTxFeeCap, utils.RPCGlobalTxFeeCapFlag.Name, utils.RPCGlobalTxFeeCapFlag.Value, utils.RPCGlobalTxFeeCapFlag.Usage) - rootCmd.PersistentFlags().BoolVar(&cfg.TCPServerEnabled, "tcp", false, "Enable TCP server") - rootCmd.PersistentFlags().StringVar(&cfg.TCPListenAddress, "tcp.addr", nodecfg.DefaultTCPHost, "TCP server listening interface") - rootCmd.PersistentFlags().IntVar(&cfg.TCPPort, "tcp.port", nodecfg.DefaultTCPPort, "TCP server listening port") + rootCmd.PersistentFlags().BoolVar(&cfg.HttpServerEnabled, "http.enabled", true, "enable http server") + rootCmd.PersistentFlags().StringVar(&cfg.HttpURL, "http.url", "", "HTTP server listening url. will OVERRIDE http.addr and http.port. will NOT respect http paths. prefix supported are tcp, unix") + rootCmd.PersistentFlags().IntVar(&cfg.HttpPort, "http.port", nodecfg.DefaultHTTPPort, "HTTP-RPC server listening port") + rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpCORSDomain, "http.corsdomain", []string{}, "Comma separated list of domains from which to accept cross origin requests (browser enforced)") + rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpVirtualHost, "http.vhosts", nodecfg.DefaultConfig.HTTPVirtualHosts, "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.") + rootCmd.PersistentFlags().BoolVar(&cfg.HttpCompression, "http.compression", true, "Disable http compression") + rootCmd.PersistentFlags().StringSliceVar(&cfg.API, "http.api", []string{"eth", "erigon"}, "API's offered over the HTTP-RPC interface: eth,erigon,web3,net,debug,trace,txpool,db. Supported methods: https://github.com/ledgerwatch/erigon/tree/devel/cmd/rpcdaemon") + rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets - Same port as HTTP") + rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketCompression, "ws.compression", false, "Enable Websocket compression (RFC 7692)") + + rootCmd.PersistentFlags().BoolVar(&cfg.SocketServerEnabled, "socket.enabled", false, "Enable IPC server") + rootCmd.PersistentFlags().StringVar(&cfg.SocketListenUrl, "socket.url", "unix:///var/run/erigon.sock", "IPC server listening url. prefix supported are tcp, unix") rootCmd.PersistentFlags().BoolVar(&cfg.TraceRequests, utils.HTTPTraceFlag.Name, false, "Trace HTTP requests with INFO level") rootCmd.PersistentFlags().DurationVar(&cfg.HTTPTimeouts.ReadTimeout, "http.timeouts.read", rpccfg.DefaultHTTPTimeouts.ReadTimeout, "Maximum duration for reading the entire request, including the body.") @@ -546,7 +551,6 @@ func StartRpcServerWithJwtAuthentication(ctx context.Context, cfg httpcfg.HttpCf func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rpc.API, logger log.Logger) error { // register apis and create handler stack - httpEndpoint := fmt.Sprintf("%s:%d", cfg.HttpListenAddress, cfg.HttpPort) srv := rpc.NewServer(cfg.RpcBatchConcurrency, cfg.TraceRequests, cfg.RpcStreamingDisable, logger) @@ -558,6 +562,8 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp srv.SetBatchLimit(cfg.BatchLimit) + defer srv.Stop() + var defaultAPIList []rpc.API for _, api := range rpcAPI { @@ -577,43 +583,61 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp return fmt.Errorf("could not start register RPC apis: %w", err) } - httpHandler := node.NewHTTPHandlerStack(srv, cfg.HttpCORSDomain, cfg.HttpVirtualHost, cfg.HttpCompression) - var wsHandler http.Handler - if cfg.WebsocketEnabled { - wsHandler = srv.WebsocketHandler([]string{"*"}, nil, cfg.WebsocketCompression, logger) - } - - graphQLHandler := graphql.CreateHandler(defaultAPIList) - - apiHandler, err := createHandler(cfg, defaultAPIList, httpHandler, wsHandler, graphQLHandler, nil) - if err != nil { - return err - } - - listener, httpAddr, err := node.StartHTTPEndpoint(httpEndpoint, cfg.HTTPTimeouts, apiHandler) - if err != nil { - return fmt.Errorf("could not start RPC api: %w", err) + info := []interface{}{ + "ws", cfg.WebsocketEnabled, + "ws.compression", cfg.WebsocketCompression, "grpc", cfg.GRPCServerEnabled, } - if cfg.TCPServerEnabled { - tcpEndpoint := fmt.Sprintf("%s:%d", cfg.TCPListenAddress, cfg.TCPPort) - tcpListener, err := net.Listen("tcp", tcpEndpoint) + if cfg.SocketServerEnabled { + socketUrl, err := url.Parse(cfg.SocketListenUrl) + if err != nil { + return fmt.Errorf("malformatted socket url %s: %w", cfg.SocketListenUrl, err) + } + tcpListener, err := net.Listen(socketUrl.Scheme, socketUrl.Host+socketUrl.EscapedPath()) if err != nil { - return fmt.Errorf("could not start TCP Listener: %w", err) + return fmt.Errorf("could not start Socket Listener: %w", err) } + defer tcpListener.Close() go func() { - defer tcpListener.Close() err := srv.ServeListener(tcpListener) if err != nil { - logger.Error("TCP Listener Fatal Error", "err", err) + if !errors.Is(err, net.ErrClosed) { + logger.Error("Socket Listener Fatal Error", "err", err) + } } }() - logger.Info("TCP Endpoint opened", "url", tcpEndpoint) + info = append(info, "socket.url", socketUrl) + logger.Info("Socket Endpoint opened", "url", socketUrl) } - info := []interface{}{ - "url", httpAddr, "ws", cfg.WebsocketEnabled, - "ws.compression", cfg.WebsocketCompression, "grpc", cfg.GRPCServerEnabled, + if cfg.HttpServerEnabled { + httpHandler := node.NewHTTPHandlerStack(srv, cfg.HttpCORSDomain, cfg.HttpVirtualHost, cfg.HttpCompression) + var wsHandler http.Handler + if cfg.WebsocketEnabled { + wsHandler = srv.WebsocketHandler([]string{"*"}, nil, cfg.WebsocketCompression, logger) + } + + graphQLHandler := graphql.CreateHandler(defaultAPIList) + + apiHandler, err := createHandler(cfg, defaultAPIList, httpHandler, wsHandler, graphQLHandler, nil) + if err != nil { + return err + } + httpEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.HttpListenAddress, cfg.HttpPort) + if cfg.HttpURL != "" { + httpEndpoint = cfg.HttpURL + } + listener, httpAddr, err := node.StartHTTPEndpoint(httpEndpoint, cfg.HTTPTimeouts, apiHandler) + if err != nil { + return fmt.Errorf("could not start RPC api: %w", err) + } + info = append(info, "http.url", httpAddr) + defer func() { + shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + _ = listener.Shutdown(shutdownCtx) + logger.Info("HTTP endpoint closed", "url", httpAddr) + }() } var ( @@ -634,26 +658,20 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp } go grpcServer.Serve(grpcListener) info = append(info, "grpc.port", cfg.GRPCPort) - } - - logger.Info("HTTP endpoint opened", info...) - - defer func() { - srv.Stop() - shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - _ = listener.Shutdown(shutdownCtx) - logger.Info("HTTP endpoint closed", "url", httpAddr) - if cfg.GRPCServerEnabled { - if cfg.GRPCHealthCheckEnabled { - healthServer.Shutdown() + defer func() { + if cfg.GRPCServerEnabled { + if cfg.GRPCHealthCheckEnabled { + healthServer.Shutdown() + } + grpcServer.GracefulStop() + _ = grpcListener.Close() + logger.Info("GRPC endpoint closed", "url", grpcEndpoint) } - grpcServer.GracefulStop() - _ = grpcListener.Close() - logger.Info("GRPC endpoint closed", "url", grpcEndpoint) - } - }() + }() + } + + logger.Info("JsonRpc endpoint opened", info...) <-ctx.Done() logger.Info("Exiting...") return nil @@ -755,7 +773,7 @@ func createHandler(cfg httpcfg.HttpCfg, apiList []rpc.API, httpHandler http.Hand } func createEngineListener(cfg httpcfg.HttpCfg, engineApi []rpc.API, logger log.Logger) (*http.Server, *rpc.Server, string, error) { - engineHttpEndpoint := fmt.Sprintf("%s:%d", cfg.AuthRpcHTTPListenAddress, cfg.AuthRpcPort) + engineHttpEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.AuthRpcHTTPListenAddress, cfg.AuthRpcPort) engineSrv := rpc.NewServer(cfg.RpcBatchConcurrency, cfg.TraceRequests, true, logger) diff --git a/cmd/rpcdaemon/cli/config_test.go b/cmd/rpcdaemon/cli/config_test.go new file mode 100644 index 00000000000..c14c9cf9456 --- /dev/null +++ b/cmd/rpcdaemon/cli/config_test.go @@ -0,0 +1,21 @@ +package cli + +import ( + "net/url" + "testing" + + "github.com/stretchr/testify/require" +) + +func TestParseSocketUrl(t *testing.T) { + t.Run("sock", func(t *testing.T) { + socketUrl, err := url.Parse("unix:///some/file/path.sock") + require.NoError(t, err) + require.EqualValues(t, "/some/file/path.sock", socketUrl.Host+socketUrl.EscapedPath()) + }) + t.Run("sock", func(t *testing.T) { + socketUrl, err := url.Parse("tcp://localhost:1234") + require.NoError(t, err) + require.EqualValues(t, "localhost:1234", socketUrl.Host+socketUrl.EscapedPath()) + }) +} diff --git a/cmd/rpcdaemon/cli/httpcfg/http_cfg.go b/cmd/rpcdaemon/cli/httpcfg/http_cfg.go index 63d4cb6a0ff..408d3f82d90 100644 --- a/cmd/rpcdaemon/cli/httpcfg/http_cfg.go +++ b/cmd/rpcdaemon/cli/httpcfg/http_cfg.go @@ -10,37 +10,43 @@ import ( ) type HttpCfg struct { - Enabled bool - PrivateApiAddr string + Enabled bool + GraphQLEnabled bool WithDatadir bool // Erigon's database can be read by separated processes on same machine - in read-only mode - with full support of transactions. It will share same "OS PageCache" with Erigon process. DataDir string Dirs datadir.Dirs - HttpListenAddress string AuthRpcHTTPListenAddress string TLSCertfile string TLSCACert string TLSKeyFile string - HttpPort int - AuthRpcPort int - HttpCORSDomain []string - HttpVirtualHost []string - AuthRpcVirtualHost []string - HttpCompression bool - API []string - Gascap uint64 - MaxTraces uint64 - WebsocketEnabled bool - WebsocketCompression bool - RpcAllowListFilePath string - RpcBatchConcurrency uint - RpcStreamingDisable bool - DBReadConcurrency int - TraceCompatibility bool // Bug for bug compatibility for trace_ routines with OpenEthereum - TxPoolApiAddr string - StateCache kvcache.CoherentConfig - Snap ethconfig.BlocksFreezing - Sync ethconfig.Sync + + HttpServerEnabled bool + HttpURL string + HttpListenAddress string + HttpPort int + HttpCORSDomain []string + HttpVirtualHost []string + AuthRpcVirtualHost []string + HttpCompression bool + + AuthRpcPort int + PrivateApiAddr string + + API []string + Gascap uint64 + MaxTraces uint64 + WebsocketEnabled bool + WebsocketCompression bool + RpcAllowListFilePath string + RpcBatchConcurrency uint + RpcStreamingDisable bool + DBReadConcurrency int + TraceCompatibility bool // Bug for bug compatibility for trace_ routines with OpenEthereum + TxPoolApiAddr string + StateCache kvcache.CoherentConfig + Snap ethconfig.BlocksFreezing + Sync ethconfig.Sync // GRPC server GRPCServerEnabled bool @@ -48,10 +54,9 @@ type HttpCfg struct { GRPCPort int GRPCHealthCheckEnabled bool - // Raw TCP Server - TCPServerEnabled bool - TCPListenAddress string - TCPPort int + // Socket Server + SocketServerEnabled bool + SocketListenUrl string JWTSecretPath string // Engine API Authentication TraceRequests bool // Always trace requests in INFO level diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 578d796716f..95ccca55945 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -20,13 +20,14 @@ package utils import ( "crypto/ecdsa" "fmt" - "github.com/ledgerwatch/erigon/cl/clparams" "math/big" "path/filepath" "runtime" "strconv" "strings" + "github.com/ledgerwatch/erigon/cl/clparams" + "github.com/c2h5oh/datasize" "github.com/ledgerwatch/erigon-lib/chain/networkname" "github.com/ledgerwatch/erigon-lib/chain/snapcfg" diff --git a/node/endpoints.go b/node/endpoints.go index 3855b6dc8d3..8ca2e1696a2 100644 --- a/node/endpoints.go +++ b/node/endpoints.go @@ -19,8 +19,10 @@ package node import ( "context" "errors" + "fmt" "net" "net/http" + "net/url" "time" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -30,13 +32,17 @@ import ( ) // StartHTTPEndpoint starts the HTTP RPC endpoint. -func StartHTTPEndpoint(endpoint string, timeouts rpccfg.HTTPTimeouts, handler http.Handler) (*http.Server, net.Addr, error) { +func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler http.Handler) (*http.Server, net.Addr, error) { // start the HTTP listener var ( listener net.Listener err error ) - if listener, err = net.Listen("tcp", endpoint); err != nil { + socketUrl, err := url.Parse(urlEndpoint) + if err != nil { + return nil, nil, fmt.Errorf("malformatted http listen url %s: %w", urlEndpoint, err) + } + if listener, err = net.Listen(socketUrl.Scheme, socketUrl.Host+socketUrl.EscapedPath()); err != nil { return nil, nil, err } // make sure timeout values are meaningful From 8231cdaede29edf8255d32e2e4c25d9e89aff2f9 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Sun, 29 Oct 2023 10:37:50 +0100 Subject: [PATCH 23/44] downloader: less webseed logs (#8586) (#8607) Merge PR #8586 into `devel` Co-authored-by: Alex Sharov --- erigon-lib/downloader/downloadercfg/logger.go | 46 +++++++------------ 1 file changed, 17 insertions(+), 29 deletions(-) diff --git a/erigon-lib/downloader/downloadercfg/logger.go b/erigon-lib/downloader/downloadercfg/logger.go index a64a4993a39..b3a3178d101 100644 --- a/erigon-lib/downloader/downloadercfg/logger.go +++ b/erigon-lib/downloader/downloadercfg/logger.go @@ -73,7 +73,7 @@ func (b adapterHandler) Handle(r lg.Record) { strings.Contains(str, "EOF") || strings.Contains(str, "closed") || strings.Contains(str, "connection reset by peer") || strings.Contains(str, "use of closed network connection") || strings.Contains(str, "broken pipe") || strings.Contains(str, "inited with remoteAddr") if skip { - log.Trace(str) + log.Trace(str, "lvl", lvl.LogString()) break } log.Debug(str) @@ -83,36 +83,22 @@ func (b adapterHandler) Handle(r lg.Record) { //strings.Contains(str, "banning ip ") || //strings.Contains(str, "spurious timer") { // suppress useless errors if skip { - log.Trace(str) + log.Trace(str, "lvl", lvl.LogString()) break } log.Info(str) case lg.Warning: str := r.String() skip := strings.Contains(str, "EOF") || - strings.Contains(str, "requested chunk too long") - - //if strings.Contains(str, "could not find offer for id") { // suppress useless errors - // break - //} - //if strings.Contains(str, "webrtc conn for unloaded torrent") { // suppress useless errors - // break - //} - //if strings.Contains(str, "TrackerClient closed") { // suppress useless errors - // break - //} - //if strings.Contains(str, "banned ip") { // suppress useless errors - // break - //} - //if strings.Contains(str, "being sole dirtier of piece") { // suppress useless errors - // break - //} - //if strings.Contains(str, "reservation cancelled") { // suppress useless errors - // break - //} - //if strings.Contains(str, "received invalid reject") { // suppress useless errors - // break - //} + strings.Contains(str, "requested chunk too long") || + strings.Contains(str, "banned ip") || + strings.Contains(str, "banning webseed") || + strings.Contains(str, "TrackerClient closed") || + strings.Contains(str, "being sole dirtier of piece") || + strings.Contains(str, "webrtc conn for unloaded torrent") || + strings.Contains(str, "could not find offer for id") || + strings.Contains(str, "received invalid reject") || + strings.Contains(str, "reservation cancelled") if skip { log.Trace(str) @@ -121,9 +107,11 @@ func (b adapterHandler) Handle(r lg.Record) { log.Warn(str) case lg.Error: str := r.String() - skip := strings.Contains(str, "EOF") + skip := strings.Contains(str, "EOF") || + strings.Contains(str, "short write") || + strings.Contains(str, "disabling data download") if skip { - log.Trace(str) + log.Trace(str, "lvl", lvl.LogString()) break } log.Error(str) @@ -133,7 +121,7 @@ func (b adapterHandler) Handle(r lg.Record) { strings.Contains(str, "torrent closed") || strings.Contains(str, "don't want conns") if skip { - log.Trace(str) + log.Trace(str, "lvl", lvl.LogString()) break } log.Error(str) @@ -141,7 +129,7 @@ func (b adapterHandler) Handle(r lg.Record) { str := r.String() skip := strings.Contains(str, "EOF") || strings.Contains(str, "unhandled response status") if skip { - log.Trace(str) + log.Trace(str, "lvl", lvl.LogString()) break } log.Info("[downloader] "+r.String(), "torrent_log_type", "unknown", "or", lvl.LogString()) From 8f67a8c55696e9d70e22ee3f0a9775b054cc8d18 Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Sun, 29 Oct 2023 11:13:06 +0100 Subject: [PATCH 24/44] Txpool: db unlimited grow fix (#8596) (#8608) read transaction was opened before stream.Recv(), but stream.Recv() is blocking infinity loop. so, this read transaction never rollback - causing unlimited db grow. --------- Merge PR #8596 into `devel` --------- Co-authored-by: Alex Sharov --- erigon-lib/txpool/fetch.go | 103 +++++++++++++++++++------------------ 1 file changed, 54 insertions(+), 49 deletions(-) diff --git a/erigon-lib/txpool/fetch.go b/erigon-lib/txpool/fetch.go index 552b01c58fb..eb4c443e27b 100644 --- a/erigon-lib/txpool/fetch.go +++ b/erigon-lib/txpool/fetch.go @@ -436,11 +436,6 @@ func (f *Fetch) handleStateChanges(ctx context.Context, client StateChangesClien if err != nil { return err } - tx, err := f.db.BeginRo(ctx) - if err != nil { - return err - } - defer tx.Rollback() for req, err := stream.Recv(); ; req, err = stream.Recv() { if err != nil { return err @@ -448,59 +443,69 @@ func (f *Fetch) handleStateChanges(ctx context.Context, client StateChangesClien if req == nil { return nil } + if err := f.handleStateChangesRequest(ctx, req); err != nil { + f.logger.Warn("[fetch] onNewBlock", "err", err) + } - var unwindTxs, minedTxs types2.TxSlots - for _, change := range req.ChangeBatch { - if change.Direction == remote.Direction_FORWARD { - minedTxs.Resize(uint(len(change.Txs))) - for i := range change.Txs { - minedTxs.Txs[i] = &types2.TxSlot{} - if err = f.threadSafeParseStateChangeTxn(func(parseContext *types2.TxParseContext) error { - _, err := parseContext.ParseTransaction(change.Txs[i], 0, minedTxs.Txs[i], minedTxs.Senders.At(i), false /* hasEnvelope */, false /* wrappedWithBlobs */, nil) - return err - }); err != nil && !errors.Is(err, context.Canceled) { - f.logger.Warn("stream.Recv", "err", err) - continue - } + if f.wg != nil { // to help tests + f.wg.Done() + } + } +} + +func (f *Fetch) handleStateChangesRequest(ctx context.Context, req *remote.StateChangeBatch) error { + var unwindTxs, minedTxs types2.TxSlots + for _, change := range req.ChangeBatch { + if change.Direction == remote.Direction_FORWARD { + minedTxs.Resize(uint(len(change.Txs))) + for i := range change.Txs { + minedTxs.Txs[i] = &types2.TxSlot{} + if err := f.threadSafeParseStateChangeTxn(func(parseContext *types2.TxParseContext) error { + _, err := parseContext.ParseTransaction(change.Txs[i], 0, minedTxs.Txs[i], minedTxs.Senders.At(i), false /* hasEnvelope */, false /* wrappedWithBlobs */, nil) + return err + }); err != nil && !errors.Is(err, context.Canceled) { + f.logger.Warn("[txpool.fetch] stream.Recv", "err", err) + continue // 1 tx handling error must not stop batch processing } } - if change.Direction == remote.Direction_UNWIND { - for i := range change.Txs { - if err = f.threadSafeParseStateChangeTxn(func(parseContext *types2.TxParseContext) error { - utx := &types2.TxSlot{} - sender := make([]byte, 20) - _, err2 := parseContext.ParseTransaction(change.Txs[i], 0, utx, sender, false /* hasEnvelope */, false /* wrappedWithBlobs */, nil) - if err2 != nil { - return err2 + } else if change.Direction == remote.Direction_UNWIND { + for i := range change.Txs { + if err := f.threadSafeParseStateChangeTxn(func(parseContext *types2.TxParseContext) error { + utx := &types2.TxSlot{} + sender := make([]byte, 20) + _, err := parseContext.ParseTransaction(change.Txs[i], 0, utx, sender, false /* hasEnvelope */, false /* wrappedWithBlobs */, nil) + if err != nil { + return err + } + if utx.Type == types2.BlobTxType { + var knownBlobTxn *metaTx + //TODO: don't check `KnownBlobTxn()` here - because each call require `txpool.mutex.lock()`. Better add all hashes here and do check inside `OnNewBlock` + if err := f.db.View(ctx, func(tx kv.Tx) error { + knownBlobTxn, err = f.pool.GetKnownBlobTxn(tx, utx.IDHash[:]) + return err + }); err != nil { + return err } - if utx.Type == types2.BlobTxType { - knownBlobTxn, err2 := f.pool.GetKnownBlobTxn(tx, utx.IDHash[:]) - if err2 != nil { - return err2 - } - // Get the blob tx from cache; ignore altogether if it isn't there - if knownBlobTxn != nil { - unwindTxs.Append(knownBlobTxn.Tx, sender, false) - } - } else { - unwindTxs.Append(utx, sender, false) + // Get the blob tx from cache; ignore altogether if it isn't there + if knownBlobTxn != nil { + unwindTxs.Append(knownBlobTxn.Tx, sender, false) } - return err - }); err != nil && !errors.Is(err, context.Canceled) { - f.logger.Warn("stream.Recv", "err", err) - continue + } else { + unwindTxs.Append(utx, sender, false) } + return nil + }); err != nil && !errors.Is(err, context.Canceled) { + f.logger.Warn("[txpool.fetch] stream.Recv", "err", err) + continue // 1 tx handling error must not stop batch processing } } } + } - if err := f.db.View(ctx, func(tx kv.Tx) error { - return f.pool.OnNewBlock(ctx, req, unwindTxs, minedTxs, tx) - }); err != nil && !errors.Is(err, context.Canceled) { - f.logger.Warn("onNewBlock", "err", err) - } - if f.wg != nil { - f.wg.Done() - } + if err := f.db.View(ctx, func(tx kv.Tx) error { + return f.pool.OnNewBlock(ctx, req, unwindTxs, minedTxs, tx) + }); err != nil && !errors.Is(err, context.Canceled) { + return err } + return nil } From b311da959f0e6614c024a02780db9d9c2f903e2b Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Mon, 30 Oct 2023 12:13:45 +0700 Subject: [PATCH 25/44] downloader: webseed better error messages (#8611) --- cmd/downloader/main.go | 2 - erigon-lib/chain/snapcfg/util.go | 3 -- .../downloader/downloadercfg/downloadercfg.go | 3 +- erigon-lib/downloader/snaptype/files.go | 2 +- erigon-lib/downloader/webseed.go | 41 +++++++++---------- turbo/app/snapshots_cmd.go | 6 --- .../freezeblocks/block_snapshots.go | 8 ++-- turbo/snapshotsync/snapshotsync.go | 3 -- 8 files changed, 26 insertions(+), 42 deletions(-) diff --git a/cmd/downloader/main.go b/cmd/downloader/main.go index b20480c4e57..7ae1bcdf6be 100644 --- a/cmd/downloader/main.go +++ b/cmd/downloader/main.go @@ -7,7 +7,6 @@ import ( "net" "os" "path/filepath" - "runtime" "strings" "time" @@ -178,7 +177,6 @@ func Downloader(ctx context.Context, logger log.Logger) error { return err } - cfg.ClientConfig.PieceHashersPerTorrent = runtime.NumCPU() * 4 cfg.ClientConfig.DisableIPv6 = disableIPV6 cfg.ClientConfig.DisableIPv4 = disableIPV4 diff --git a/erigon-lib/chain/snapcfg/util.go b/erigon-lib/chain/snapcfg/util.go index 8af11e63955..548c9b94a87 100644 --- a/erigon-lib/chain/snapcfg/util.go +++ b/erigon-lib/chain/snapcfg/util.go @@ -72,9 +72,6 @@ func maxBlockNum(preverified Preverified) uint64 { } onlyName := fileName[:len(fileName)-len(ext)] parts := strings.Split(onlyName, "-") - if parts[0] != "v1" { - panic("not implemented") - } if parts[3] != "headers" { continue } diff --git a/erigon-lib/downloader/downloadercfg/downloadercfg.go b/erigon-lib/downloader/downloadercfg/downloadercfg.go index 498a6894b96..dadc4d3376b 100644 --- a/erigon-lib/downloader/downloadercfg/downloadercfg.go +++ b/erigon-lib/downloader/downloadercfg/downloadercfg.go @@ -29,6 +29,7 @@ import ( lg "github.com/anacrolix/log" "github.com/anacrolix/torrent" "github.com/c2h5oh/datasize" + "github.com/ledgerwatch/erigon-lib/common/cmp" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/common/dir" "github.com/ledgerwatch/log/v3" @@ -59,7 +60,7 @@ type Cfg struct { func Default() *torrent.ClientConfig { torrentConfig := torrent.NewDefaultClientConfig() - torrentConfig.PieceHashersPerTorrent = runtime.NumCPU() + torrentConfig.PieceHashersPerTorrent = cmp.Max(1, runtime.NumCPU()-1) torrentConfig.MinDialTimeout = 6 * time.Second //default: 3s torrentConfig.HandshakesTimeout = 8 * time.Second //default: 4s diff --git a/erigon-lib/downloader/snaptype/files.go b/erigon-lib/downloader/snaptype/files.go index 102c5a2fc50..e61ef210c18 100644 --- a/erigon-lib/downloader/snaptype/files.go +++ b/erigon-lib/downloader/snaptype/files.go @@ -122,7 +122,7 @@ func FilesWithExt(dir, expectExt string) ([]FileInfo, error) { func IsCorrectFileName(name string) bool { parts := strings.Split(name, "-") - return len(parts) == 4 && parts[3] != "v1" + return len(parts) == 4 } func IsCorrectHistoryFileName(name string) bool { diff --git a/erigon-lib/downloader/webseed.go b/erigon-lib/downloader/webseed.go index 45947dedae7..02949c15e7b 100644 --- a/erigon-lib/downloader/webseed.go +++ b/erigon-lib/downloader/webseed.go @@ -56,7 +56,7 @@ func (d *WebSeeds) downloadWebseedTomlFromProviders(ctx context.Context, s3Provi } response, err := d.callHttpProvider(ctx, webSeedProviderURL) if err != nil { // don't fail on error - d.logger.Debug("[snapshots] downloadWebseedTomlFromProviders", "err", err, "url", webSeedProviderURL.EscapedPath()) + d.logger.Debug("[snapshots.webseed] get from HTTP provider", "err", err, "url", webSeedProviderURL.EscapedPath()) continue } list = append(list, response) @@ -69,7 +69,7 @@ func (d *WebSeeds) downloadWebseedTomlFromProviders(ctx context.Context, s3Provi } response, err := d.callS3Provider(ctx, webSeedProviderURL) if err != nil { // don't fail on error - d.logger.Debug("[snapshots] downloadWebseedTomlFromProviders", "err", err, "url", "s3") + d.logger.Debug("[snapshots.webseed] get from S3 provider", "err", err) continue } list = append(list, response) @@ -78,13 +78,9 @@ func (d *WebSeeds) downloadWebseedTomlFromProviders(ctx context.Context, s3Provi for _, webSeedFile := range diskProviders { response, err := d.readWebSeedsFile(webSeedFile) if err != nil { // don't fail on error - _, fileName := filepath.Split(webSeedFile) - d.logger.Debug("[snapshots] downloadWebseedTomlFromProviders", "err", err, "file", fileName) + d.logger.Debug("[snapshots.webseed] get from File provider", "err", err) continue } - if len(diskProviders) > 0 { - d.logger.Log(d.verbosity, "[snapshots] see webseed.toml file", "files", webSeedFile) - } list = append(list, response) } @@ -189,13 +185,14 @@ func (d *WebSeeds) callHttpProvider(ctx context.Context, webSeedProviderUrl *url request = request.WithContext(ctx) resp, err := http.DefaultClient.Do(request) if err != nil { - return nil, err + return nil, fmt.Errorf("webseed.http: host=%s, url=%s, %w", webSeedProviderUrl.Hostname(), webSeedProviderUrl.EscapedPath(), err) } defer resp.Body.Close() response := snaptype.WebSeedsFromProvider{} if err := toml.NewDecoder(resp.Body).Decode(&response); err != nil { - return nil, err + return nil, fmt.Errorf("webseed.http: host=%s, url=%s, %w", webSeedProviderUrl.Hostname(), webSeedProviderUrl.EscapedPath(), err) } + d.logger.Debug("[snapshots.webseed] get from HTTP provider", "urls", len(response), "host", webSeedProviderUrl.Hostname(), "url", webSeedProviderUrl.EscapedPath()) return response, nil } func (d *WebSeeds) callS3Provider(ctx context.Context, token string) (snaptype.WebSeedsFromProvider, error) { @@ -235,13 +232,14 @@ func (d *WebSeeds) callS3Provider(ctx context.Context, token string) (snaptype.W // } resp, err := client.GetObject(ctx, &s3.GetObjectInput{Bucket: &bucketName, Key: &fileName}) if err != nil { - return nil, err + return nil, fmt.Errorf("webseed.s3: bucket=%s, %w", bucketName, err) } defer resp.Body.Close() response := snaptype.WebSeedsFromProvider{} if err := toml.NewDecoder(resp.Body).Decode(&response); err != nil { - return nil, err + return nil, fmt.Errorf("webseed.s3: bucket=%s, %w", bucketName, err) } + d.logger.Debug("[snapshots.webseed] get from S3 provider", "urls", len(response), "bucket", bucketName) return response, nil } func (d *WebSeeds) callTorrentHttpProvider(ctx context.Context, url *url.URL) ([]byte, error) { @@ -252,7 +250,7 @@ func (d *WebSeeds) callTorrentHttpProvider(ctx context.Context, url *url.URL) ([ request = request.WithContext(ctx) resp, err := http.DefaultClient.Do(request) if err != nil { - return nil, err + return nil, fmt.Errorf("webseed.downloadTorrentFile: host=%s, url=%s, %w", url.Hostname(), url.EscapedPath(), err) } defer resp.Body.Close() //protect against too small and too big data @@ -261,28 +259,27 @@ func (d *WebSeeds) callTorrentHttpProvider(ctx context.Context, url *url.URL) ([ } res, err := io.ReadAll(resp.Body) if err != nil { - return nil, err + return nil, fmt.Errorf("webseed.downloadTorrentFile: host=%s, url=%s, %w", url.Hostname(), url.EscapedPath(), err) } - if err = validateTorrentBytes(res, url.Path); err != nil { - return nil, err + if err = validateTorrentBytes(res); err != nil { + return nil, fmt.Errorf("webseed.downloadTorrentFile: host=%s, url=%s, %w", url.Hostname(), url.EscapedPath(), err) } return res, nil } -func validateTorrentBytes(b []byte, url string) error { +func validateTorrentBytes(b []byte) error { var mi metainfo.MetaInfo - if err := bencode.NewDecoder(bytes.NewBuffer(b)).Decode(&mi); err != nil { - return fmt.Errorf("invalid bytes received from url %s, err=%w", url, err) - } - return nil + return bencode.NewDecoder(bytes.NewBuffer(b)).Decode(&mi) } func (d *WebSeeds) readWebSeedsFile(webSeedProviderPath string) (snaptype.WebSeedsFromProvider, error) { + _, fileName := filepath.Split(webSeedProviderPath) data, err := os.ReadFile(webSeedProviderPath) if err != nil { - return nil, err + return nil, fmt.Errorf("webseed.readWebSeedsFile: file=%s, %w", fileName, err) } response := snaptype.WebSeedsFromProvider{} if err := toml.Unmarshal(data, &response); err != nil { - return nil, err + return nil, fmt.Errorf("webseed.readWebSeedsFile: file=%s, %w", fileName, err) } + d.logger.Debug("[snapshots.webseed] get from File provider", "urls", len(response), "file", fileName) return response, nil } diff --git a/turbo/app/snapshots_cmd.go b/turbo/app/snapshots_cmd.go index 24d4621e4f0..fa8388ab365 100644 --- a/turbo/app/snapshots_cmd.go +++ b/turbo/app/snapshots_cmd.go @@ -21,7 +21,6 @@ import ( "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/common/dir" "github.com/ledgerwatch/erigon-lib/compress" - "github.com/ledgerwatch/erigon-lib/downloader/snaptype" "github.com/ledgerwatch/erigon-lib/etl" "github.com/ledgerwatch/erigon-lib/kv" "github.com/ledgerwatch/erigon-lib/kv/kvcfg" @@ -128,11 +127,6 @@ var ( Usage: "Do operation every N blocks", Value: 1_000, } - SnapshotSegmentSizeFlag = cli.Uint64Flag{ - Name: "segment.size", - Usage: "Amount of blocks in each segment", - Value: snaptype.Erigon2SegmentSize, - } SnapshotRebuildFlag = cli.BoolFlag{ Name: "rebuild", Usage: "Force rebuild", diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index d7d7ce35207..adfcc72ec34 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -1233,8 +1233,8 @@ func canRetire(from, to uint64) (blockFrom, blockTo uint64, can bool) { blockFrom = (from / 1_000) * 1_000 roundedTo1K := (to / 1_000) * 1_000 var maxJump uint64 = 1_000 - if blockFrom%500_000 == 0 { - maxJump = 500_000 + if blockFrom%snaptype.Erigon2SegmentSize == 0 { + maxJump = snaptype.Erigon2SegmentSize } else if blockFrom%100_000 == 0 { maxJump = 100_000 } else if blockFrom%10_000 == 0 { @@ -1243,8 +1243,8 @@ func canRetire(from, to uint64) (blockFrom, blockTo uint64, can bool) { //roundedTo1K := (to / 1_000) * 1_000 jump := cmp.Min(maxJump, roundedTo1K-blockFrom) switch { // only next segment sizes are allowed - case jump >= 500_000: - blockTo = blockFrom + 500_000 + case jump >= snaptype.Erigon2SegmentSize: + blockTo = blockFrom + snaptype.Erigon2SegmentSize case jump >= 100_000: blockTo = blockFrom + 100_000 case jump >= 10_000: diff --git a/turbo/snapshotsync/snapshotsync.go b/turbo/snapshotsync/snapshotsync.go index c1cfd628d1c..06c0a4a6fef 100644 --- a/turbo/snapshotsync/snapshotsync.go +++ b/turbo/snapshotsync/snapshotsync.go @@ -49,9 +49,6 @@ func BuildProtoRequest(downloadRequest []services.DownloadRequest) *proto_downlo }) } } else { - if r.Ranges.To-r.Ranges.From != snaptype.Erigon2SegmentSize { - continue - } if r.Bor { for _, t := range []snaptype.Type{snaptype.BorEvents, snaptype.BorSpans} { req.Items = append(req.Items, &proto_downloader.DownloadItem{ From c23e5a1abf9690ae9b2adb89d541cefcaa4ef9a4 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Mon, 30 Oct 2023 13:46:35 +0700 Subject: [PATCH 26/44] =?UTF-8?q?downloader:=20preparations=20for=20reduci?= =?UTF-8?q?ng=20blocks=20merge=C2=A0limit=20(#8612)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- cmd/capcli/cli.go | 4 +-- cmd/integration/commands/stages.go | 2 +- erigon-lib/downloader/snaptype/files.go | 12 +++++-- eth/backend.go | 2 +- turbo/app/snapshots_cmd.go | 2 +- .../freezeblocks/block_snapshots.go | 31 +++++++++++-------- .../freezeblocks/block_snapshots_test.go | 26 +++++++++++++--- .../freezeblocks/bor_snapshots.go | 15 ++++----- turbo/stages/mock/mock_sentry.go | 2 +- 9 files changed, 64 insertions(+), 32 deletions(-) diff --git a/cmd/capcli/cli.go b/cmd/capcli/cli.go index 4a0012e132d..5cf469ac8e4 100644 --- a/cmd/capcli/cli.go +++ b/cmd/capcli/cli.go @@ -442,7 +442,7 @@ func (c *DumpSnapshots) Run(ctx *Context) error { return }) - return freezeblocks.DumpBeaconBlocks(ctx, db, beaconDB, 0, to, snaptype.Erigon2SegmentSize, dirs.Tmp, dirs.Snap, 8, log.LvlInfo, log.Root()) + return freezeblocks.DumpBeaconBlocks(ctx, db, beaconDB, 0, to, snaptype.Erigon2MergeLimit, dirs.Tmp, dirs.Snap, 8, log.LvlInfo, log.Root()) } type CheckSnapshots struct { @@ -480,7 +480,7 @@ func (c *CheckSnapshots) Run(ctx *Context) error { return err } - to = (to / snaptype.Erigon2SegmentSize) * snaptype.Erigon2SegmentSize + to = (to / snaptype.Erigon2MergeLimit) * snaptype.Erigon2MergeLimit csn := freezeblocks.NewCaplinSnapshots(ethconfig.BlocksFreezing{}, dirs.Snap, log.Root()) if err := csn.ReopenFolder(); err != nil { diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index 8896ae7b27d..9849a7bad80 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -1551,7 +1551,7 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig, } notifications := &shards.Notifications{} - blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, db, notifications.Events, logger) + blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, freezeblocks.MergeSteps, db, notifications.Events, logger) stages := stages2.NewDefaultStages(context.Background(), db, p2p.Config{}, &cfg, sentryControlServer, notifications, nil, blockReader, blockRetire, agg, nil, nil, heimdallClient, logger) sync := stagedsync.New(stages, stagedsync.DefaultUnwindOrder, stagedsync.DefaultPruneOrder, logger) diff --git a/erigon-lib/downloader/snaptype/files.go b/erigon-lib/downloader/snaptype/files.go index e61ef210c18..562fe159f4f 100644 --- a/erigon-lib/downloader/snaptype/files.go +++ b/erigon-lib/downloader/snaptype/files.go @@ -155,7 +155,15 @@ func ParseFileName(dir, fileName string) (res FileInfo, ok bool) { } const Erigon3SeedableSteps = 32 -const Erigon2SegmentSize = 500_000 + +// Use-cases: +// - produce and seed snapshots earlier on chain tip. reduce depnedency on "good peers with history" at p2p-network. +// Some networks have no much archive peers, also ConsensusLayer clients are not-good(not-incentivised) at serving history. +// - avoiding having too much files: +// more files(shards) - means "more metadata", "more lookups for non-indexed queries", "more dictionaries", "more bittorrent connections", ... +// less files - means small files will be removed after merge (no peers for this files). +const Erigon2RecentMergeLimit = 100_000 //nolint +const Erigon2MergeLimit = 500_000 const Erigon2MinSegmentSize = 1_000 // FileInfo - parsed file metadata @@ -167,7 +175,7 @@ type FileInfo struct { } func (f FileInfo) TorrentFileExists() bool { return dir.FileExist(f.Path + ".torrent") } -func (f FileInfo) Seedable() bool { return f.To-f.From == Erigon2SegmentSize } +func (f FileInfo) Seedable() bool { return f.To-f.From == Erigon2MergeLimit } func (f FileInfo) NeedTorrentFile() bool { return f.Seedable() && !f.TorrentFileExists() } func IdxFiles(dir string) (res []FileInfo, err error) { return FilesWithExt(dir, ".idx") } diff --git a/eth/backend.go b/eth/backend.go index 6c271596dd3..c70fa9be3f9 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -622,7 +622,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger // intiialize engine backend var engine *execution_client.ExecutionClientDirect - blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, backend.chainDB, backend.notifications.Events, logger) + blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, freezeblocks.MergeSteps, backend.chainDB, backend.notifications.Events, logger) miningRPC = privateapi.NewMiningServer(ctx, backend, ethashApi, logger) diff --git a/turbo/app/snapshots_cmd.go b/turbo/app/snapshots_cmd.go index fa8388ab365..47f10f625d3 100644 --- a/turbo/app/snapshots_cmd.go +++ b/turbo/app/snapshots_cmd.go @@ -404,7 +404,7 @@ func doRetireCommand(cliCtx *cli.Context) error { blockReader := freezeblocks.NewBlockReader(blockSnapshots, borSnapshots) blockWriter := blockio.NewBlockWriter(fromdb.HistV3(db)) - br := freezeblocks.NewBlockRetire(estimate.CompressSnapshot.Workers(), dirs, blockReader, blockWriter, db, nil, logger) + br := freezeblocks.NewBlockRetire(estimate.CompressSnapshot.Workers(), dirs, blockReader, blockWriter, freezeblocks.MergeSteps, db, nil, logger) agg, err := libstate.NewAggregatorV3(ctx, dirs.SnapHistory, dirs.Tmp, ethconfig.HistoryV3AggregationStep, db, logger) if err != nil { return err diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index adfcc72ec34..dd36b794662 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -1202,10 +1202,12 @@ type BlockRetire struct { blockReader services.FullBlockReader blockWriter *blockio.BlockWriter dirs datadir.Dirs + + mergeSteps []uint64 } -func NewBlockRetire(workers int, dirs datadir.Dirs, blockReader services.FullBlockReader, blockWriter *blockio.BlockWriter, db kv.RoDB, notifier services.DBEventNotifier, logger log.Logger) *BlockRetire { - return &BlockRetire{workers: workers, tmpDir: dirs.Tmp, dirs: dirs, blockReader: blockReader, blockWriter: blockWriter, db: db, notifier: notifier, logger: logger} +func NewBlockRetire(workers int, dirs datadir.Dirs, blockReader services.FullBlockReader, blockWriter *blockio.BlockWriter, mergeSteps []uint64, db kv.RoDB, notifier services.DBEventNotifier, logger log.Logger) *BlockRetire { + return &BlockRetire{workers: workers, tmpDir: dirs.Tmp, dirs: dirs, blockReader: blockReader, blockWriter: blockWriter, mergeSteps: mergeSteps, db: db, notifier: notifier, logger: logger} } func (br *BlockRetire) snapshots() *RoSnapshots { return br.blockReader.Snapshots().(*RoSnapshots) } @@ -1233,8 +1235,8 @@ func canRetire(from, to uint64) (blockFrom, blockTo uint64, can bool) { blockFrom = (from / 1_000) * 1_000 roundedTo1K := (to / 1_000) * 1_000 var maxJump uint64 = 1_000 - if blockFrom%snaptype.Erigon2SegmentSize == 0 { - maxJump = snaptype.Erigon2SegmentSize + if blockFrom%snaptype.Erigon2MergeLimit == 0 { + maxJump = snaptype.Erigon2MergeLimit } else if blockFrom%100_000 == 0 { maxJump = 100_000 } else if blockFrom%10_000 == 0 { @@ -1243,8 +1245,8 @@ func canRetire(from, to uint64) (blockFrom, blockTo uint64, can bool) { //roundedTo1K := (to / 1_000) * 1_000 jump := cmp.Min(maxJump, roundedTo1K-blockFrom) switch { // only next segment sizes are allowed - case jump >= snaptype.Erigon2SegmentSize: - blockTo = blockFrom + snaptype.Erigon2SegmentSize + case jump >= snaptype.Erigon2MergeLimit: + blockTo = blockFrom + snaptype.Erigon2MergeLimit case jump >= 100_000: blockTo = blockFrom + 100_000 case jump >= 10_000: @@ -1274,7 +1276,7 @@ func (br *BlockRetire) RetireBlocks(ctx context.Context, blockFrom, blockTo uint firstTxNum := blockReader.(*BlockReader).FirstTxNumNotInSnapshots() // in future we will do it in background - if err := DumpBlocks(ctx, blockFrom, blockTo, snaptype.Erigon2SegmentSize, tmpDir, snapshots.Dir(), firstTxNum, db, workers, lvl, logger, blockReader); err != nil { + if err := DumpBlocks(ctx, blockFrom, blockTo, snaptype.Erigon2MergeLimit, tmpDir, snapshots.Dir(), firstTxNum, db, workers, lvl, logger, blockReader); err != nil { return fmt.Errorf("DumpBlocks: %w", err) } if err := snapshots.ReopenFolder(); err != nil { @@ -1284,7 +1286,7 @@ func (br *BlockRetire) RetireBlocks(ctx context.Context, blockFrom, blockTo uint if notifier != nil && !reflect.ValueOf(notifier).IsNil() { // notify about new snapshots of any size notifier.OnNewSnapshot() } - merger := NewMerger(tmpDir, workers, lvl, db, chainConfig, notifier, logger) + merger := NewMerger(tmpDir, workers, lvl, br.mergeSteps, db, chainConfig, notifier, logger) rangesToMerge := merger.FindMergeRanges(snapshots.Ranges()) if len(rangesToMerge) == 0 { return nil @@ -2172,10 +2174,11 @@ type Merger struct { chainDB kv.RoDB notifier services.DBEventNotifier logger log.Logger + mergeSteps []uint64 } -func NewMerger(tmpDir string, compressWorkers int, lvl log.Lvl, chainDB kv.RoDB, chainConfig *chain.Config, notifier services.DBEventNotifier, logger log.Logger) *Merger { - return &Merger{tmpDir: tmpDir, compressWorkers: compressWorkers, lvl: lvl, chainDB: chainDB, chainConfig: chainConfig, notifier: notifier, logger: logger} +func NewMerger(tmpDir string, compressWorkers int, lvl log.Lvl, mergeSteps []uint64, chainDB kv.RoDB, chainConfig *chain.Config, notifier services.DBEventNotifier, logger log.Logger) *Merger { + return &Merger{tmpDir: tmpDir, compressWorkers: compressWorkers, lvl: lvl, mergeSteps: mergeSteps, chainDB: chainDB, chainConfig: chainConfig, notifier: notifier, logger: logger} } type Range struct { @@ -2185,14 +2188,16 @@ type Range struct { func (r Range) From() uint64 { return r.from } func (r Range) To() uint64 { return r.to } -func (*Merger) FindMergeRanges(currentRanges []Range) (toMerge []Range) { +var MergeSteps = []uint64{500_000, 100_000, 10_000} + +func (m *Merger) FindMergeRanges(currentRanges []Range) (toMerge []Range) { for i := len(currentRanges) - 1; i > 0; i-- { r := currentRanges[i] - if r.to-r.from >= snaptype.Erigon2SegmentSize { // is complete .seg + if r.to-r.from >= snaptype.Erigon2MergeLimit { // is complete .seg continue } - for _, span := range []uint64{500_000, 100_000, 10_000} { + for _, span := range m.mergeSteps { if r.to%span != 0 { continue } diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots_test.go b/turbo/snapshotsync/freezeblocks/block_snapshots_test.go index 39c0ce60794..eb663df0911 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots_test.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots_test.go @@ -57,6 +57,24 @@ func createTestSegmentFile(t *testing.T, from, to uint64, name snaptype.Type, di } } +func TestFindMergeRange(t *testing.T) { + t.Run("big", func(t *testing.T) { + merger := NewMerger("x", 1, log.LvlInfo, MergeSteps, nil, params.MainnetChainConfig, nil, nil) + var ranges []Range + for i := 0; i < 24; i++ { + ranges = append(ranges, Range{from: uint64(i * 100_000), to: uint64((i + 1) * 100_000)}) + } + found := merger.FindMergeRanges(ranges) + + var expect []Range + for i := 0; i < 4; i++ { + expect = append(expect, Range{from: uint64(i * snaptype.Erigon2MergeLimit), to: uint64((i + 1) * snaptype.Erigon2MergeLimit)}) + } + require.Equal(t, expect, found) + }) + +} + func TestMergeSnapshots(t *testing.T) { logger := log.New() dir, require := t.TempDir(), require.New(t) @@ -67,15 +85,15 @@ func TestMergeSnapshots(t *testing.T) { } N := uint64(7) - createFile(0, 500_000) - for i := uint64(500_000); i < 500_000+N*100_000; i += 100_000 { + createFile(0, snaptype.Erigon2MergeLimit) + for i := uint64(snaptype.Erigon2MergeLimit); i < snaptype.Erigon2MergeLimit+N*100_000; i += 100_000 { createFile(i, i+100_000) } s := NewRoSnapshots(ethconfig.BlocksFreezing{Enabled: true}, dir, logger) defer s.Close() require.NoError(s.ReopenFolder()) { - merger := NewMerger(dir, 1, log.LvlInfo, nil, params.MainnetChainConfig, nil, logger) + merger := NewMerger(dir, 1, log.LvlInfo, MergeSteps, nil, params.MainnetChainConfig, nil, logger) ranges := merger.FindMergeRanges(s.Ranges()) require.True(len(ranges) > 0) err := merger.Merge(context.Background(), s, ranges, s.Dir(), false) @@ -90,7 +108,7 @@ func TestMergeSnapshots(t *testing.T) { require.Equal(5, a) { - merger := NewMerger(dir, 1, log.LvlInfo, nil, params.MainnetChainConfig, nil, logger) + merger := NewMerger(dir, 1, log.LvlInfo, MergeSteps, nil, params.MainnetChainConfig, nil, logger) ranges := merger.FindMergeRanges(s.Ranges()) require.True(len(ranges) == 0) err := merger.Merge(context.Background(), s, ranges, s.Dir(), false) diff --git a/turbo/snapshotsync/freezeblocks/bor_snapshots.go b/turbo/snapshotsync/freezeblocks/bor_snapshots.go index 1caf5abdba8..26846a64e54 100644 --- a/turbo/snapshotsync/freezeblocks/bor_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/bor_snapshots.go @@ -181,7 +181,7 @@ func (br *BlockRetire) RetireBorBlocks(ctx context.Context, blockFrom, blockTo u snapshots := br.borSnapshots() firstTxNum := blockReader.(*BlockReader).FirstTxNumNotInSnapshots() - if err := DumpBorBlocks(ctx, chainConfig, blockFrom, blockTo, snaptype.Erigon2SegmentSize, tmpDir, snapshots.Dir(), firstTxNum, db, workers, lvl, logger, blockReader); err != nil { + if err := DumpBorBlocks(ctx, chainConfig, blockFrom, blockTo, snaptype.Erigon2MergeLimit, tmpDir, snapshots.Dir(), firstTxNum, db, workers, lvl, logger, blockReader); err != nil { return fmt.Errorf("DumpBorBlocks: %w", err) } if err := snapshots.ReopenFolder(); err != nil { @@ -191,7 +191,7 @@ func (br *BlockRetire) RetireBorBlocks(ctx context.Context, blockFrom, blockTo u if notifier != nil && !reflect.ValueOf(notifier).IsNil() { // notify about new snapshots of any size notifier.OnNewSnapshot() } - merger := NewBorMerger(tmpDir, workers, lvl, db, chainConfig, notifier, logger) + merger := NewBorMerger(tmpDir, workers, lvl, br.mergeSteps, db, chainConfig, notifier, logger) rangesToMerge := merger.FindMergeRanges(snapshots.Ranges()) if len(rangesToMerge) == 0 { return nil @@ -1059,20 +1059,21 @@ type BorMerger struct { chainDB kv.RoDB notifier services.DBEventNotifier logger log.Logger + mergeSteps []uint64 } -func NewBorMerger(tmpDir string, compressWorkers int, lvl log.Lvl, chainDB kv.RoDB, chainConfig *chain.Config, notifier services.DBEventNotifier, logger log.Logger) *BorMerger { - return &BorMerger{tmpDir: tmpDir, compressWorkers: compressWorkers, lvl: lvl, chainDB: chainDB, chainConfig: chainConfig, notifier: notifier, logger: logger} +func NewBorMerger(tmpDir string, compressWorkers int, lvl log.Lvl, mergeSteps []uint64, chainDB kv.RoDB, chainConfig *chain.Config, notifier services.DBEventNotifier, logger log.Logger) *BorMerger { + return &BorMerger{tmpDir: tmpDir, compressWorkers: compressWorkers, lvl: lvl, mergeSteps: mergeSteps, chainDB: chainDB, chainConfig: chainConfig, notifier: notifier, logger: logger} } -func (*BorMerger) FindMergeRanges(currentRanges []Range) (toMerge []Range) { +func (m *BorMerger) FindMergeRanges(currentRanges []Range) (toMerge []Range) { for i := len(currentRanges) - 1; i > 0; i-- { r := currentRanges[i] - if r.to-r.from >= snaptype.Erigon2SegmentSize { // is complete .seg + if r.to-r.from >= snaptype.Erigon2MergeLimit { // is complete .seg continue } - for _, span := range []uint64{500_000, 100_000, 10_000} { + for _, span := range m.mergeSteps { if r.to%span != 0 { continue } diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index df9e7df5f54..ada1746a563 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -417,7 +417,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK return block, nil } - blockRetire := freezeblocks.NewBlockRetire(1, dirs, mock.BlockReader, blockWriter, mock.DB, mock.Notifications.Events, logger) + blockRetire := freezeblocks.NewBlockRetire(1, dirs, mock.BlockReader, blockWriter, freezeblocks.MergeSteps, mock.DB, mock.Notifications.Events, logger) mock.Sync = stagedsync.New( stagedsync.DefaultStages(mock.Ctx, stagedsync.StageSnapshotsCfg(mock.DB, *mock.ChainConfig, dirs, blockRetire, snapshotsDownloader, mock.BlockReader, mock.Notifications.Events, mock.HistoryV3, mock.agg, nil), From 513fd50fa501ab6385dc3f58b18079d806d6ff5a Mon Sep 17 00:00:00 2001 From: Giulio rebuffo Date: Mon, 30 Oct 2023 13:48:14 +0100 Subject: [PATCH 27/44] Compress snapshots for Caplin with lz4 level=1 (#8609) --- .../format/chunk_encoding/chunks.go | 26 +++- .../format/snapshot_format/blocks.go | 133 ++++++------------ cl/phase1/core/state/raw/copy.go | 3 - cmd/capcli/cli.go | 73 +++++++++- eth/backend.go | 1 - go.mod | 1 + go.sum | 2 + .../freezeblocks/beacon_block_reader.go | 25 +++- .../freezeblocks/caplin_snapshots.go | 16 ++- 9 files changed, 173 insertions(+), 107 deletions(-) diff --git a/cl/persistence/format/chunk_encoding/chunks.go b/cl/persistence/format/chunk_encoding/chunks.go index eeefb3962ee..28afb2008d9 100644 --- a/cl/persistence/format/chunk_encoding/chunks.go +++ b/cl/persistence/format/chunk_encoding/chunks.go @@ -28,7 +28,26 @@ func WriteChunk(w io.Writer, buf []byte, t DataType) error { return nil } -func ReadChunk(r io.Reader) (buf []byte, t DataType, err error) { +func ReadChunk(r io.Reader, out io.Writer) (t DataType, err error) { + prefix := make([]byte, 8) + if _, err := r.Read(prefix); err != nil { + return DataType(0), err + } + t = DataType(prefix[0]) + prefix[0] = 0 + + bufLen := binary.BigEndian.Uint64(prefix) + if bufLen == 0 { + return + } + + if _, err = io.CopyN(out, r, int64(bufLen)); err != nil { + return + } + return +} + +func ReadChunkToBytes(r io.Reader) (b []byte, t DataType, err error) { prefix := make([]byte, 8) if _, err := r.Read(prefix); err != nil { return nil, DataType(0), err @@ -40,8 +59,9 @@ func ReadChunk(r io.Reader) (buf []byte, t DataType, err error) { if bufLen == 0 { return } - buf = make([]byte, binary.BigEndian.Uint64(prefix)) - if _, err = r.Read(buf); err != nil { + b = make([]byte, bufLen) + + if _, err = r.Read(b); err != nil { return } return diff --git a/cl/persistence/format/snapshot_format/blocks.go b/cl/persistence/format/snapshot_format/blocks.go index 8029ef78407..66e4077318d 100644 --- a/cl/persistence/format/snapshot_format/blocks.go +++ b/cl/persistence/format/snapshot_format/blocks.go @@ -1,16 +1,21 @@ package snapshot_format import ( + "bytes" "encoding/binary" "fmt" "io" + "sync" - "github.com/golang/snappy" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" "github.com/ledgerwatch/erigon/cl/persistence/format/chunk_encoding" ) +var buffersPool = sync.Pool{ + New: func() interface{} { return &bytes.Buffer{} }, +} + type ExecutionBlockReaderByNumber interface { BlockByNumber(number uint64) (*cltypes.Eth1Block, error) } @@ -35,7 +40,7 @@ func writeExecutionBlockPtr(w io.Writer, p *cltypes.Eth1Block) error { } func readExecutionBlockPtr(r io.Reader) (uint64, error) { - b, dT, err := chunk_encoding.ReadChunk(r) + b, dT, err := chunk_encoding.ReadChunkToBytes(r) if err != nil { return 0, err } @@ -107,8 +112,7 @@ func WriteBlockForSnapshot(block *cltypes.SignedBeaconBlock, w io.Writer) error return chunk_encoding.WriteChunk(w, encoded, chunk_encoding.ChunkDataType) } -func readMetadataForBlock(r io.Reader) (clparams.StateVersion, error) { - b := make([]byte, 33) // version + body root +func readMetadataForBlock(r io.Reader, b []byte) (clparams.StateVersion, error) { if _, err := r.Read(b); err != nil { return 0, err } @@ -116,127 +120,70 @@ func readMetadataForBlock(r io.Reader) (clparams.StateVersion, error) { } func ReadBlockFromSnapshot(r io.Reader, executionReader ExecutionBlockReaderByNumber, cfg *clparams.BeaconChainConfig) (*cltypes.SignedBeaconBlock, error) { - plainSSZ := []byte{} - block := cltypes.NewSignedBeaconBlock(cfg) - // Metadata section is just the current hardfork of the block. TODO(give it a useful purpose) - v, err := readMetadataForBlock(r) - if err != nil { - return nil, err - } + buffer := buffersPool.Get().(*bytes.Buffer) + defer buffersPool.Put(buffer) + buffer.Reset() - // Read the first chunk - chunk1, dT1, err := chunk_encoding.ReadChunk(r) + v, err := ReadRawBlockFromSnapshot(r, buffer, executionReader, cfg) if err != nil { return nil, err } - if dT1 != chunk_encoding.ChunkDataType { - return nil, fmt.Errorf("malformed beacon block, invalid chunk 1 type %d, expected: %d", dT1, chunk_encoding.ChunkDataType) - } - plainSSZ = append(plainSSZ, chunk1...) - - if v <= clparams.AltairVersion { - return block, block.DecodeSSZ(plainSSZ, int(v)) - } - // Read the block pointer and retrieve chunk4 from the execution reader - blockPointer, err := readExecutionBlockPtr(r) - if err != nil { - return nil, err - } - executionBlock, err := executionReader.BlockByNumber(blockPointer) - if err != nil { - return nil, err - } - // Read the 4th chunk - chunk2, err := executionBlock.EncodeSSZ(nil) - if err != nil { - return nil, err - } - plainSSZ = append(plainSSZ, chunk2...) - if v <= clparams.BellatrixVersion { - return block, block.DecodeSSZ(plainSSZ, int(v)) - } - - // Read the 5h chunk - chunk3, dT5, err := chunk_encoding.ReadChunk(r) - if err != nil { - return nil, err - } - if dT5 != chunk_encoding.ChunkDataType { - return nil, fmt.Errorf("malformed beacon block, invalid chunk 5 type %d, expected: %d", dT5, chunk_encoding.ChunkDataType) - } - plainSSZ = append(plainSSZ, chunk3...) - - return block, block.DecodeSSZ(plainSSZ, int(v)) + return block, block.DecodeSSZ(buffer.Bytes(), int(v)) } -func ReadRawBlockFromSnapshot(r io.Reader, executionReader ExecutionBlockReaderByNumber, cfg *clparams.BeaconChainConfig) ([]byte, error) { - plainSSZ := []byte{} - - // Metadata section is just the current hardfork of the block. TODO(give it a useful purpose) - v, err := readMetadataForBlock(r) +func ReadRawBlockFromSnapshot(r io.Reader, out io.Writer, executionReader ExecutionBlockReaderByNumber, cfg *clparams.BeaconChainConfig) (clparams.StateVersion, error) { + metadataSlab := make([]byte, 33) + // Metadata section is just the current hardfork of the block. + v, err := readMetadataForBlock(r, metadataSlab) if err != nil { - return nil, err + return v, err } // Read the first chunk - chunk1, dT1, err := chunk_encoding.ReadChunk(r) + dT1, err := chunk_encoding.ReadChunk(r, out) if err != nil { - return nil, err + return v, err } if dT1 != chunk_encoding.ChunkDataType { - return nil, fmt.Errorf("malformed beacon block, invalid chunk 1 type %d, expected: %d", dT1, chunk_encoding.ChunkDataType) - } - plainSSZ = append(plainSSZ, chunk1...) - // Read the attestation chunk (2nd chunk) - chunk2, dT2, err := chunk_encoding.ReadChunk(snappy.NewReader(r)) - if err != nil { - return nil, err - } - if dT2 != chunk_encoding.ChunkDataType { - return nil, fmt.Errorf("malformed beacon block, invalid chunk 2 type %d, expected: %d", dT2, chunk_encoding.ChunkDataType) - } - plainSSZ = append(plainSSZ, chunk2...) - // Read the 3rd chunk - chunk3, dT3, err := chunk_encoding.ReadChunk(r) - if err != nil { - return nil, err + return v, fmt.Errorf("malformed beacon block, invalid chunk 1 type %d, expected: %d", dT1, chunk_encoding.ChunkDataType) } - if dT3 != chunk_encoding.ChunkDataType { - return nil, fmt.Errorf("malformed beacon block, invalid chunk 3 type %d, expected: %d", dT3, chunk_encoding.ChunkDataType) - } - plainSSZ = append(plainSSZ, chunk3...) + if v <= clparams.AltairVersion { - return plainSSZ, nil + return v, nil } // Read the block pointer and retrieve chunk4 from the execution reader blockPointer, err := readExecutionBlockPtr(r) if err != nil { - return nil, err + return v, err } executionBlock, err := executionReader.BlockByNumber(blockPointer) if err != nil { - return nil, err + return v, err + } + if executionBlock == nil { + return v, fmt.Errorf("execution block %d not found", blockPointer) } - // Read the 4th chunk - chunk4, err := executionBlock.EncodeSSZ(nil) + // TODO(Giulio2002): optimize GC + eth1Bytes, err := executionBlock.EncodeSSZ(nil) if err != nil { - return nil, err + return v, err + } + if _, err := out.Write(eth1Bytes); err != nil { + return v, err } - plainSSZ = append(plainSSZ, chunk4...) if v <= clparams.BellatrixVersion { - return plainSSZ, nil + return v, nil } // Read the 5h chunk - chunk5, dT5, err := chunk_encoding.ReadChunk(r) + dT2, err := chunk_encoding.ReadChunk(r, out) if err != nil { - return nil, err + return v, err } - if dT5 != chunk_encoding.ChunkDataType { - return nil, fmt.Errorf("malformed beacon block, invalid chunk 5 type %d, expected: %d", dT5, chunk_encoding.ChunkDataType) + if dT2 != chunk_encoding.ChunkDataType { + return v, fmt.Errorf("malformed beacon block, invalid chunk 5 type %d, expected: %d", dT2, chunk_encoding.ChunkDataType) } - plainSSZ = append(plainSSZ, chunk5...) - return plainSSZ, nil + return v, nil } diff --git a/cl/phase1/core/state/raw/copy.go b/cl/phase1/core/state/raw/copy.go index 4e547c71763..909fd3db9b9 100644 --- a/cl/phase1/core/state/raw/copy.go +++ b/cl/phase1/core/state/raw/copy.go @@ -1,8 +1,6 @@ package raw import ( - "fmt" - "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" "github.com/ledgerwatch/erigon/cl/cltypes/solid" @@ -65,6 +63,5 @@ func (b *BeaconState) CopyInto(dst *BeaconState) error { func (b *BeaconState) Copy() (*BeaconState, error) { copied := New(b.BeaconConfig()) - fmt.Println(copied.slashings) return copied, b.CopyInto(copied) } diff --git a/cmd/capcli/cli.go b/cmd/capcli/cli.go index 5cf469ac8e4..cfd04bb9426 100644 --- a/cmd/capcli/cli.go +++ b/cmd/capcli/cli.go @@ -7,9 +7,12 @@ import ( "strings" "time" + "github.com/ledgerwatch/erigon/turbo/debug" + lg "github.com/anacrolix/log" "github.com/ledgerwatch/erigon-lib/direct" downloader3 "github.com/ledgerwatch/erigon-lib/downloader" + "github.com/ledgerwatch/erigon-lib/metrics" state2 "github.com/ledgerwatch/erigon-lib/state" "github.com/c2h5oh/datasize" @@ -64,6 +67,7 @@ var CLI struct { DumpSnapshots DumpSnapshots `cmd:"" help:"generate caplin snapshots"` CheckSnapshots CheckSnapshots `cmd:"" help:"check snapshot folder against content of chain data"` DownloadSnapshots DownloadSnapshots `cmd:"" help:"download snapshots from webseed"` + LoopSnapshots LoopSnapshots `cmd:"" help:"loop over snapshots"` } type chainCfg struct { @@ -83,6 +87,16 @@ type withSentinel struct { Sentinel string `help:"sentinel url" default:"localhost:7777"` } +type withPPROF struct { + Pprof bool `help:"enable pprof" default:"false"` +} + +func (w *withPPROF) withProfile() { + if w.Pprof { + debug.StartPProf("localhost:6060", metrics.Setup("localhost:6060", log.Root())) + } +} + func (w *withSentinel) connectSentinel() (sentinel.SentinelClient, error) { // YOLO message size gconn, err := grpc.Dial(w.Sentinel, grpc.WithInsecure(), grpc.WithDefaultCallOptions(grpc.MaxCallRecvMsgSize(math.MaxInt))) @@ -448,6 +462,7 @@ func (c *DumpSnapshots) Run(ctx *Context) error { type CheckSnapshots struct { chainCfg outputFolder + withPPROF Slot uint64 `name:"slot" help:"slot to check"` } @@ -457,9 +472,9 @@ func (c *CheckSnapshots) Run(ctx *Context) error { if err != nil { return err } + c.withProfile() log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StderrHandler)) log.Info("Started the checking process", "chain", c.Chain) - dirs := datadir.New(c.Datadir) log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StderrHandler)) @@ -527,6 +542,61 @@ func (c *CheckSnapshots) Run(ctx *Context) error { return nil } +type LoopSnapshots struct { + chainCfg + outputFolder + withPPROF + + Slot uint64 `name:"slot" help:"slot to check"` +} + +func (c *LoopSnapshots) Run(ctx *Context) error { + c.withProfile() + + _, _, beaconConfig, _, err := clparams.GetConfigsByNetworkName(c.Chain) + if err != nil { + return err + } + log.Root().SetHandler(log.LvlFilterHandler(log.LvlDebug, log.StderrHandler)) + log.Info("Started the checking process", "chain", c.Chain) + + dirs := datadir.New(c.Datadir) + log.Root().SetHandler(log.LvlFilterHandler(log.LvlInfo, log.StderrHandler)) + + rawDB := persistence.AferoRawBeaconBlockChainFromOsPath(beaconConfig, dirs.CaplinHistory) + _, db, err := caplin1.OpenCaplinDatabase(ctx, db_config.DatabaseConfiguration{PruneDepth: math.MaxUint64}, beaconConfig, rawDB, dirs.CaplinIndexing, nil, false) + if err != nil { + return err + } + var to uint64 + tx, err := db.BeginRo(ctx) + if err != nil { + return err + } + defer tx.Rollback() + + to, err = beacon_indicies.ReadHighestFinalized(tx) + if err != nil { + return err + } + + to = (to / snaptype.Erigon2MergeLimit) * snaptype.Erigon2MergeLimit + + csn := freezeblocks.NewCaplinSnapshots(ethconfig.BlocksFreezing{}, dirs.Snap, log.Root()) + if err := csn.ReopenFolder(); err != nil { + return err + } + + br := &snapshot_format.MockBlockReader{} + snReader := freezeblocks.NewBeaconSnapshotReader(csn, br, beaconConfig) + start := time.Now() + for i := c.Slot; i < to; i++ { + snReader.ReadBlock(i) + } + log.Info("Successfully checked", "slot", c.Slot, "time", time.Since(start)) + return nil +} + type DownloadSnapshots struct { chainCfg outputFolder @@ -584,5 +654,4 @@ func (d *DownloadSnapshots) Run(ctx *Context) error { return fmt.Errorf("new server: %w", err) } return snapshotsync.WaitForDownloader("CapCliDownloader", ctx, false, snapshotsync.OnlyCaplin, s, tx, freezeblocks.NewBlockReader(freezeblocks.NewRoSnapshots(ethconfig.NewSnapCfg(false, false, false), dirs.Snap, log.Root()), freezeblocks.NewBorRoSnapshots(ethconfig.NewSnapCfg(false, false, false), dirs.Snap, log.Root())), nil, params.ChainConfigByChainName(d.Chain), direct.NewDownloaderClient(bittorrentServer)) - } diff --git a/eth/backend.go b/eth/backend.go index c70fa9be3f9..288f84238e9 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -485,7 +485,6 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger } } - fmt.Println(blockReader.FrozenBlocks()) inMemoryExecution := func(batch kv.RwTx, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, notifications *shards.Notifications) error { terseLogger := log.New() diff --git a/go.mod b/go.mod index fa42248c023..619bd24caac 100644 --- a/go.mod +++ b/go.mod @@ -66,6 +66,7 @@ require ( github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml/v2 v2.1.0 + github.com/pierrec/lz4 v2.6.1+incompatible github.com/pion/randutil v0.1.0 github.com/pion/stun v0.6.0 github.com/protolambda/ztyp v0.2.2 diff --git a/go.sum b/go.sum index 2f85410ceb2..81f8da24712 100644 --- a/go.sum +++ b/go.sum @@ -686,6 +686,8 @@ github.com/pelletier/go-toml/v2 v2.1.0 h1:FnwAJ4oYMvbT/34k9zzHuZNrhlz48GB3/s6at6 github.com/pelletier/go-toml/v2 v2.1.0/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc= github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pierrec/lz4 v2.6.1+incompatible h1:9UY3+iC23yxF0UfGaYrGplQ+79Rg+h/q9FV9ix19jjM= +github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pion/datachannel v1.5.2 h1:piB93s8LGmbECrpO84DnkIVWasRMk3IimbcXkTQLE6E= github.com/pion/datachannel v1.5.2/go.mod h1:FTGQWaHrdCwIJ1rw6xBIfZVkslikjShim5yr05XFuCQ= github.com/pion/dtls/v2 v2.1.3/go.mod h1:o6+WvyLDAlXF7YiPB/RlskRoeK+/JtuaZa5emwQcWus= diff --git a/turbo/snapshotsync/freezeblocks/beacon_block_reader.go b/turbo/snapshotsync/freezeblocks/beacon_block_reader.go index 78ef3fa9cc4..4f815791b1e 100644 --- a/turbo/snapshotsync/freezeblocks/beacon_block_reader.go +++ b/turbo/snapshotsync/freezeblocks/beacon_block_reader.go @@ -2,12 +2,24 @@ package freezeblocks import ( "bytes" + "sync" "github.com/ledgerwatch/erigon/cl/clparams" "github.com/ledgerwatch/erigon/cl/cltypes" "github.com/ledgerwatch/erigon/cl/persistence/format/snapshot_format" + "github.com/pierrec/lz4" ) +var buffersPool = sync.Pool{ + New: func() interface{} { return &bytes.Buffer{} }, +} + +var lz4ReaderPool = sync.Pool{ + New: func() interface{} { + return lz4.NewReader(nil) + }, +} + type BeaconSnapshotReader interface { // ReadBlock reads the block at the given slot. // If the block is not present, it returns nil. @@ -40,7 +52,18 @@ func (r *beaconSnapshotReader) ReadBlock(slot uint64) (*cltypes.SignedBeaconBloc if buf == nil { return nil, nil } - return snapshot_format.ReadBlockFromSnapshot(bytes.NewReader(buf), r.eth1Getter, r.cfg) + + // Use pooled buffers and readers to avoid allocations. + buffer := buffersPool.Get().(*bytes.Buffer) + defer buffersPool.Put(buffer) + buffer.Reset() + buffer.Write(buf) + + lzReader := lz4ReaderPool.Get().(*lz4.Reader) + defer lz4ReaderPool.Put(lzReader) + lzReader.Reset(buffer) + + return snapshot_format.ReadBlockFromSnapshot(lzReader, r.eth1Getter, r.cfg) } func (r *beaconSnapshotReader) RawBlockSSZ(slot uint64) ([]byte, error) { diff --git a/turbo/snapshotsync/freezeblocks/caplin_snapshots.go b/turbo/snapshotsync/freezeblocks/caplin_snapshots.go index 54c9cd2c5dc..064de66a85d 100644 --- a/turbo/snapshotsync/freezeblocks/caplin_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/caplin_snapshots.go @@ -23,6 +23,7 @@ import ( "github.com/ledgerwatch/erigon/cl/persistence/format/snapshot_format" "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/log/v3" + "github.com/pierrec/lz4" ) type BeaconBlockSegment struct { @@ -338,6 +339,9 @@ func dumpBeaconBlocksRange(ctx context.Context, db kv.RoDB, b persistence.BlockS return err } defer tx.Rollback() + var w bytes.Buffer + lzWriter := lz4.NewWriter(&w) + defer lzWriter.Close() // Generate .seg file, which is just the list of beacon blocks. for i := fromSlot; i < toSlot; i++ { obj, err := b.GetBlock(ctx, tx, i) @@ -354,16 +358,20 @@ func dumpBeaconBlocksRange(ctx context.Context, db kv.RoDB, b persistence.BlockS } continue } - var buf bytes.Buffer - if err := snapshot_format.WriteBlockForSnapshot(obj.Data, &buf); err != nil { + lzWriter.Reset(&w) + lzWriter.CompressionLevel = 1 + if err := snapshot_format.WriteBlockForSnapshot(obj.Data, lzWriter); err != nil { return err } - word := buf.Bytes() + if err := lzWriter.Flush(); err != nil { + return err + } + word := w.Bytes() if err := sn.AddWord(word); err != nil { return err } - + w.Reset() } if err := sn.Compress(); err != nil { return fmt.Errorf("compress: %w", err) From 83bbe0dd371b078fd93d3715b6c915d583bf2adb Mon Sep 17 00:00:00 2001 From: Anshal Shukla <53994948+anshalshukla@users.noreply.github.com> Date: Mon, 30 Oct 2023 19:48:47 +0530 Subject: [PATCH 28/44] Fix Agra hf scheduling on Mumbai (#8620) Co-authored-by: yperbasis --- erigon-lib/chain/chain_config_test.go | 8 ++++---- params/chainspecs/bor-devnet.json | 4 ++-- params/chainspecs/mumbai.json | 6 +++--- params/config_test.go | 10 +++++----- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/erigon-lib/chain/chain_config_test.go b/erigon-lib/chain/chain_config_test.go index d2b87a85a83..990202dd1c7 100644 --- a/erigon-lib/chain/chain_config_test.go +++ b/erigon-lib/chain/chain_config_test.go @@ -58,11 +58,11 @@ func TestBorKeyValueConfigHelper(t *testing.T) { burntContract := map[string]common.Address{ "22640000": address1, - "41824608": address2, + "41874000": address2, } assert.Equal(t, borKeyValueConfigHelper(burntContract, 22640000), address1) assert.Equal(t, borKeyValueConfigHelper(burntContract, 22640000+1), address1) - assert.Equal(t, borKeyValueConfigHelper(burntContract, 41824608-1), address1) - assert.Equal(t, borKeyValueConfigHelper(burntContract, 41824608), address2) - assert.Equal(t, borKeyValueConfigHelper(burntContract, 41824608+1), address2) + assert.Equal(t, borKeyValueConfigHelper(burntContract, 41874000-1), address1) + assert.Equal(t, borKeyValueConfigHelper(burntContract, 41874000), address2) + assert.Equal(t, borKeyValueConfigHelper(burntContract, 41874000+1), address2) } diff --git a/params/chainspecs/bor-devnet.json b/params/chainspecs/bor-devnet.json index 17dd3a5786f..e41007f9535 100644 --- a/params/chainspecs/bor-devnet.json +++ b/params/chainspecs/bor-devnet.json @@ -14,7 +14,7 @@ "londonBlock": 0, "burntContract": { "22640000": "0x70bcA57F4579f58670aB2d18Ef16e02C17553C38", - "41824608": "0x617b94CCCC2511808A3C9478ebb96f455CF167aA" + "41874000": "0x617b94CCCC2511808A3C9478ebb96f455CF167aA" }, "bor": { "period": { @@ -41,7 +41,7 @@ "code": "0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611546565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154c565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115d9565b005b348015610b2e57600080fd5b50610b376115f6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161c90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da76023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163c90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d846023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165b565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600181526020017f890000000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611753565b90505b92915050565b6040518060800160405280605b8152602001611e1c605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b10565b611be6565b9050949350505050565b608981565b60015481565b604051806080016040528060528152602001611dca605291396040516020018082805190602001908083835b6020831061159b5780518252602082019150602081019050602083039250611578565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e1611381565b6115ea57600080fd5b6115f38161165b565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162b57600080fd5b600082840390508091505092915050565b60008082840190508381101561165157600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169557600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d357600080fd5b505afa1580156117e7573d6000803e3d6000fd5b505050506040513d60208110156117fd57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561188f57600080fd5b505afa1580156118a3573d6000803e3d6000fd5b505050506040513d60208110156118b957600080fd5b810190808051906020019092919050505090506118d7868686611c30565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119df57600080fd5b505afa1580156119f3573d6000803e3d6000fd5b505050506040513d6020811015611a0957600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9757600080fd5b505afa158015611aab573d6000803e3d6000fd5b505050506040513d6020811015611ac157600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1c605b91396040516020018082805190602001908083835b60208310611b625780518252602082019150602081019050602083039250611b3f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d18573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820a4a6f71a98ac3fc613c3a8f1e2e11b9eb9b6b39f125f7d9508916c2b8fb02c7164736f6c63430005100032" } }, - "41824608": { + "41874000": { "0x0000000000000000000000000000000000001001": { "balance": "0x0", "code": "0x608060405234801561001057600080fd5b506004361061005e576000357c01000000000000000000000000000000000000000000000000000000009004806319494a17146100635780633434735f146100fe5780635407ca6714610148575b600080fd5b6100e46004803603604081101561007957600080fd5b8101908080359060200190929190803590602001906401000000008111156100a057600080fd5b8201836020820111156100b257600080fd5b803590602001918460018302840111640100000000831117156100d457600080fd5b9091929391929390505050610166565b604051808215151515815260200191505060405180910390f35b6101066104d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101506104eb565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461021d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061027461026f85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506104f1565b61051f565b905060006102958260008151811061028857fe5b60200260200101516105fc565b90508060016000540114610311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103418360018151811061033457fe5b602002602001015161066d565b905060606103628460028151811061035557fe5b6020026020010151610690565b905061036d8261071c565b156104c8576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103c75780820151818401526020810190506103ac565b50505050905090810190601f1680156103f45780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f19650847f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee88604051808215151515815260200191505060405180910390a250505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104f961099c565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061052a82610735565b61053357600080fd5b600061053e83610783565b905060608160405190808252806020026020018201604052801561057c57816020015b6105696109b6565b8152602001906001900390816105615790505b509050600061058e85602001516107f4565b8560200151019050600080600090505b848110156105ef576105af8361087d565b91506040518060400160405280838152602001848152508482815181106105d257fe5b60200260200101819052508183019250808060010191505061059e565b5082945050505050919050565b600080826000015111801561061657506021826000015111155b61061f57600080fd5b600061062e83602001516107f4565b9050600081846000015103905060008083866020015101905080519150602083101561066157826020036101000a820491505b81945050505050919050565b6000601582600001511461068057600080fd5b610689826105fc565b9050919050565b606060008260000151116106a357600080fd5b60006106b283602001516107f4565b905060008184600001510390506060816040519080825280601f01601f1916602001820160405280156106f45781602001600182028038833980820191505090505b5090506000816020019050610710848760200151018285610935565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b6000808260000151141561074c576000905061077e565b60008083602001519050805160001a915060c060ff168260ff1610156107775760009250505061077e565b6001925050505b919050565b6000808260000151141561079a57600090506107ef565b600080905060006107ae84602001516107f4565b84602001510190506000846000015185602001510190505b808210156107e8576107d78261087d565b8201915082806001019350506107c6565b8293505050505b919050565b600080825160001a9050608060ff16811015610814576000915050610878565b60b860ff16811080610839575060c060ff168110158015610838575060f860ff1681105b5b15610848576001915050610878565b60c060ff168110156108685760018060b80360ff16820301915050610878565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561089e576001915061092b565b60b860ff168110156108bb576001608060ff16820301915061092a565b60c060ff168110156108eb5760b78103600185019450806020036101000a85510460018201810193505050610929565b60f860ff1681101561090857600160c060ff168203019150610928565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b600081141561094357610997565b5b602060ff1681106109735782518252602060ff1683019250602060ff1682019150602060ff1681039050610944565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a723158208f1ea6fcf63d6911ac5dbfe340be1029614581802c6a750e7d6354b32ce6647c64736f6c63430005110032" diff --git a/params/chainspecs/mumbai.json b/params/chainspecs/mumbai.json index 6a4c192425b..3a61eb1acd1 100644 --- a/params/chainspecs/mumbai.json +++ b/params/chainspecs/mumbai.json @@ -14,7 +14,7 @@ "londonBlock": 22640000, "burntContract": { "22640000": "0x70bcA57F4579f58670aB2d18Ef16e02C17553C38", - "41824608": "0x617b94CCCC2511808A3C9478ebb96f455CF167aA" + "41874000": "0x617b94CCCC2511808A3C9478ebb96f455CF167aA" }, "bor": { "period": { @@ -48,7 +48,7 @@ "code": "0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611548565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154e565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115db565b005b348015610b2e57600080fd5b50610b376115f8565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161e90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da96023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163e90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d866023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165d565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600381526020017f013881000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611755565b90505b92915050565b6040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b12565b611be8565b9050949350505050565b6201388181565b60015481565b604051806080016040528060528152602001611dcc605291396040516020018082805190602001908083835b6020831061159d578051825260208201915060208101905060208303925061157a565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e3611381565b6115ec57600080fd5b6115f58161165d565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162d57600080fd5b600082840390508091505092915050565b60008082840190508381101561165357600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169757600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d557600080fd5b505afa1580156117e9573d6000803e3d6000fd5b505050506040513d60208110156117ff57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561189157600080fd5b505afa1580156118a5573d6000803e3d6000fd5b505050506040513d60208110156118bb57600080fd5b810190808051906020019092919050505090506118d9868686611c32565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119e157600080fd5b505afa1580156119f5573d6000803e3d6000fd5b505050506040513d6020811015611a0b57600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9957600080fd5b505afa158015611aad573d6000803e3d6000fd5b505050506040513d6020811015611ac357600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1e605b91396040516020018082805190602001908083835b60208310611b645780518252602082019150602081019050602083039250611b41565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d1a573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820ccd6c2a9c259832bbb367986ee06cd87af23022681b0cb22311a864b701d939564736f6c63430005100032" } }, - "41824608": { + "41874000": { "0x0000000000000000000000000000000000001001": { "balance": "0x0", "code": "0x608060405234801561001057600080fd5b506004361061005e576000357c01000000000000000000000000000000000000000000000000000000009004806319494a17146100635780633434735f146100fe5780635407ca6714610148575b600080fd5b6100e46004803603604081101561007957600080fd5b8101908080359060200190929190803590602001906401000000008111156100a057600080fd5b8201836020820111156100b257600080fd5b803590602001918460018302840111640100000000831117156100d457600080fd5b9091929391929390505050610166565b604051808215151515815260200191505060405180910390f35b6101066104d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101506104eb565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461021d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061027461026f85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050506104f1565b61051f565b905060006102958260008151811061028857fe5b60200260200101516105fc565b90508060016000540114610311576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103418360018151811061033457fe5b602002602001015161066d565b905060606103628460028151811061035557fe5b6020026020010151610690565b905061036d8261071c565b156104c8576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103c75780820151818401526020810190506103ac565b50505050905090810190601f1680156103f45780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f19650847f5a22725590b0a51c923940223f7458512164b1113359a735e86e7f27f44791ee88604051808215151515815260200191505060405180910390a250505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104f961099c565b600060208301905060405180604001604052808451815260200182815250915050919050565b606061052a82610735565b61053357600080fd5b600061053e83610783565b905060608160405190808252806020026020018201604052801561057c57816020015b6105696109b6565b8152602001906001900390816105615790505b509050600061058e85602001516107f4565b8560200151019050600080600090505b848110156105ef576105af8361087d565b91506040518060400160405280838152602001848152508482815181106105d257fe5b60200260200101819052508183019250808060010191505061059e565b5082945050505050919050565b600080826000015111801561061657506021826000015111155b61061f57600080fd5b600061062e83602001516107f4565b9050600081846000015103905060008083866020015101905080519150602083101561066157826020036101000a820491505b81945050505050919050565b6000601582600001511461068057600080fd5b610689826105fc565b9050919050565b606060008260000151116106a357600080fd5b60006106b283602001516107f4565b905060008184600001510390506060816040519080825280601f01601f1916602001820160405280156106f45781602001600182028038833980820191505090505b5090506000816020019050610710848760200151018285610935565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b6000808260000151141561074c576000905061077e565b60008083602001519050805160001a915060c060ff168260ff1610156107775760009250505061077e565b6001925050505b919050565b6000808260000151141561079a57600090506107ef565b600080905060006107ae84602001516107f4565b84602001510190506000846000015185602001510190505b808210156107e8576107d78261087d565b8201915082806001019350506107c6565b8293505050505b919050565b600080825160001a9050608060ff16811015610814576000915050610878565b60b860ff16811080610839575060c060ff168110158015610838575060f860ff1681105b5b15610848576001915050610878565b60c060ff168110156108685760018060b80360ff16820301915050610878565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561089e576001915061092b565b60b860ff168110156108bb576001608060ff16820301915061092a565b60c060ff168110156108eb5760b78103600185019450806020036101000a85510460018201810193505050610929565b60f860ff1681101561090857600160c060ff168203019150610928565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b600081141561094357610997565b5b602060ff1681106109735782518252602060ff1683019250602060ff1682019150602060ff1681039050610944565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a723158208f1ea6fcf63d6911ac5dbfe340be1029614581802c6a750e7d6354b32ce6647c64736f6c63430005110032" @@ -58,6 +58,6 @@ "jaipurBlock": 22770000, "delhiBlock": 29638656, "indoreBlock": 37075456, - "agraBlock": 41824608 + "agraBlock": 41874000 } } diff --git a/params/config_test.go b/params/config_test.go index 7a46adfdf52..7617ead1ac0 100644 --- a/params/config_test.go +++ b/params/config_test.go @@ -117,19 +117,19 @@ func TestGetBurntContract(t *testing.T) { assert.Equal(t, common.HexToAddress("0x6BBe78ee9e474842Dbd4AB4987b3CeFE88426A92"), *addr) // Mumbai - addr = MumbaiChainConfig.GetBurntContract(22_640_000) + addr = MumbaiChainConfig.GetBurntContract(22640000) require.NotNil(t, addr) assert.Equal(t, common.HexToAddress("0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"), *addr) - addr = MumbaiChainConfig.GetBurntContract(22_640_001) + addr = MumbaiChainConfig.GetBurntContract(22640000 + 1) require.NotNil(t, addr) assert.Equal(t, common.HexToAddress("0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"), *addr) - addr = MumbaiChainConfig.GetBurntContract(41_824_607) + addr = MumbaiChainConfig.GetBurntContract(41874000 - 1) require.NotNil(t, addr) assert.Equal(t, common.HexToAddress("0x70bcA57F4579f58670aB2d18Ef16e02C17553C38"), *addr) - addr = MumbaiChainConfig.GetBurntContract(41_824_608) + addr = MumbaiChainConfig.GetBurntContract(41874000) require.NotNil(t, addr) assert.Equal(t, common.HexToAddress("0x617b94CCCC2511808A3C9478ebb96f455CF167aA"), *addr) - addr = MumbaiChainConfig.GetBurntContract(41_824_609) + addr = MumbaiChainConfig.GetBurntContract(41874000 + 1) require.NotNil(t, addr) assert.Equal(t, common.HexToAddress("0x617b94CCCC2511808A3C9478ebb96f455CF167aA"), *addr) } From c90bff7e22337691ca4c41df41a782e805435f46 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Tue, 31 Oct 2023 10:11:40 +0700 Subject: [PATCH 29/44] mdbx: use release tag (#8628) --- erigon-lib/go.mod | 12 +- erigon-lib/go.sum | 299 ++-------------------------------------------- go.mod | 2 +- go.sum | 4 +- 4 files changed, 22 insertions(+), 295 deletions(-) diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index bb94dcd6683..28b3b15b40a 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon-lib go 1.20 require ( - github.com/erigontech/mdbx-go v0.27.19 + github.com/erigontech/mdbx-go v0.27.20 github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3 github.com/ledgerwatch/interfaces v0.0.0-20231011121315-f58b806039f0 github.com/ledgerwatch/log/v3 v3.9.0 @@ -34,9 +34,9 @@ require ( github.com/matryer/moq v0.3.3 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pelletier/go-toml/v2 v2.1.0 - github.com/prometheus/client_golang v1.12.2 - github.com/prometheus/client_model v0.2.0 - github.com/prometheus/common v0.35.0 + github.com/prometheus/client_golang v1.17.0 + github.com/prometheus/client_model v0.5.0 + github.com/prometheus/common v0.44.0 github.com/quasilyte/go-ruleguard/dsl v0.3.22 github.com/spaolacci/murmur3 v1.1.0 github.com/stretchr/testify v1.8.4 @@ -100,7 +100,7 @@ require ( github.com/huandu/xstrings v1.4.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect - github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect + github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mschoch/smat v0.2.0 // indirect github.com/pion/datachannel v1.5.2 // indirect @@ -123,7 +123,7 @@ require ( github.com/pion/webrtc/v3 v3.1.42 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/prometheus/procfs v0.7.3 // indirect + github.com/prometheus/procfs v0.11.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 // indirect github.com/valyala/fastrand v1.1.0 // indirect diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 5c684a43837..739a02fb44d 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -1,42 +1,10 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= -cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= -cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= -cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= -cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= -cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= -cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= -cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= -cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= -cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= -cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= -cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= -cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= -cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= -cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= -cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= -cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= -cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= -cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= -cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= -cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= -cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU= -cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= -cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos= -cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= -cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= -cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= crawshaw.io/iox v0.0.0-20181124134642-c51c3df30797 h1:yDf7ARQc637HoxDho7xjqdvO5ZA2Yb+xzv/fOnnvZzw= crawshaw.io/iox v0.0.0-20181124134642-c51c3df30797/go.mod h1:sXBiorCo8c46JlQV3oXPKINnZ8mcqnye1EkVkqsectk= crawshaw.io/sqlite v0.3.2/go.mod h1:igAO5JulrQ1DbdZdtVq48mnZUBAPOeFzer7VhDWNtW4= -dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= -github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/RoaringBitmap/roaring v0.4.7/go.mod h1:8khRDP4HmeXns4xIj9oGrKSz7XTQiJx2zgh7AcNke4w= github.com/RoaringBitmap/roaring v0.4.17/go.mod h1:D3qVegWTmfCaX4Bl5CrBE9hfrSrrXIr8KVNvRsDi1NI= github.com/RoaringBitmap/roaring v0.4.23/go.mod h1:D0gp8kJQgE1A4LQ5wFLggQEyvDi06Mq5mKs52e1TwOo= @@ -54,7 +22,6 @@ github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuy github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/anacrolix/chansync v0.3.0 h1:lRu9tbeuw3wl+PhMu/r+JJCRu5ArFXIluOgdF0ao6/U= github.com/anacrolix/chansync v0.3.0/go.mod h1:DZsatdsdXxD0WiwcGl0nJVwyjCKMDv+knl1q2iBjA2k= github.com/anacrolix/dht/v2 v2.20.0 h1:eDx9lfE9iCSf5sPK0290GToHURNhEFuUGN8iyvhvJDk= @@ -168,12 +135,8 @@ github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b h1:6+ZFm0flnudZzdS github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b/go.mod h1:S/7n9copUssQ56c7aAgHqftWO4LTf4xY6CGWt8Bc+3M= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= @@ -202,8 +165,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erigontech/mdbx-go v0.27.19 h1:3jugN7wNmVZ4zDk4heLMPAGuOXuCG/0/DfzjlGB48kk= -github.com/erigontech/mdbx-go v0.27.19/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= +github.com/erigontech/mdbx-go v0.27.20 h1:b6nhop/nEtXLR0s8Vu1NvoQeiI6GNRoPVA5YbUPUGU0= +github.com/erigontech/mdbx-go v0.27.20/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -214,13 +177,9 @@ github.com/glycerine/go-unsnap-stream v0.0.0-20190901134440-81cf024a9e0a/go.mod github.com/glycerine/goconvey v0.0.0-20180728074245-46e3a41ad493/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/glycerine/goconvey v0.0.0-20190315024820-982ee783a72e/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24= -github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= -github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0= github.com/go-llsqlite/adapter v0.0.0-20230912124304-94ed0e573c23 h1:7krbnPREaxbmEaAkZovTNCMjmiZXEy/Gz9isFbqFK0I= github.com/go-llsqlite/adapter v0.0.0-20230912124304-94ed0e573c23/go.mod h1:DADrR88ONKPPeSGjFp5iEN55Arx3fi2qXZeKCYDpbmU= github.com/go-llsqlite/crawshaw v0.0.0-20230910110433-7e901377eb6c h1:pm7z8uwA2q3s8fAsJmKuGckNohqIrw2PRtv6yJ6z0Ro= @@ -228,7 +187,6 @@ github.com/go-llsqlite/crawshaw v0.0.0-20230910110433-7e901377eb6c/go.mod h1:UdT github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= -github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= @@ -245,29 +203,18 @@ github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7a github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= -github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y= -github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw= -github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= -github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= -github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= -github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= @@ -275,7 +222,6 @@ github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiu github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180124185431-e89373fe6b4a/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.1.2 h1:xf4v41cLI2Z6FxbKm+8Bu+m8ifhj15JuZ9sa0jZCMUU= github.com/google/btree v1.1.2/go.mod h1:qOPhT0dTNdNzV6Z/lhRX0YXUafgPLFUh+gZMl761Gm4= @@ -283,30 +229,14 @@ github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5a github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= -github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= -github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= -github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= -github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/subcommands v1.2.0/go.mod h1:ZjhPrFU+Olkh9WazFPsl27BQ4UPiG37m3yTrtFlrHVk= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= -github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181103185306-d547d1d9531e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20190309154008-847fc94819f9/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= @@ -318,7 +248,6 @@ github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/ad github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI= github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8= github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= -github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru/v2 v2.0.6 h1:3xi/Cafd1NaoEnS/yDssIiuVeDVywU0QdFGl3aQaQHM= github.com/hashicorp/golang-lru/v2 v2.0.6/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= @@ -332,25 +261,16 @@ github.com/huandu/xstrings v1.3.1/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq github.com/huandu/xstrings v1.3.2/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= github.com/huandu/xstrings v1.4.0 h1:D17IlohoQq4UcpqD7fDk80P7l+lwAmlFaBHgOipl2FU= github.com/huandu/xstrings v1.4.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= -github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk= github.com/jtolds/gls v4.2.1+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= -github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= -github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= @@ -378,8 +298,9 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= +github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mmcloughlin/addchain v0.4.0 h1:SobOdjm2xLj1KkXN5/n0xTIWyZA2+s99UCY1iPfkHRY= github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqkyU72HC5wJ4RlU= github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= @@ -387,12 +308,10 @@ github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg= github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM= github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -466,43 +385,35 @@ github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXP github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_golang v1.5.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= -github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= -github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= -github.com/prometheus/client_golang v1.12.2 h1:51L9cDoUHVrXx4zWYlcLQIZ+d+VXHgqnYKkIuq4g/34= -github.com/prometheus/client_golang v1.12.2/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= +github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= +github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= +github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= -github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= -github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= -github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= -github.com/prometheus/common v0.35.0 h1:Eyr+Pw2VymWejHqCugNaQXkAi6KayVNxaHeu6khmFBE= -github.com/prometheus/common v0.35.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA= +github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= +github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= github.com/prometheus/procfs v0.0.11/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= -github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= -github.com/prometheus/procfs v0.7.3 h1:4jVXhlkAyzOScmCkXBTOLRLTz8EeU+eyjrwB/EPq0VU= -github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= +github.com/prometheus/procfs v0.11.1 h1:xRC8Iq1yyca5ypa9n1EZnWZkt7dwcoRPQwX/5gwaUuI= +github.com/prometheus/procfs v0.11.1/go.mod h1:eesXgaPo1q7lBpVMoMy0ZOFTth9hBn4W/y0/p/ScXhY= github.com/quasilyte/go-ruleguard/dsl v0.3.22 h1:wd8zkOhSNr+I+8Qeciml08ivDt1pSXe60+5DqOpCjPE= github.com/quasilyte/go-ruleguard/dsl v0.3.22/go.mod h1:KeCP03KrjuSO0H1kTuZQCWlQPulDV6YMIXmpQss17rU= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= +github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 h1:Lt9DzQALzHoDwMBGJ6v8ObDPR0dzr2a6sXTB1Fq7IHs= github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417/go.mod h1:qe5TWALJ8/a1Lqznoc5BDHpYX/8HU60Hm2AwRmqzxqA= github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46 h1:GHRpF1pTW19a8tTFrMLUcfWwyC0pnifVo2ClaLq+hP8= @@ -510,7 +421,6 @@ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5P github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= -github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= @@ -544,20 +454,14 @@ github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OL github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY= github.com/willf/bitset v1.1.9/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4= -github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= -go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= -go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= -go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opentelemetry.io/otel v1.8.0 h1:zcvBFizPbpa1q7FehvFiHbQwGzmPILebO0tyqIR5Djg= go.opentelemetry.io/otel v1.8.0/go.mod h1:2pkj+iMj0o03Y+cW6/m8Y4WkRdYN3AvCXCnzRMp9yvM= go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOlHrfY= @@ -568,8 +472,6 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= @@ -580,35 +482,13 @@ golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= -golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= -golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4= -golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM= -golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU= golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g= golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k= -golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= -golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs= -golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= -golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= -golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= -golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY= -golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= -golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= @@ -623,38 +503,18 @@ golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73r golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= -golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= -golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= -golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201201195509-5d6afe98e0b7/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= -golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211201190559-0a0e4e1bb54c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= -golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220401154927-543a649e0bdd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= golang.org/x/net v0.0.0-20220531201128-c960675eff93/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -666,21 +526,13 @@ golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= -golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= @@ -690,48 +542,24 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200413165638-669c56c373c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -749,9 +577,7 @@ golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.1.0/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -761,9 +587,6 @@ golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -771,44 +594,11 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= -golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= -golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= -golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191108193012-7d206e10da11/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= -golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw= -golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8= -golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= -golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= @@ -819,73 +609,22 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= -google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= -google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= -google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= -google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI= -google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE= -google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= -google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= -google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= -google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= -google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= -google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= -google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= -google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA= -google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= -google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U= -google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA= -google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d h1:uvYuEyMHKNt+lT4K3bN6fGswmK8qSvcreM3BwjDh+y4= google.golang.org/genproto/googleapis/rpc v0.0.0-20230822172742-b8732ec3820d/go.mod h1:+Bk1OCOj40wS2hwAMA+aCW9ypzm63QTBBHp6lQ3p+9M= google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= -google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= -google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= -google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk= -google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= -google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.59.0 h1:Z5Iec2pjwb+LEOqzpB2MR12/eKFhDPhuqW91O+4bwUk= google.golang.org/grpc v1.59.0/go.mod h1:aUPDwccQo6OTjy7Hct4AfBPD1GptF4fyUjIkQ9YtF98= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.3.0 h1:rNBFJjBCOgVr9pWD7rs/knKL4FRTKgpZmsRfV214zcA= @@ -895,11 +634,7 @@ google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= -google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= -google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= -google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8= @@ -926,12 +661,7 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= 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= -honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= -honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= -honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= -honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= modernc.org/libc v1.24.1 h1:uvJSeCKL/AgzBo2yYIPPTy82v21KgGnizcGYfBHaNuM= modernc.org/libc v1.24.1/go.mod h1:FmfO1RLrU3MHJfyi9eYYmZBfi/R+tqZ6+hQ3yQQUkak= modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4= @@ -940,9 +670,6 @@ modernc.org/memory v1.6.0 h1:i6mzavxrE9a30whzMfwf7XWVODx2r5OYXvU46cirX7o= modernc.org/memory v1.6.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/sqlite v1.26.0 h1:SocQdLRSYlA8W99V8YH0NES75thx19d9sB/aFc4R8Lw= modernc.org/sqlite v1.26.0/go.mod h1:FL3pVXie73rg3Rii6V/u5BoHlSoyeZeIgKZEgHARyCU= -rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= -rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= -rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= rsc.io/tmplfunc v0.0.3 h1:53XFQh69AfOa8Tw0Jm7t+GV7KZhOi6jzsCzTtKbMvzU= rsc.io/tmplfunc v0.0.3/go.mod h1:AG3sTPzElb1Io3Yg4voV9AGZJuleGAwaVRxL9M49PhA= zombiezen.com/go/sqlite v0.13.1 h1:qDzxyWWmMtSSEH5qxamqBFmqA2BLSSbtODi3ojaE02o= diff --git a/go.mod b/go.mod index 619bd24caac..deca4f5918a 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon go 1.20 require ( - github.com/erigontech/mdbx-go v0.28.1-0.20231027032558-7bc6afaf5e01 + github.com/erigontech/mdbx-go v0.27.20 github.com/ledgerwatch/erigon-lib v1.0.0 github.com/ledgerwatch/log/v3 v3.9.0 github.com/ledgerwatch/secp256k1 v1.0.0 diff --git a/go.sum b/go.sum index 81f8da24712..838eae86eed 100644 --- a/go.sum +++ b/go.sum @@ -284,8 +284,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erigontech/mdbx-go v0.28.1-0.20231027032558-7bc6afaf5e01 h1:KkUQQYMIL2DdpCUIjKVi2dvwUEuo/1oKp9D2BVUIIOY= -github.com/erigontech/mdbx-go v0.28.1-0.20231027032558-7bc6afaf5e01/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= +github.com/erigontech/mdbx-go v0.27.20 h1:b6nhop/nEtXLR0s8Vu1NvoQeiI6GNRoPVA5YbUPUGU0= +github.com/erigontech/mdbx-go v0.27.20/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c h1:CndMRAH4JIwxbW8KYq6Q+cGWcGHz0FjGR3QqcInWcW0= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= From d8d7d8d5df981609f4776febdff0d033927250c9 Mon Sep 17 00:00:00 2001 From: a Date: Tue, 31 Oct 2023 04:14:20 -0500 Subject: [PATCH 30/44] Enable h2c for http handler. add https handler for http2 (#8610) new flag examples. --https.enabled --https.addr="0.0.0.0" --https.port=443 --https.url="unix:///file.wow" --https.cert="keyfile.cert" --https.key="certfile.cert" also adds support for h2c to the http handler - http2 protocol without tls. --- cmd/rpcdaemon/README.md | 16 +++++- cmd/rpcdaemon/cli/config.go | 81 ++++++++++++++++++++------- cmd/rpcdaemon/cli/httpcfg/http_cfg.go | 7 +++ cmd/utils/flags.go | 7 ++- node/endpoints.go | 74 +++++++++++++++++++++++- turbo/cli/default_flags.go | 1 + turbo/cli/flags.go | 8 ++- 7 files changed, 165 insertions(+), 29 deletions(-) diff --git a/cmd/rpcdaemon/README.md b/cmd/rpcdaemon/README.md index 5ee769e25a8..7a275d2ac5b 100644 --- a/cmd/rpcdaemon/README.md +++ b/cmd/rpcdaemon/README.md @@ -194,6 +194,20 @@ If the `--http.url` flag is set, then `--http.addr` and `--http.port` with both note that this is NOT geth-style IPC. for that, read the next section, IPC endpoint(geth-compatible) + +### HTTPS, HTTP2, and H2C + +Erigon supports HTTPS, HTTP2, and H2C out of the box. H2C is served by the default HTTP handler. + +To enable the HTTPS+HTTP2 server, add flag `--https.enabled`, along with providing flags `-https.cert="/path/to.cert"` and `--https.key=/path/to.key` + +By default, the HTTPS server will run on the HTTP port + 363. use flag `--https.port` to set the port + +The HTTPS server will inherit all other configuration parameters from http, for instance, enabling the websocket server, cors domains, or enabled namespaces + +If the `--https.url` flag is set, then `--https.addr` and `--https.port` with both be ignored. + + ### IPC endpoint (geth compatible) erigon supports the geth-style unix socket IPC. you can enable this with `--socket.enabled` flag, @@ -266,7 +280,7 @@ The following table shows the current implementation status of Erigon's RPC daem | eth_getFilterChanges | Yes | | | eth_uninstallFilter | Yes | | | eth_getLogs | Yes | | -| | | | +| interned spe | | | | eth_accounts | No | deprecated | | eth_sendRawTransaction | Yes | `remote`. | | eth_sendTransaction | - | not yet implemented | diff --git a/cmd/rpcdaemon/cli/config.go b/cmd/rpcdaemon/cli/config.go index ea15834adcb..614287a639e 100644 --- a/cmd/rpcdaemon/cli/config.go +++ b/cmd/rpcdaemon/cli/config.go @@ -89,10 +89,6 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) { rootCmd.PersistentFlags().StringVar(&cfg.PrivateApiAddr, "private.api.addr", "127.0.0.1:9090", "Erigon's components (txpool, rpcdaemon, sentry, downloader, ...) can be deployed as independent Processes on same/another server. Then components will connect to erigon by this internal grpc API. Example: 127.0.0.1:9090") rootCmd.PersistentFlags().StringVar(&cfg.DataDir, "datadir", "", "path to Erigon working directory") rootCmd.PersistentFlags().BoolVar(&cfg.GraphQLEnabled, "graphql", false, "enables graphql endpoint (disabled by default)") - rootCmd.PersistentFlags().StringVar(&cfg.HttpListenAddress, "http.addr", nodecfg.DefaultHTTPHost, "HTTP-RPC server listening interface") - rootCmd.PersistentFlags().StringVar(&cfg.TLSCertfile, "tls.cert", "", "certificate for client side TLS handshake") - rootCmd.PersistentFlags().StringVar(&cfg.TLSKeyFile, "tls.key", "", "key file for client side TLS handshake") - rootCmd.PersistentFlags().StringVar(&cfg.TLSCACert, "tls.cacert", "", "CA certificate for client side TLS handshake") rootCmd.PersistentFlags().Uint64Var(&cfg.Gascap, "rpc.gascap", 50_000_000, "Sets a cap on gas that can be used in eth_call/estimateGas") rootCmd.PersistentFlags().Uint64Var(&cfg.MaxTraces, "trace.maxtraces", 200, "Sets a limit on traces that can be returned in trace_filter") @@ -110,17 +106,29 @@ func RootCommand() (*cobra.Command, *httpcfg.HttpCfg) { rootCmd.PersistentFlags().IntVar(&cfg.GRPCPort, "grpc.port", nodecfg.DefaultGRPCPort, "GRPC server listening port") rootCmd.PersistentFlags().BoolVar(&cfg.GRPCHealthCheckEnabled, "grpc.healthcheck", false, "Enable GRPC health check") rootCmd.PersistentFlags().Float64Var(ðconfig.Defaults.RPCTxFeeCap, utils.RPCGlobalTxFeeCapFlag.Name, utils.RPCGlobalTxFeeCapFlag.Value, utils.RPCGlobalTxFeeCapFlag.Usage) + rootCmd.PersistentFlags().StringVar(&cfg.TLSCertfile, "tls.cert", "", "certificate for client side TLS handshake for GRPC") + rootCmd.PersistentFlags().StringVar(&cfg.TLSKeyFile, "tls.key", "", "key file for client side TLS handshake for GRPC") + rootCmd.PersistentFlags().StringVar(&cfg.TLSCACert, "tls.cacert", "", "CA certificate for client side TLS handshake for GRPC") + + rootCmd.PersistentFlags().StringSliceVar(&cfg.API, "http.api", []string{"eth", "erigon"}, "API's offered over the RPC interface: eth,erigon,web3,net,debug,trace,txpool,db. Supported methods: https://github.com/ledgerwatch/erigon/tree/devel/cmd/rpcdaemon") rootCmd.PersistentFlags().BoolVar(&cfg.HttpServerEnabled, "http.enabled", true, "enable http server") + rootCmd.PersistentFlags().StringVar(&cfg.HttpListenAddress, "http.addr", nodecfg.DefaultHTTPHost, "HTTP server listening interface") + rootCmd.PersistentFlags().IntVar(&cfg.HttpPort, "http.port", nodecfg.DefaultHTTPPort, "HTTP server listening port") rootCmd.PersistentFlags().StringVar(&cfg.HttpURL, "http.url", "", "HTTP server listening url. will OVERRIDE http.addr and http.port. will NOT respect http paths. prefix supported are tcp, unix") - rootCmd.PersistentFlags().IntVar(&cfg.HttpPort, "http.port", nodecfg.DefaultHTTPPort, "HTTP-RPC server listening port") rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpCORSDomain, "http.corsdomain", []string{}, "Comma separated list of domains from which to accept cross origin requests (browser enforced)") rootCmd.PersistentFlags().StringSliceVar(&cfg.HttpVirtualHost, "http.vhosts", nodecfg.DefaultConfig.HTTPVirtualHosts, "Comma separated list of virtual hostnames from which to accept requests (server enforced). Accepts '*' wildcard.") rootCmd.PersistentFlags().BoolVar(&cfg.HttpCompression, "http.compression", true, "Disable http compression") - rootCmd.PersistentFlags().StringSliceVar(&cfg.API, "http.api", []string{"eth", "erigon"}, "API's offered over the HTTP-RPC interface: eth,erigon,web3,net,debug,trace,txpool,db. Supported methods: https://github.com/ledgerwatch/erigon/tree/devel/cmd/rpcdaemon") - rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets - Same port as HTTP") + rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketEnabled, "ws", false, "Enable Websockets - Same port as HTTP[S]") rootCmd.PersistentFlags().BoolVar(&cfg.WebsocketCompression, "ws.compression", false, "Enable Websocket compression (RFC 7692)") + rootCmd.PersistentFlags().BoolVar(&cfg.HttpsServerEnabled, "https.enabled", false, "enable http server") + rootCmd.PersistentFlags().StringVar(&cfg.HttpsListenAddress, "https.addr", nodecfg.DefaultHTTPHost, "rpc HTTPS server listening interface") + rootCmd.PersistentFlags().IntVar(&cfg.HttpsPort, "https.port", 0, "rpc HTTPS server listening port. default to http+363 if not set") + rootCmd.PersistentFlags().StringVar(&cfg.HttpsURL, "https.url", "", "rpc HTTPS server listening url. will OVERRIDE https.addr and https.port. will NOT respect paths. prefix supported are tcp, unix") + rootCmd.PersistentFlags().StringVar(&cfg.HttpsCertfile, "https.cert", "", "certificate for rpc HTTPS server") + rootCmd.PersistentFlags().StringVar(&cfg.HttpsKeyFile, "https.key", "", "key file for rpc HTTPS server") + rootCmd.PersistentFlags().BoolVar(&cfg.SocketServerEnabled, "socket.enabled", false, "Enable IPC server") rootCmd.PersistentFlags().StringVar(&cfg.SocketListenUrl, "socket.url", "unix:///var/run/erigon.sock", "IPC server listening url. prefix supported are tcp, unix") @@ -610,24 +618,25 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp logger.Info("Socket Endpoint opened", "url", socketUrl) } - if cfg.HttpServerEnabled { - httpHandler := node.NewHTTPHandlerStack(srv, cfg.HttpCORSDomain, cfg.HttpVirtualHost, cfg.HttpCompression) - var wsHandler http.Handler - if cfg.WebsocketEnabled { - wsHandler = srv.WebsocketHandler([]string{"*"}, nil, cfg.WebsocketCompression, logger) - } - - graphQLHandler := graphql.CreateHandler(defaultAPIList) + httpHandler := node.NewHTTPHandlerStack(srv, cfg.HttpCORSDomain, cfg.HttpVirtualHost, cfg.HttpCompression) + var wsHandler http.Handler + if cfg.WebsocketEnabled { + wsHandler = srv.WebsocketHandler([]string{"*"}, nil, cfg.WebsocketCompression, logger) + } + graphQLHandler := graphql.CreateHandler(defaultAPIList) + apiHandler, err := createHandler(cfg, defaultAPIList, httpHandler, wsHandler, graphQLHandler, nil) + if err != nil { + return err + } - apiHandler, err := createHandler(cfg, defaultAPIList, httpHandler, wsHandler, graphQLHandler, nil) - if err != nil { - return err - } + if cfg.HttpServerEnabled { httpEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.HttpListenAddress, cfg.HttpPort) if cfg.HttpURL != "" { httpEndpoint = cfg.HttpURL } - listener, httpAddr, err := node.StartHTTPEndpoint(httpEndpoint, cfg.HTTPTimeouts, apiHandler) + listener, httpAddr, err := node.StartHTTPEndpoint(httpEndpoint, &node.HttpEndpointConfig{ + Timeouts: cfg.HTTPTimeouts, + }, apiHandler) if err != nil { return fmt.Errorf("could not start RPC api: %w", err) } @@ -639,6 +648,34 @@ func startRegularRpcServer(ctx context.Context, cfg httpcfg.HttpCfg, rpcAPI []rp logger.Info("HTTP endpoint closed", "url", httpAddr) }() } + if cfg.HttpsURL != "" { + cfg.HttpsServerEnabled = true + } + if cfg.HttpsServerEnabled { + if cfg.HttpsPort == 0 { + cfg.HttpsPort = cfg.HttpPort + 363 + } + httpsEndpoint := fmt.Sprintf("tcp://%s:%d", cfg.HttpsListenAddress, cfg.HttpsPort) + if cfg.HttpsURL != "" { + httpsEndpoint = cfg.HttpsURL + } + listener, httpAddr, err := node.StartHTTPEndpoint(httpsEndpoint, &node.HttpEndpointConfig{ + Timeouts: cfg.HTTPTimeouts, + HTTPS: true, + CertFile: cfg.HttpsCertfile, + KeyFile: cfg.HttpsKeyFile, + }, apiHandler) + if err != nil { + return fmt.Errorf("could not start RPC api: %w", err) + } + info = append(info, "https.url", httpAddr) + defer func() { + shutdownCtx, cancel := context.WithTimeout(context.Background(), 5*time.Second) + defer cancel() + _ = listener.Shutdown(shutdownCtx) + logger.Info("HTTPS endpoint closed", "url", httpAddr) + }() + } var ( healthServer *grpcHealth.Server @@ -797,7 +834,9 @@ func createEngineListener(cfg httpcfg.HttpCfg, engineApi []rpc.API, logger log.L return nil, nil, "", err } - engineListener, engineAddr, err := node.StartHTTPEndpoint(engineHttpEndpoint, cfg.AuthRpcTimeouts, engineApiHandler) + engineListener, engineAddr, err := node.StartHTTPEndpoint(engineHttpEndpoint, &node.HttpEndpointConfig{ + Timeouts: cfg.AuthRpcTimeouts, + }, engineApiHandler) if err != nil { return nil, nil, "", fmt.Errorf("could not start RPC api: %w", err) } diff --git a/cmd/rpcdaemon/cli/httpcfg/http_cfg.go b/cmd/rpcdaemon/cli/httpcfg/http_cfg.go index 408d3f82d90..b2b2a99d091 100644 --- a/cmd/rpcdaemon/cli/httpcfg/http_cfg.go +++ b/cmd/rpcdaemon/cli/httpcfg/http_cfg.go @@ -30,6 +30,13 @@ type HttpCfg struct { AuthRpcVirtualHost []string HttpCompression bool + HttpsServerEnabled bool + HttpsURL string + HttpsListenAddress string + HttpsPort int + HttpsCertfile string + HttpsKeyFile string + AuthRpcPort int PrivateApiAddr string diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 95ccca55945..e1e1164b0e0 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -305,7 +305,12 @@ var ( } HTTPEnabledFlag = cli.BoolFlag{ Name: "http", - Usage: "HTTP-RPC server (enabled by default). Use --http=false to disable it", + Usage: "JSON-RPC server (enabled by default). Use --http=false to disable it", + Value: true, + } + HTTPServerEnabledFlag = cli.BoolFlag{ + Name: "http.enabled", + Usage: "JSON-RPC HTTP server (enabled by default). Use --http.enabled=false to disable it", Value: true, } HTTPListenAddrFlag = cli.StringFlag{ diff --git a/node/endpoints.go b/node/endpoints.go index 8ca2e1696a2..5a2a1051735 100644 --- a/node/endpoints.go +++ b/node/endpoints.go @@ -29,10 +29,73 @@ import ( "github.com/ledgerwatch/erigon/rpc" "github.com/ledgerwatch/erigon/rpc/rpccfg" "github.com/ledgerwatch/log/v3" + "golang.org/x/net/http2" + "golang.org/x/net/http2/h2c" ) +type HttpEndpointConfig struct { + Timeouts rpccfg.HTTPTimeouts + HTTPS bool + CertFile string + KeyFile string +} + +// StartHTTPEndpoint starts the HTTP RPC endpoint. +func StartHTTPEndpoint(urlEndpoint string, cfg *HttpEndpointConfig, handler http.Handler) (*http.Server, net.Addr, error) { + // start the HTTP listener + var ( + listener net.Listener + err error + ) + socketUrl, err := url.Parse(urlEndpoint) + if err != nil { + return nil, nil, fmt.Errorf("malformatted http listen url %s: %w", urlEndpoint, err) + } + if listener, err = net.Listen(socketUrl.Scheme, socketUrl.Host+socketUrl.EscapedPath()); err != nil { + return nil, nil, err + } + // make sure timeout values are meaningful + CheckTimeouts(&cfg.Timeouts) + // create the http2 server for handling h2c + h2 := &http2.Server{} + // enable h2c support + handler = h2c.NewHandler(handler, h2) + // Bundle the http server + httpSrv := &http.Server{ + Handler: handler, + ReadTimeout: cfg.Timeouts.ReadTimeout, + WriteTimeout: cfg.Timeouts.WriteTimeout, + IdleTimeout: cfg.Timeouts.IdleTimeout, + ReadHeaderTimeout: cfg.Timeouts.ReadTimeout, + } + // start the HTTP server + go func() { + var serveErr error + if cfg.HTTPS { + serveErr = httpSrv.ServeTLS(listener, cfg.CertFile, cfg.KeyFile) + if serveErr != nil && !isIgnoredHttpServerError(serveErr) { + log.Warn("Failed to serve https endpoint", "err", serveErr) + } + } else { + serveErr = httpSrv.Serve(listener) + if serveErr != nil && !isIgnoredHttpServerError(serveErr) { + log.Warn("Failed to serve http endpoint", "err", serveErr) + } + } + }() + return httpSrv, listener.Addr(), err +} + +func isIgnoredHttpServerError(serveErr error) bool { + return (errors.Is(serveErr, context.Canceled) || errors.Is(serveErr, libcommon.ErrStopped) || errors.Is(serveErr, http.ErrServerClosed)) + +} + // StartHTTPEndpoint starts the HTTP RPC endpoint. -func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler http.Handler) (*http.Server, net.Addr, error) { +func StartHTTPSEndpoint(urlEndpoint string, + keyFile string, certFile string, + timeouts rpccfg.HTTPTimeouts, handler http.Handler, +) (*http.Server, net.Addr, error) { // start the HTTP listener var ( listener net.Listener @@ -47,7 +110,11 @@ func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler } // make sure timeout values are meaningful CheckTimeouts(&timeouts) - // Bundle and start the HTTP server + // create the http2 server for handling h2c + h2 := &http2.Server{} + // enable h2c support + handler = h2c.NewHandler(handler, h2) + // Bundle the http server httpSrv := &http.Server{ Handler: handler, ReadTimeout: timeouts.ReadTimeout, @@ -55,8 +122,9 @@ func StartHTTPEndpoint(urlEndpoint string, timeouts rpccfg.HTTPTimeouts, handler IdleTimeout: timeouts.IdleTimeout, ReadHeaderTimeout: timeouts.ReadTimeout, } + // start the HTTP server go func() { - serveErr := httpSrv.Serve(listener) + serveErr := httpSrv.ServeTLS(listener, certFile, keyFile) if serveErr != nil && !(errors.Is(serveErr, context.Canceled) || errors.Is(serveErr, libcommon.ErrStopped) || errors.Is(serveErr, http.ErrServerClosed)) { log.Warn("Failed to serve http endpoint", "err", serveErr) diff --git a/turbo/cli/default_flags.go b/turbo/cli/default_flags.go index 40fad68e151..978b96d974b 100644 --- a/turbo/cli/default_flags.go +++ b/turbo/cli/default_flags.go @@ -51,6 +51,7 @@ var DefaultFlags = []cli.Flag{ &BadBlockFlag, &utils.HTTPEnabledFlag, + &utils.HTTPServerEnabledFlag, &utils.GraphQLEnabledFlag, &utils.HTTPListenAddrFlag, &utils.HTTPPortFlag, diff --git a/turbo/cli/flags.go b/turbo/cli/flags.go index 43a903f0ad5..80bd6210f42 100644 --- a/turbo/cli/flags.go +++ b/turbo/cli/flags.go @@ -2,9 +2,10 @@ package cli import ( "fmt" - "github.com/ledgerwatch/erigon-lib/common/hexutil" "time" + "github.com/ledgerwatch/erigon-lib/common/hexutil" + "github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg" libcommon "github.com/ledgerwatch/erigon-lib/common" @@ -356,8 +357,9 @@ func setEmbeddedRpcDaemon(ctx *cli.Context, cfg *nodecfg.Config, logger log.Logg logger.Info("starting HTTP APIs", "APIs", apis) c := &httpcfg.HttpCfg{ - Enabled: ctx.Bool(utils.HTTPEnabledFlag.Name), - Dirs: cfg.Dirs, + Enabled: ctx.Bool(utils.HTTPEnabledFlag.Name), + HttpServerEnabled: ctx.Bool(utils.HTTPServerEnabledFlag.Name), + Dirs: cfg.Dirs, TLSKeyFile: cfg.TLSKeyFile, TLSCACert: cfg.TLSCACert, From cabd2b21ddfa1c10c30ab4e38aa7c403a82ec1fe Mon Sep 17 00:00:00 2001 From: Andrew Ashikhmin <34320705+yperbasis@users.noreply.github.com> Date: Tue, 31 Oct 2023 10:35:53 +0100 Subject: [PATCH 31/44] Mumbai: fix fork ID for Agra (#8630) otherwise we start losing maticnetwork/bor peers on devp2p --- core/forkid/forkid.go | 4 ++++ core/forkid/forkid_test.go | 12 ++++++++++++ 2 files changed, 16 insertions(+) diff --git a/core/forkid/forkid.go b/core/forkid/forkid.go index 8af0ca34a08..433c9221b18 100644 --- a/core/forkid/forkid.go +++ b/core/forkid/forkid.go @@ -244,6 +244,10 @@ func GatherForks(config *chain.Config, genesisTime uint64) (heightForks []uint64 heightForks = append(heightForks, *config.Aura.PosdaoTransition) } + if config.Bor != nil && config.Bor.AgraBlock != nil { + heightForks = append(heightForks, config.Bor.AgraBlock.Uint64()) + } + // Sort the fork block numbers & times to permit chronological XOR slices.Sort(heightForks) slices.Sort(timeForks) diff --git a/core/forkid/forkid_test.go b/core/forkid/forkid_test.go index 45dd5bcf3f1..5355436193c 100644 --- a/core/forkid/forkid_test.go +++ b/core/forkid/forkid_test.go @@ -141,6 +141,18 @@ func TestCreation(t *testing.T) { {4100419, 1684934220, ID{Hash: checksumToBytes(0xa15a4252), Next: 0}}, // First Shanghai block }, }, + // Mumbai test cases + { + params.MumbaiChainConfig, + params.MumbaiGenesisHash, + []testcase{ + {0, 0, ID{Hash: checksumToBytes(0xf6ef3fdf), Next: 2722000}}, + {2722000, 0, ID{Hash: checksumToBytes(0x8647df30), Next: 13996000}}, // First Istanbul block + {13996000, 0, ID{Hash: checksumToBytes(0x06cc1179), Next: 22640000}}, // First Berlin block + {22640000, 0, ID{Hash: checksumToBytes(0x9adf950e), Next: 41874000}}, // First London block + {41874000, 0, ID{Hash: checksumToBytes(0x0c015a91), Next: 0}}, // First Agra block + }, + }, } for i, tt := range tests { for j, ttt := range tt.cases { From c20af7d985ab69028bdd6c4fa54fc42d739e1de7 Mon Sep 17 00:00:00 2001 From: Mark Holt <135143369+mh0lt@users.noreply.github.com> Date: Tue, 31 Oct 2023 18:43:23 +0000 Subject: [PATCH 32/44] Add code to handle close/cancel semantics (#8633) --- erigon-lib/diagnostics/provider.go | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/erigon-lib/diagnostics/provider.go b/erigon-lib/diagnostics/provider.go index 2d80e13f473..c1c2ae756c7 100644 --- a/erigon-lib/diagnostics/provider.go +++ b/erigon-lib/diagnostics/provider.go @@ -2,6 +2,7 @@ package diagnostics import ( "context" + "errors" "fmt" "reflect" "sync" @@ -98,7 +99,9 @@ func startProvider(ctx context.Context, infoType Type, provider Provider, logger }() if err := provider.StartDiagnostics(ctx); err != nil { - logger.Warn("Diagnostic provider failed", "type", infoType, "err", err) + if !errors.Is(err, context.Canceled) { + logger.Warn("Diagnostic provider failed", "type", infoType, "err", err) + } } } @@ -109,7 +112,12 @@ func Send[I Info](ctx context.Context, info I) error { cval := ctx.Value(ckChan) if c, ok := cval.(chan I); ok { - c <- info + select { + case c <- info: + default: + // drop the diagnostic message if the receiver is busy + // so the sender is not blocked on non critcal actions + } } else { return fmt.Errorf("unexpected channel type: %T", cval) } @@ -123,7 +131,11 @@ func Context[I Info](ctx context.Context, buffer int) (context.Context, <-chan I ctx, cancel := context.WithCancel(ctx) return ctx, ch, func() { - close(ch) + if ch != nil { + toClose := ch + ch = nil + close(toClose) + } cancel() } } From eb65ffbaa70d3c163cf987390052889a29cf0533 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Wed, 1 Nov 2023 03:02:34 +0100 Subject: [PATCH 33/44] config: avoid OOM in docker using cgroups v2 limit (#6646) (#8632) Tested on Debian 11 by: $ git revert HEAD $ make docker $ docker run --memory=8.8G before the fix outputs: 15.6 GB after the fix outputs: 8.8 GB --- erigon-lib/go.mod | 7 ++ erigon-lib/go.sum | 16 +++ erigon-lib/mmap/total_memory.go | 21 ++++ erigon-lib/mmap/total_memory_cgroups.go | 117 +++++++++++++++++++ erigon-lib/mmap/total_memory_cgroups_stub.go | 11 ++ eth/ethconfig/estimate/esitmated_ram.go | 41 +------ go.mod | 13 +-- go.sum | 30 ++--- 8 files changed, 187 insertions(+), 69 deletions(-) create mode 100644 erigon-lib/mmap/total_memory.go create mode 100644 erigon-lib/mmap/total_memory_cgroups.go create mode 100644 erigon-lib/mmap/total_memory_cgroups_stub.go diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index 28b3b15b40a..337752a61f8 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -22,6 +22,7 @@ require ( github.com/aws/aws-sdk-go-v2/credentials v1.13.43 github.com/aws/aws-sdk-go-v2/service/s3 v1.40.2 github.com/c2h5oh/datasize v0.0.0-20220606134207-859f65c6625b + github.com/containerd/cgroups/v3 v3.0.2 github.com/crate-crypto/go-kzg-4844 v0.7.0 github.com/deckarep/golang-set/v2 v2.3.1 github.com/edsrzf/mmap-go v1.1.0 @@ -86,14 +87,18 @@ require ( github.com/bits-and-blooms/bitset v1.7.0 // indirect github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cilium/ebpf v0.9.1 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/consensys/gnark-crypto v0.12.0 // indirect + github.com/coreos/go-systemd/v22 v22.3.2 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/docker/go-units v0.4.0 // indirect github.com/dustin/go-humanize v1.0.1 // indirect github.com/go-llsqlite/adapter v0.0.0-20230912124304-94ed0e573c23 // indirect github.com/go-llsqlite/crawshaw v0.0.0-20230910110433-7e901377eb6c // indirect github.com/go-logr/logr v1.2.3 // indirect github.com/go-logr/stdr v1.2.2 // indirect + github.com/godbus/dbus/v5 v5.0.4 // indirect github.com/golang/protobuf v1.5.3 // indirect github.com/google/uuid v1.3.1 // indirect github.com/gorilla/websocket v1.5.0 // indirect @@ -103,6 +108,7 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/mschoch/smat v0.2.0 // indirect + github.com/opencontainers/runtime-spec v1.0.2 // indirect github.com/pion/datachannel v1.5.2 // indirect github.com/pion/dtls/v2 v2.2.4 // indirect github.com/pion/ice/v2 v2.2.6 // indirect @@ -126,6 +132,7 @@ require ( github.com/prometheus/procfs v0.11.1 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/valyala/fastrand v1.1.0 // indirect github.com/valyala/histogram v1.2.0 // indirect go.etcd.io/bbolt v1.3.6 // indirect diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 739a02fb44d..8b38439c3b1 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -137,12 +137,18 @@ github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= +github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/YjhQ= github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.0 h1:1OnSpOykNkUIBIBJKdhwy2p0JlW5o+Az02ICzZmvvdg= github.com/consensys/gnark-crypto v0.12.0/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= +github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= +github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= +github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI= +github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXkYxeOi8ZF1sYioxhc= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= @@ -151,6 +157,8 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/deckarep/golang-set/v2 v2.3.1 h1:vjmkvJt/IV27WXPyYQpAh4bRyWJc5Y435D17XQ9QU5A= github.com/deckarep/golang-set/v2 v2.3.1/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4= +github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= +github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20180421182945-02af3965c54e/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -196,6 +204,8 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw= github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= +github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA= +github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= @@ -323,6 +333,8 @@ github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= +github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0= +github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= @@ -421,6 +433,8 @@ github.com/ryszard/goskiplist v0.0.0-20150312221310-2dfbae5fcf46/go.mod h1:uAQ5P github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZKJ48R1S7H23Ji7oFO5Bw= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= @@ -468,6 +482,7 @@ go.opentelemetry.io/otel/trace v1.8.0 h1:cSy0DF9eGI5WIfNwZ1q2iUyGj00tGzP24dE1lOl go.opentelemetry.io/otel/trace v1.8.0/go.mod h1:0Bt3PXY8w+3pheS3hQUt+wow8b1ojPaTBoTCh2zIFI4= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.10/go.mod h1:8a7PlsEVH3e/a/GLqe5IIrQx6GzcnRmZEufDUTk4A7A= +go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.18.1/go.mod h1:xg/QME4nWcxGxrpdeYfq7UvYrLh66cuVKdrbD1XF/NI= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -562,6 +577,7 @@ golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= diff --git a/erigon-lib/mmap/total_memory.go b/erigon-lib/mmap/total_memory.go new file mode 100644 index 00000000000..33eca4ea38a --- /dev/null +++ b/erigon-lib/mmap/total_memory.go @@ -0,0 +1,21 @@ +package mmap + +import ( + "github.com/ledgerwatch/erigon-lib/common/cmp" + "github.com/pbnjay/memory" + "runtime/debug" +) + +func TotalMemory() uint64 { + mem := memory.TotalMemory() + + if cgroupsMemLimit, err := cgroupsMemoryLimit(); (err == nil) && (cgroupsMemLimit > 0) { + mem = cmp.Min(mem, cgroupsMemLimit) + } + + if goMemLimit := debug.SetMemoryLimit(-1); goMemLimit > 0 { + mem = cmp.Min(mem, uint64(goMemLimit)) + } + + return mem +} diff --git a/erigon-lib/mmap/total_memory_cgroups.go b/erigon-lib/mmap/total_memory_cgroups.go new file mode 100644 index 00000000000..696a1f89e8f --- /dev/null +++ b/erigon-lib/mmap/total_memory_cgroups.go @@ -0,0 +1,117 @@ +//go:build linux + +/* +https://github.com/raulk/go-watchdog +https://github.com/elee1766/go-watchdog + +The MIT License (MIT) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +*/ + +package mmap + +import ( + "errors" + "fmt" + "github.com/containerd/cgroups/v3" + "github.com/containerd/cgroups/v3/cgroup1" + "github.com/containerd/cgroups/v3/cgroup2" + "os" +) + +// cgroupsMemoryLimit will try to discover +// the memory limit from the cgroup of the process (derived from /proc/self/cgroup), +// or from the root cgroup path if the PID == 1 (which indicates that the process +// is running in a container). +// +// Memory usage is calculated by querying the cgroup stats. +// +// This function will return an error immediately if the OS does not support cgroups, +// or if another error occurs during initialization. +func cgroupsMemoryLimit() (uint64, error) { + switch cgroups.Mode() { + case cgroups.Unified: + return cgroupsV2MemoryLimit() + case cgroups.Legacy: + return cgroupsV1MemoryLimit() + case cgroups.Unavailable: + fallthrough + default: + return 0, errors.New("cgroups not supported in this environment") + } +} + +func cgroupsV1MemoryLimit() (uint64, error) { + // use self path unless our PID is 1, in which case we're running inside + // a container and our limits are in the root path. + path := cgroup1.NestedPath("") + if pid := os.Getpid(); pid == 1 { + path = cgroup1.RootPath + } + + cgroup, err := cgroup1.Load(path, cgroup1.WithHiearchy(func() ([]cgroup1.Subsystem, error) { + system, err := cgroup1.Default() + if err != nil { + return nil, err + } + var out []cgroup1.Subsystem + for _, v := range system { + switch v.Name() { + case cgroup1.Memory: + out = append(out, v) + } + } + return out, nil + })) + if err != nil { + return 0, fmt.Errorf("failed to load cgroup1 for process: %w", err) + } + + if stat, err := cgroup.Stat(); err != nil { + return 0, fmt.Errorf("failed to load memory cgroup1 stats: %w", err) + } else if stat.Memory == nil || stat.Memory.Usage == nil { + return 0, fmt.Errorf("cgroup1 memory stats are nil; aborting") + } else { + return stat.Memory.Usage.Limit, nil + } +} + +func cgroupsV2MemoryLimit() (uint64, error) { + // use self path unless our PID is 1, in which case we're running inside + // a container and our limits are in the root path. + pid := os.Getpid() + path, err := cgroup2.PidGroupPath(pid) + if err != nil { + return 0, fmt.Errorf("failed to load cgroup2 path for process pid %d: %w", pid, err) + } + + cgroup, err := cgroup2.Load(path) + if err != nil { + return 0, fmt.Errorf("failed to load cgroup2 for process: %w", err) + } + + if stat, err := cgroup.Stat(); err != nil { + return 0, fmt.Errorf("failed to load cgroup2 memory stats: %w", err) + } else if stat.Memory == nil { + return 0, fmt.Errorf("cgroup2 memory stats are nil; aborting") + } else { + return stat.Memory.UsageLimit, nil + } +} diff --git a/erigon-lib/mmap/total_memory_cgroups_stub.go b/erigon-lib/mmap/total_memory_cgroups_stub.go new file mode 100644 index 00000000000..0d921aa905b --- /dev/null +++ b/erigon-lib/mmap/total_memory_cgroups_stub.go @@ -0,0 +1,11 @@ +//go:build !linux + +package mmap + +import ( + "errors" +) + +func cgroupsMemoryLimit() (uint64, error) { + return 0, errors.New("cgroups not supported in this environment") +} diff --git a/eth/ethconfig/estimate/esitmated_ram.go b/eth/ethconfig/estimate/esitmated_ram.go index 0eeb3f0622e..cc8bd0bbb94 100644 --- a/eth/ethconfig/estimate/esitmated_ram.go +++ b/eth/ethconfig/estimate/esitmated_ram.go @@ -1,14 +1,10 @@ package estimate import ( - "os" - "runtime" - "runtime/debug" - "github.com/c2h5oh/datasize" "github.com/ledgerwatch/erigon-lib/common/cmp" - "github.com/pbnjay/memory" - "github.com/shirou/gopsutil/v3/docker" + "github.com/ledgerwatch/erigon-lib/mmap" + "runtime" ) type estimatedRamPerWorker datasize.ByteSize @@ -16,9 +12,10 @@ type estimatedRamPerWorker datasize.ByteSize // Workers - return max workers amount based on total Memory/CPU's and estimated RAM per worker func (r estimatedRamPerWorker) Workers() int { // 50% of TotalMemory. Better don't count on 100% because OOM Killer may have aggressive defaults and other software may need RAM - maxWorkersForGivenMemory := (totalMemory() / 2) / uint64(r) + maxWorkersForGivenMemory := (mmap.TotalMemory() / 2) / uint64(r) return cmp.Min(AlmostAllCPUs(), int(maxWorkersForGivenMemory)) } + func (r estimatedRamPerWorker) WorkersHalf() int { return cmp.Max(1, r.Workers()/2) } func (r estimatedRamPerWorker) WorkersQuarter() int { return cmp.Max(1, r.Workers()/4) } @@ -33,33 +30,3 @@ const ( func AlmostAllCPUs() int { return cmp.Max(1, runtime.GOMAXPROCS(-1)-1) } -func totalMemory() uint64 { - mem := memory.TotalMemory() - - if cgroupsMemLimit, ok := cgroupsMemoryLimit(); ok { - mem = cmp.Min(mem, cgroupsMemLimit) - } - - if goMemLimit := debug.SetMemoryLimit(-1); goMemLimit > 0 { - mem = cmp.Min(mem, uint64(goMemLimit)) - } - - return mem -} - -// apply limit from docker if can, treat errors as "not available or maybe non-docker environment -// supports only cgroups v1, for v2 see: https://github.com/shirou/gopsutil/issues/1416 -func cgroupsMemoryLimit() (mem uint64, ok bool) { - hostname, err := os.Hostname() - if err != nil { - return 0, false - } - cgmem, err := docker.CgroupMemDocker(hostname) - if err != nil { - return 0, false - } - if cgmem == nil || cgmem.MemLimitInBytes <= 0 { - return 0, false - } - return cgmem.MemLimitInBytes, true -} diff --git a/go.mod b/go.mod index deca4f5918a..6e12207b6b3 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,6 @@ require ( github.com/maticnetwork/polyproto v0.0.3-0.20230216113155-340ea926ca53 github.com/multiformats/go-multiaddr v0.11.0 github.com/nxadm/tail v1.4.9-0.20211216163028-4472660a31a6 - github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pelletier/go-toml v1.9.5 github.com/pelletier/go-toml/v2 v2.1.0 github.com/pierrec/lz4 v2.6.1+incompatible @@ -74,7 +73,6 @@ require ( github.com/prysmaticlabs/gohashtree v0.0.3-alpha.0.20230502123415-aafd8b3ca202 github.com/quasilyte/go-ruleguard/dsl v0.3.22 github.com/rs/cors v1.10.1 - github.com/shirou/gopsutil/v3 v3.23.8 github.com/spf13/afero v1.9.5 github.com/spf13/cobra v1.7.0 github.com/spf13/pflag v1.0.5 @@ -148,8 +146,10 @@ require ( github.com/bradfitz/iter v0.0.0-20191230175014-e8f45d346db8 // indirect github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect + github.com/cilium/ebpf v0.9.1 // indirect github.com/consensys/bavard v0.1.13 // indirect github.com/containerd/cgroups v1.1.0 // indirect + github.com/containerd/cgroups/v3 v3.0.2 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect @@ -166,7 +166,6 @@ require ( github.com/go-llsqlite/crawshaw v0.0.0-20230910110433-7e901377eb6c // indirect github.com/go-logr/logr v1.2.4 // indirect github.com/go-logr/stdr v1.2.2 // indirect - github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect github.com/go-stack/stack v1.8.1 // indirect github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect @@ -198,7 +197,6 @@ require ( github.com/libp2p/go-netroute v0.2.1 // indirect github.com/libp2p/go-reuseport v0.4.0 // indirect github.com/libp2p/go-yamux/v4 v4.0.1 // indirect - github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect @@ -225,6 +223,7 @@ require ( github.com/multiformats/go-varint v0.0.7 // indirect github.com/onsi/ginkgo/v2 v2.11.0 // indirect github.com/opencontainers/runtime-spec v1.1.0 // indirect + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect github.com/pion/datachannel v1.5.2 // indirect github.com/pion/dtls/v2 v2.2.7 // indirect github.com/pion/ice/v2 v2.2.6 // indirect @@ -242,7 +241,6 @@ require ( github.com/pion/webrtc/v3 v3.1.42 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_golang v1.17.0 // indirect github.com/prometheus/client_model v0.5.0 // indirect github.com/prometheus/common v0.44.0 // indirect @@ -257,15 +255,12 @@ require ( github.com/rogpeppe/go-internal v1.10.0 // indirect github.com/rs/dnscache v0.0.0-20211102005908-e0241e321417 // indirect github.com/russross/blackfriday/v2 v2.1.0 // indirect - github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/sirupsen/logrus v1.9.0 // indirect github.com/spaolacci/murmur3 v1.1.0 // indirect github.com/supranational/blst v0.3.11 // indirect - github.com/tklauser/go-sysconf v0.3.12 // indirect - github.com/tklauser/numcpus v0.6.1 // indirect github.com/valyala/fastrand v1.1.0 // indirect github.com/valyala/histogram v1.2.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - github.com/yusufpapurcu/wmi v1.2.3 // indirect go.etcd.io/bbolt v1.3.6 // indirect go.opentelemetry.io/otel v1.8.0 // indirect go.opentelemetry.io/otel/trace v1.8.0 // indirect diff --git a/go.sum b/go.sum index 838eae86eed..f0e77298c9e 100644 --- a/go.sum +++ b/go.sum @@ -215,6 +215,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= +github.com/cilium/ebpf v0.9.1 h1:64sn2K3UKw8NbP/blsixRpF3nXuyhz/VjRlRzvlBRu4= +github.com/cilium/ebpf v0.9.1/go.mod h1:+OhNOIXx/Fnu1IE8bJz2dzOA+VSfyTfdNUVdlQnxUFY= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -226,6 +228,8 @@ github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5U github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= +github.com/containerd/cgroups/v3 v3.0.2 h1:f5WFqIVSgo5IZmtTT3qVBo6TzI1ON6sycSBKkymb9L0= +github.com/containerd/cgroups/v3 v3.0.2/go.mod h1:JUgITrzdFqp42uI2ryGA+ge0ap/nxzYgkGmIcetmErE= github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -333,8 +337,6 @@ github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU= github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= @@ -410,10 +412,8 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ= github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -574,8 +574,6 @@ github.com/libp2p/go-reuseport v0.4.0 h1:nR5KU7hD0WxXCJbmw7r2rhRYruNRl2koHw8fQsc github.com/libp2p/go-reuseport v0.4.0/go.mod h1:ZtI03j/wO5hZVDFo2jKywN6bYKWLOy8Se6DrI2E1cLU= github.com/libp2p/go-yamux/v4 v4.0.1 h1:FfDR4S1wj6Bw2Pqbc8Uz7pCxeRBPbwsBbEdfwiCypkQ= github.com/libp2p/go-yamux/v4 v4.0.1/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= -github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk= @@ -739,8 +737,6 @@ github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdL github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= -github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= @@ -812,12 +808,6 @@ github.com/sclevine/agouti v3.0.0+incompatible/go.mod h1:b4WX9W9L1sfQKXeJf1mUTLZ github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8= github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I= -github.com/shirou/gopsutil/v3 v3.23.8 h1:xnATPiybo6GgdRoC4YoGnxXZFRc3dqQTGi73oLvvBrE= -github.com/shirou/gopsutil/v3 v3.23.8/go.mod h1:7hmCaBn+2ZwaZOr6jmPBZDfawwMGuo1id3C6aM8EDqQ= -github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= -github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= -github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= -github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= @@ -844,6 +834,8 @@ github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5k github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v0.0.0-20190215210624-980c5ac6f3ac/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v0.0.0-20181108003508-044398e4856c/go.mod h1:XDJAKZRPZ1CvBcN2aX5YOUTYGHki24fSF0Iv48Ibg0s= @@ -885,10 +877,6 @@ github.com/tidwall/btree v1.6.0/go.mod h1:twD9XRA5jj9VUQGELzDO4HPQTNJsoWWfYEL+EU github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.0/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= github.com/tinylib/msgp v1.1.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE= -github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= -github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= -github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= -github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc= github.com/ugorji/go/codec v1.1.13 h1:013LbFhocBoIqgHeIHKlV4JWYhqogATYWZhIcH0WHn4= github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU= @@ -919,8 +907,6 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw= -github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU= go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4= go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA= @@ -1115,7 +1101,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1144,7 +1129,6 @@ golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1162,13 +1146,13 @@ golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220608164250-635b8c9b7f68/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= From 22332f72eb9c9b8b0a9b217ef49822fbbf9b8c92 Mon Sep 17 00:00:00 2001 From: yyjia Date: Wed, 1 Nov 2023 10:08:47 +0800 Subject: [PATCH 34/44] fix: batch close confict with flush (#8613) both batch.Flush() and batch.close() close channel, I think flush is not necessary to close channel --- erigon-lib/kv/membatch/mapmutation.go | 8 +++++- erigon-lib/kv/membatch/mapmutation_test.go | 32 ++++++++++++++++++++++ 2 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 erigon-lib/kv/membatch/mapmutation_test.go diff --git a/erigon-lib/kv/membatch/mapmutation.go b/erigon-lib/kv/membatch/mapmutation.go index e29ed3efa5b..994a042f67f 100644 --- a/erigon-lib/kv/membatch/mapmutation.go +++ b/erigon-lib/kv/membatch/mapmutation.go @@ -235,18 +235,24 @@ func (m *Mapmutation) Flush(ctx context.Context, tx kv.RwTx) error { m.puts = map[string]map[string][]byte{} m.size = 0 m.count = 0 - m.clean() return nil } func (m *Mapmutation) Close() { + if m.clean == nil { + return + } + m.mu.Lock() defer m.mu.Unlock() m.puts = map[string]map[string][]byte{} m.size = 0 m.count = 0 m.size = 0 + m.clean() + m.clean = nil + } func (m *Mapmutation) Commit() error { panic("not db txn, use .Flush method") } func (m *Mapmutation) Rollback() { panic("not db txn, use .Close method") } diff --git a/erigon-lib/kv/membatch/mapmutation_test.go b/erigon-lib/kv/membatch/mapmutation_test.go new file mode 100644 index 00000000000..e3e9927036c --- /dev/null +++ b/erigon-lib/kv/membatch/mapmutation_test.go @@ -0,0 +1,32 @@ +package membatch + +import ( + "context" + "github.com/ledgerwatch/erigon-lib/kv" + "github.com/ledgerwatch/erigon-lib/kv/memdb" + "github.com/ledgerwatch/log/v3" + "github.com/stretchr/testify/require" + "os" + "testing" +) + +func TestMapmutation_Flush_Close(t *testing.T) { + db := memdb.NewTestDB(t) + + tx, err := db.BeginRw(context.Background()) + require.NoError(t, err) + defer tx.Rollback() + + batch := NewHashBatch(tx, nil, os.TempDir(), log.New()) + defer func() { + batch.Close() + }() + err = batch.Put(kv.ChaindataTables[0], []byte{1}, []byte{1}) + require.NoError(t, err) + err = batch.Put(kv.ChaindataTables[0], []byte{2}, []byte{2}) + require.NoError(t, err) + err = batch.Flush(context.Background(), tx) + require.NoError(t, err) + batch.Close() + batch.Close() +} From d4b19b3bb6efabc7e1149300298c9dd71a9c42b2 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 1 Nov 2023 09:56:02 +0700 Subject: [PATCH 35/44] pool: limit broadcast tx size by 4kb (#8634) similar to geth --- erigon-lib/txpool/pool.go | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/erigon-lib/txpool/pool.go b/erigon-lib/txpool/pool.go index 9111b5f4ba0..0f835136b51 100644 --- a/erigon-lib/txpool/pool.go +++ b/erigon-lib/txpool/pool.go @@ -1627,6 +1627,11 @@ func promote(pending *PendingPool, baseFee, queued *SubPool, pendingBaseFee uint } } +// txMaxBroadcastSize is the max size of a transaction that will be broadcasted. +// All transactions with a higher size will be announced and need to be fetched +// by the peer. +const txMaxBroadcastSize = 4 * 1024 + // MainLoop - does: // send pending byHash to p2p: // - new byHash @@ -1725,7 +1730,8 @@ func MainLoop(ctx context.Context, db kv.RwDB, coreDB kv.RoDB, p *TxPool, newTxs localTxSizes = append(localTxSizes, size) localTxHashes = append(localTxHashes, hash...) - if t != types.BlobTxType { // "Nodes MUST NOT automatically broadcast blob transactions to their peers" - EIP-4844 + // "Nodes MUST NOT automatically broadcast blob transactions to their peers" - EIP-4844 + if t != types.BlobTxType { localTxRlps = append(localTxRlps, slotRlp) broadCastedHashes = append(broadCastedHashes, hash...) } @@ -1733,7 +1739,9 @@ func MainLoop(ctx context.Context, db kv.RwDB, coreDB kv.RoDB, p *TxPool, newTxs remoteTxTypes = append(remoteTxTypes, t) remoteTxSizes = append(remoteTxSizes, size) remoteTxHashes = append(remoteTxHashes, hash...) - if t != types.BlobTxType { // "Nodes MUST NOT automatically broadcast blob transactions to their peers" - EIP-4844 + + // "Nodes MUST NOT automatically broadcast blob transactions to their peers" - EIP-4844 + if t != types.BlobTxType && len(slotRlp) < txMaxBroadcastSize { remoteTxRlps = append(remoteTxRlps, slotRlp) } } From b5ea87d8c5acd1c72347246e64452d7dc00b2a37 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 1 Nov 2023 15:50:27 +0700 Subject: [PATCH 36/44] mdbx_empty_kv_dup (#8635) --- erigon-lib/go.mod | 2 +- erigon-lib/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index 337752a61f8..109b392334f 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon-lib go 1.20 require ( - github.com/erigontech/mdbx-go v0.27.20 + github.com/erigontech/mdbx-go v0.35.2-0.20231101074031-9f999220e9ed github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3 github.com/ledgerwatch/interfaces v0.0.0-20231011121315-f58b806039f0 github.com/ledgerwatch/log/v3 v3.9.0 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index 8b38439c3b1..e99a7f6a4e8 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -173,8 +173,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erigontech/mdbx-go v0.27.20 h1:b6nhop/nEtXLR0s8Vu1NvoQeiI6GNRoPVA5YbUPUGU0= -github.com/erigontech/mdbx-go v0.27.20/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= +github.com/erigontech/mdbx-go v0.35.2-0.20231101074031-9f999220e9ed h1:i1xZSrLxifCa0nabPeTxma9/3hqPSRmvqwWqad8rLVM= +github.com/erigontech/mdbx-go v0.35.2-0.20231101074031-9f999220e9ed/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= github.com/frankban/quicktest v1.9.0/go.mod h1:ui7WezCLWMWxVWr1GETZY3smRy0G4KWq9vcPtJmFl7Y= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= diff --git a/go.mod b/go.mod index 6e12207b6b3..b7b2c0a2837 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/ledgerwatch/erigon go 1.20 require ( - github.com/erigontech/mdbx-go v0.27.20 + github.com/erigontech/mdbx-go v0.35.2-0.20231101074031-9f999220e9ed github.com/ledgerwatch/erigon-lib v1.0.0 github.com/ledgerwatch/log/v3 v3.9.0 github.com/ledgerwatch/secp256k1 v1.0.0 diff --git a/go.sum b/go.sum index f0e77298c9e..02969b32912 100644 --- a/go.sum +++ b/go.sum @@ -288,8 +288,8 @@ github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1m github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/erigontech/mdbx-go v0.27.20 h1:b6nhop/nEtXLR0s8Vu1NvoQeiI6GNRoPVA5YbUPUGU0= -github.com/erigontech/mdbx-go v0.27.20/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= +github.com/erigontech/mdbx-go v0.35.2-0.20231101074031-9f999220e9ed h1:i1xZSrLxifCa0nabPeTxma9/3hqPSRmvqwWqad8rLVM= +github.com/erigontech/mdbx-go v0.35.2-0.20231101074031-9f999220e9ed/go.mod h1:FAMxbOgqOnRDx51j8HjuJZIgznbDwjX7LItd+/UWyA4= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c h1:CndMRAH4JIwxbW8KYq6Q+cGWcGHz0FjGR3QqcInWcW0= github.com/fjl/gencodec v0.0.0-20220412091415-8bb9e558978c/go.mod h1:AzA8Lj6YtixmJWL+wkKoBGsLWy9gFrAzi4g+5bCKwpY= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= From 8e54a965ca7bbc1cec571f97e0b5d114abb98e37 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 1 Nov 2023 15:50:35 +0700 Subject: [PATCH 37/44] webseed: don't download .torrent files (#8629) --- erigon-lib/downloader/util.go | 17 ------ erigon-lib/downloader/webseed.go | 88 -------------------------------- 2 files changed, 105 deletions(-) diff --git a/erigon-lib/downloader/util.go b/erigon-lib/downloader/util.go index 7bf8f58274b..cc557e09f55 100644 --- a/erigon-lib/downloader/util.go +++ b/erigon-lib/downloader/util.go @@ -292,23 +292,6 @@ func loadTorrent(torrentFilePath string) (*torrent.TorrentSpec, error) { mi.AnnounceList = Trackers return torrent.TorrentSpecFromMetaInfoErr(mi) } -func saveTorrent(torrentFilePath string, res []byte) error { - if len(res) == 0 { - return fmt.Errorf("try to write 0 bytes to file: %s", torrentFilePath) - } - f, err := os.Create(torrentFilePath) - if err != nil { - return err - } - defer f.Close() - if _, err = f.Write(res); err != nil { - return err - } - if err = f.Sync(); err != nil { - return err - } - return nil -} // addTorrentFile - adding .torrent file to torrentClient (and checking their hashes), if .torrent file // added first time - pieces verification process will start (disk IO heavy) - Progress diff --git a/erigon-lib/downloader/webseed.go b/erigon-lib/downloader/webseed.go index 02949c15e7b..5cbb2b0e908 100644 --- a/erigon-lib/downloader/webseed.go +++ b/erigon-lib/downloader/webseed.go @@ -1,10 +1,8 @@ package downloader import ( - "bytes" "context" "fmt" - "io" "net/http" "net/url" "os" @@ -17,14 +15,10 @@ import ( "github.com/aws/aws-sdk-go-v2/credentials" "github.com/aws/aws-sdk-go-v2/service/s3" - "github.com/anacrolix/torrent/bencode" "github.com/anacrolix/torrent/metainfo" - "github.com/c2h5oh/datasize" - "github.com/ledgerwatch/erigon-lib/common/dir" "github.com/ledgerwatch/erigon-lib/downloader/snaptype" "github.com/ledgerwatch/log/v3" "github.com/pelletier/go-toml/v2" - "golang.org/x/sync/errgroup" ) // WebSeeds - allow use HTTP-based infrastrucutre to support Bittorrent network @@ -42,7 +36,6 @@ type WebSeeds struct { func (d *WebSeeds) Discover(ctx context.Context, s3tokens []string, urls []*url.URL, files []string, rootDir string) { d.downloadWebseedTomlFromProviders(ctx, s3tokens, urls, files) - d.downloadTorrentFilesFromProviders(ctx, rootDir) } func (d *WebSeeds) downloadWebseedTomlFromProviders(ctx context.Context, s3Providers []string, httpProviders []*url.URL, diskProviders []string) { @@ -106,59 +99,6 @@ func (d *WebSeeds) downloadWebseedTomlFromProviders(ctx context.Context, s3Provi d.torrentUrls = torrentUrls } -// downloadTorrentFilesFromProviders - if they are not exist on file-system -func (d *WebSeeds) downloadTorrentFilesFromProviders(ctx context.Context, rootDir string) { - // TODO: need more tests, need handle more forward-compatibility and backward-compatibility case - // - now, if add new type of .torrent files to S3 bucket - existing nodes will start downloading it. maybe need whitelist of file types - // - maybe need download new files if --snap.stop=true - if !d.downloadTorrentFile { - return - } - if len(d.TorrentUrls()) == 0 { - return - } - var addedNew int - e, ctx := errgroup.WithContext(ctx) - urlsByName := d.TorrentUrls() - //TODO: - // - what to do if node already synced? - for name, tUrls := range urlsByName { - tPath := filepath.Join(rootDir, name) - if dir.FileExist(tPath) { - continue - } - addedNew++ - if strings.HasSuffix(name, ".v.torrent") || strings.HasSuffix(name, ".ef.torrent") { - _, fName := filepath.Split(name) - if strings.HasPrefix(fName, "commitment") { - d.logger.Log(d.verbosity, "[snapshots] webseed has .torrent, but we skip it because we don't support it yet", "name", name) - continue - } - } - name := name - tUrls := tUrls - e.Go(func() error { - for _, url := range tUrls { - res, err := d.callTorrentHttpProvider(ctx, url) - if err != nil { - d.logger.Debug("[snapshots] callTorrentHttpProvider", "err", err) - continue - } - d.logger.Log(d.verbosity, "[snapshots] downloaded .torrent file from webseed", "name", name) - if err := saveTorrent(tPath, res); err != nil { - d.logger.Debug("[snapshots] saveTorrent", "err", err) - continue - } - return nil - } - return nil - }) - } - if err := e.Wait(); err != nil { - d.logger.Debug("[snapshots] webseed discover", "err", err) - } -} - func (d *WebSeeds) TorrentUrls() snaptype.TorrentUrls { d.lock.Lock() defer d.lock.Unlock() @@ -242,34 +182,6 @@ func (d *WebSeeds) callS3Provider(ctx context.Context, token string) (snaptype.W d.logger.Debug("[snapshots.webseed] get from S3 provider", "urls", len(response), "bucket", bucketName) return response, nil } -func (d *WebSeeds) callTorrentHttpProvider(ctx context.Context, url *url.URL) ([]byte, error) { - request, err := http.NewRequest(http.MethodGet, url.String(), nil) - if err != nil { - return nil, err - } - request = request.WithContext(ctx) - resp, err := http.DefaultClient.Do(request) - if err != nil { - return nil, fmt.Errorf("webseed.downloadTorrentFile: host=%s, url=%s, %w", url.Hostname(), url.EscapedPath(), err) - } - defer resp.Body.Close() - //protect against too small and too big data - if resp.ContentLength == 0 || resp.ContentLength > int64(128*datasize.MB) { - return nil, nil - } - res, err := io.ReadAll(resp.Body) - if err != nil { - return nil, fmt.Errorf("webseed.downloadTorrentFile: host=%s, url=%s, %w", url.Hostname(), url.EscapedPath(), err) - } - if err = validateTorrentBytes(res); err != nil { - return nil, fmt.Errorf("webseed.downloadTorrentFile: host=%s, url=%s, %w", url.Hostname(), url.EscapedPath(), err) - } - return res, nil -} -func validateTorrentBytes(b []byte) error { - var mi metainfo.MetaInfo - return bencode.NewDecoder(bytes.NewBuffer(b)).Decode(&mi) -} func (d *WebSeeds) readWebSeedsFile(webSeedProviderPath string) (snaptype.WebSeedsFromProvider, error) { _, fileName := filepath.Split(webSeedProviderPath) data, err := os.ReadFile(webSeedProviderPath) From 3698e7f4767b8b5c93b034c9a3717784cb89ee9c Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Wed, 1 Nov 2023 11:08:47 +0100 Subject: [PATCH 38/44] devnet: configuration fixes (#8592) * fix "genesis hash does not match" when dev nodes connect The "dev" nodes need to have the same --miner.etherbase in order to generate the same genesis ExtraData by DeveloperGenesisBlock(). Override DevnetEtherbase global var that's used if --miner.etherbase is not passed. (for NonBlockProducer case) * fix missing private key for the hardcoded DevnetEtherbase Fixes panic if SigKey is not found. Bor non-producers will use a default `DevnetEtherbase` while Dev nodes modify it. Save hardcoded DevnetEtherbase/DevnetSignPrivateKey into accounts so that SigKey can recover it. * refactor devnet.node to contain Node config This avoids interface{} type casts and fixes an error with Heimdall.validatorSet == nil * add connection retries to rpcCall and Subscribe of requestGenerator Fixes "connection refused" errors due to node not ready to handle early RPC requests. * fix deadlock in Heimdall.NodeStarted * fix GetBlockByNumber Fixes "cannot unmarshal string into Go struct field body.transactions of type jsonrpc.RPCTransaction" * demote "no of blocks on childchain is less than confirmations required" to Info (#8626) * demote "mismatched pending subpool size" to Debug (#8615) * revert wiggle testing code --- cmd/devnet/accounts/accounts.go | 8 ++ cmd/devnet/args/{node.go => node_args.go} | 58 ++++++------ .../args/{node_test.go => node_args_test.go} | 4 +- cmd/devnet/devnet/context.go | 2 +- cmd/devnet/devnet/network.go | 79 ++++------------ cmd/devnet/devnet/node.go | 63 +++++-------- cmd/devnet/main.go | 18 ++-- cmd/devnet/requests/account.go | 8 +- cmd/devnet/requests/admin.go | 2 +- cmd/devnet/requests/block.go | 63 ++++++++++--- cmd/devnet/requests/event.go | 2 +- cmd/devnet/requests/request_generator.go | 92 +++++++++++++++---- cmd/devnet/requests/trace.go | 4 +- cmd/devnet/requests/transaction.go | 12 +-- cmd/devnet/requests/tx.go | 2 +- cmd/devnet/services/accounts/faucet.go | 2 +- cmd/devnet/services/polygon/checkpoint.go | 12 ++- cmd/devnet/services/polygon/heimdall.go | 12 ++- cmd/devnet/services/polygon/proofgenerator.go | 2 +- cmd/devnet/services/polygon/statesync.go | 2 +- cmd/devnet/transactions/tx.go | 11 ++- cmd/utils/flags.go | 2 +- consensus/bor/bor.go | 6 -- params/config.go | 15 ++- rpc/http.go | 30 +++--- rpc/websocket.go | 4 + 26 files changed, 278 insertions(+), 237 deletions(-) rename cmd/devnet/args/{node.go => node_args.go} (87%) rename cmd/devnet/args/{node_test.go => node_args_test.go} (99%) diff --git a/cmd/devnet/accounts/accounts.go b/cmd/devnet/accounts/accounts.go index 032cebdc616..097ca74daf5 100644 --- a/cmd/devnet/accounts/accounts.go +++ b/cmd/devnet/accounts/accounts.go @@ -20,6 +20,14 @@ func init() { core.DevnetSignKey = func(addr libcommon.Address) *ecdsa.PrivateKey { return SigKey(addr) } + + devnetEtherbaseAccount := &Account{ + "DevnetEtherbase", + core.DevnetEtherbase, + core.DevnetSignPrivateKey, + } + accountsByAddress[core.DevnetEtherbase] = devnetEtherbaseAccount + accountsByName[devnetEtherbaseAccount.Name] = devnetEtherbaseAccount } var accountsByAddress = map[libcommon.Address]*Account{} diff --git a/cmd/devnet/args/node.go b/cmd/devnet/args/node_args.go similarity index 87% rename from cmd/devnet/args/node.go rename to cmd/devnet/args/node_args.go index 0ab64a9e1ed..9684d11c899 100644 --- a/cmd/devnet/args/node.go +++ b/cmd/devnet/args/node_args.go @@ -4,8 +4,10 @@ import ( "crypto/ecdsa" "encoding/hex" "fmt" + "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/crypto" "github.com/ledgerwatch/erigon/p2p/enode" + "github.com/ledgerwatch/erigon/params" "math/big" "net" "path/filepath" @@ -16,7 +18,7 @@ import ( "github.com/ledgerwatch/erigon/cmd/devnet/requests" ) -type Node struct { +type NodeArgs struct { requests.RequestGenerator `arg:"-"` Name string `arg:"-"` BuildDir string `arg:"positional" default:"./build/bin/devnet" json:"builddir"` @@ -55,8 +57,7 @@ type Node struct { NodeKeyHex string `arg:"--nodekeyhex" json:"nodekeyhex,omitempty"` } -func (node *Node) configure(base Node, nodeNumber int) error { - +func (node *NodeArgs) Configure(base NodeArgs, nodeNumber int) error { if len(node.Name) == 0 { node.Name = fmt.Sprintf("%s-%d", base.Chain, nodeNumber) } @@ -104,21 +105,29 @@ func (node *Node) configure(base Node, nodeNumber int) error { return nil } -func (node *Node) ChainID() *big.Int { - return &big.Int{} +func (node *NodeArgs) GetName() string { + return node.Name +} + +func (node *NodeArgs) ChainID() *big.Int { + config := params.ChainConfigByChainName(node.Chain) + if config == nil { + return nil + } + return config.ChainID } -func (node *Node) GetHttpPort() int { +func (node *NodeArgs) GetHttpPort() int { return node.HttpPort } -func (node *Node) GetEnodeURL() string { +func (node *NodeArgs) GetEnodeURL() string { port := node.Port return enode.NewV4(&node.NodeKey.PublicKey, net.ParseIP("127.0.0.1"), port, port).URLv4() } type BlockProducer struct { - Node + NodeArgs Mine bool `arg:"--mine" flag:"true"` Etherbase string `arg:"--miner.etherbase"` DevPeriod int `arg:"--dev.period"` @@ -129,10 +138,10 @@ type BlockProducer struct { account *accounts.Account } -func (m *BlockProducer) Configure(baseNode Node, nodeNumber int) (interface{}, error) { - err := m.configure(baseNode, nodeNumber) +func (m *BlockProducer) Configure(baseNode NodeArgs, nodeNumber int) error { + err := m.NodeArgs.Configure(baseNode, nodeNumber) if err != nil { - return nil, err + return err } switch m.Chain { @@ -140,10 +149,12 @@ func (m *BlockProducer) Configure(baseNode Node, nodeNumber int) (interface{}, e if m.DevPeriod == 0 { m.DevPeriod = 30 } - m.account = accounts.NewAccount(m.Name() + "-etherbase") + m.account = accounts.NewAccount(m.GetName() + "-etherbase") + core.DevnetEtherbase = m.account.Address + core.DevnetSignPrivateKey = m.account.SigKey() case networkname.BorDevnetChainName: - m.account = accounts.NewAccount(m.Name() + "-etherbase") + m.account = accounts.NewAccount(m.GetName() + "-etherbase") if len(m.HttpApi) == 0 { m.HttpApi = "admin,eth,erigon,web3,net,debug,trace,txpool,parity,ots,bor" @@ -154,11 +165,7 @@ func (m *BlockProducer) Configure(baseNode Node, nodeNumber int) (interface{}, e m.Etherbase = m.account.Address.Hex() } - return m, nil -} - -func (n *BlockProducer) Name() string { - return n.Node.Name + return nil } func (n *BlockProducer) Account() *accounts.Account { @@ -170,25 +177,12 @@ func (n *BlockProducer) IsBlockProducer() bool { } type NonBlockProducer struct { - Node + NodeArgs HttpApi string `arg:"--http.api" default:"admin,eth,debug,net,trace,web3,erigon,txpool" json:"http.api"` TorrentPort string `arg:"--torrent.port" default:"42070" json:"torrent.port"` NoDiscover string `arg:"--nodiscover" flag:"" default:"true" json:"nodiscover"` } -func (n *NonBlockProducer) Configure(baseNode Node, nodeNumber int) (interface{}, error) { - err := n.configure(baseNode, nodeNumber) - if err != nil { - return nil, err - } - - return n, nil -} - -func (n *NonBlockProducer) Name() string { - return n.Node.Name -} - func (n *NonBlockProducer) IsBlockProducer() bool { return false } diff --git a/cmd/devnet/args/node_test.go b/cmd/devnet/args/node_args_test.go similarity index 99% rename from cmd/devnet/args/node_test.go rename to cmd/devnet/args/node_args_test.go index 6b940c52d39..a67370b19ea 100644 --- a/cmd/devnet/args/node_test.go +++ b/cmd/devnet/args/node_args_test.go @@ -13,7 +13,7 @@ func TestNodeArgs(t *testing.T) { asMap := map[string]struct{}{} nodeArgs, _ := args.AsArgs(args.BlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ DataDir: filepath.Join("data", fmt.Sprintf("%d", 1)), PrivateApiAddr: "localhost:9092", }, @@ -37,7 +37,7 @@ func TestNodeArgs(t *testing.T) { } nodeArgs, _ = args.AsArgs(args.NonBlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ DataDir: filepath.Join("data", fmt.Sprintf("%d", 2)), StaticPeers: "enode", PrivateApiAddr: "localhost:9091", diff --git a/cmd/devnet/devnet/context.go b/cmd/devnet/devnet/context.go index 002567e22dd..97348746e75 100644 --- a/cmd/devnet/devnet/context.go +++ b/cmd/devnet/devnet/context.go @@ -151,7 +151,7 @@ func CurrentNetwork(ctx context.Context) *Network { } if current := CurrentNode(ctx); current != nil { - if n, ok := current.(*node); ok { + if n, ok := current.(*devnetNode); ok { return n.network } } diff --git a/cmd/devnet/devnet/network.go b/cmd/devnet/devnet/network.go index 76997bf3cb6..2f6e948d827 100644 --- a/cmd/devnet/devnet/network.go +++ b/cmd/devnet/devnet/network.go @@ -2,11 +2,9 @@ package devnet import ( "context" - "errors" "fmt" "github.com/ledgerwatch/erigon/cmd/utils" "math/big" - "net" "os" "reflect" "strings" @@ -15,7 +13,6 @@ import ( "github.com/ledgerwatch/erigon-lib/common/dbg" "github.com/ledgerwatch/erigon/cmd/devnet/args" - "github.com/ledgerwatch/erigon/cmd/devnet/devnetutils" "github.com/ledgerwatch/erigon/cmd/devnet/requests" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/params" @@ -63,7 +60,7 @@ func (nw *Network) Start(ctx context.Context) error { } } - baseNode := args.Node{ + baseNode := args.NodeArgs{ DataDir: nw.DataDir, Chain: nw.Chain, Port: nw.BasePort, @@ -84,7 +81,7 @@ func (nw *Network) Start(ctx context.Context) error { metricsNode := cliCtx.Int("metrics.node") nw.namedNodes = map[string]Node{} - for i, nodeConfig := range nw.Nodes { + for i, nodeArgs := range nw.Nodes { { base := baseNode if metricsEnabled && metricsNode == i { @@ -93,24 +90,21 @@ func (nw *Network) Start(ctx context.Context) error { } base.StaticPeers = strings.Join(nw.peers, ",") - argsObj, err := nodeConfig.Configure(base, i) + err := nodeArgs.Configure(base, i) if err != nil { nw.Stop() return err } - nodePort := nodeConfig.GetHttpPort() - nodeAddr := fmt.Sprintf("%s:%d", nw.BaseRPCHost, nodePort) - - node, err := nw.createNode(nodeAddr, argsObj) + node, err := nw.createNode(nodeArgs) if err != nil { nw.Stop() return err } nw.Nodes[i] = node - nw.namedNodes[node.Name()] = node - nw.peers = append(nw.peers, nodeConfig.GetEnodeURL()) + nw.namedNodes[node.GetName()] = node + nw.peers = append(nw.peers, nodeArgs.GetEnodeURL()) for _, service := range nw.Services { service.NodeCreated(ctx, node) @@ -135,11 +129,13 @@ func (nw *Network) Start(ctx context.Context) error { var blockProducerFunds = (&big.Int{}).Mul(big.NewInt(1000), big.NewInt(params.Ether)) -func (nw *Network) createNode(nodeAddr string, cfg interface{}) (Node, error) { - n := &node{ +func (nw *Network) createNode(nodeArgs Node) (Node, error) { + nodeAddr := fmt.Sprintf("%s:%d", nw.BaseRPCHost, nodeArgs.GetHttpPort()) + + n := &devnetNode{ sync.Mutex{}, requests.NewRequestGenerator(nodeAddr, nw.Logger), - cfg, + nodeArgs, &nw.wg, nw, make(chan error), @@ -184,15 +180,15 @@ func copyFlags(flags []cli.Flag) []cli.Flag { func (nw *Network) startNode(n Node) error { nw.wg.Add(1) - node := n.(*node) + node := n.(*devnetNode) - args, err := args.AsArgs(node.args) + args, err := args.AsArgs(node.nodeArgs) if err != nil { return err } go func() { - nw.Logger.Info("Running node", "name", node.Name(), "args", args) + nw.Logger.Info("Running node", "name", node.GetName(), "args", args) // catch any errors and avoid panics if an error occurs defer func() { @@ -201,17 +197,17 @@ func (nw *Network) startNode(n Node) error { return } - nw.Logger.Error("catch panic", "node", node.Name(), "err", panicResult, "stack", dbg.Stack()) + nw.Logger.Error("catch panic", "node", node.GetName(), "err", panicResult, "stack", dbg.Stack()) nw.Stop() os.Exit(1) }() // cli flags are not thread safe and assume only one copy of a flag // variable is needed per process - which does not work here - app := erigonapp.MakeApp(node.Name(), node.run, copyFlags(erigoncli.DefaultFlags)) + app := erigonapp.MakeApp(node.GetName(), node.run, copyFlags(erigoncli.DefaultFlags)) if err := app.Run(args); err != nil { - nw.Logger.Warn("App run returned error", "node", node.Name(), "err", err) + nw.Logger.Warn("App run returned error", "node", node.GetName(), "err", err) } }() @@ -222,47 +218,6 @@ func (nw *Network) startNode(n Node) error { return nil } -func isConnectionError(err error) bool { - var opErr *net.OpError - if errors.As(err, &opErr) { - return opErr.Op == "dial" - } - return false -} - -// getEnode returns the enode of the netowrk node -func getEnode(n Node) (string, error) { - reqCount := 0 - - for { - nodeInfo, err := n.AdminNodeInfo() - - if err != nil { - if r, ok := n.(*node); ok { - if !r.running() { - return "", err - } - } - - if isConnectionError(err) && (reqCount < 10) { - reqCount++ - time.Sleep(time.Duration(devnetutils.RandomInt(5)) * time.Second) - continue - } - - return "", err - } - - enode, err := devnetutils.UniqueIDFromEnode(nodeInfo.Enode) - - if err != nil { - return "", err - } - - return enode, nil - } -} - func (nw *Network) Stop() { type stoppable interface { Stop() diff --git a/cmd/devnet/devnet/node.go b/cmd/devnet/devnet/node.go index 053f45b8d70..abba7715d68 100644 --- a/cmd/devnet/devnet/node.go +++ b/cmd/devnet/devnet/node.go @@ -2,10 +2,8 @@ package devnet import ( "context" - "errors" "fmt" "math/big" - "net" "net/http" "sync" @@ -16,7 +14,6 @@ import ( "github.com/ledgerwatch/erigon/diagnostics" "github.com/ledgerwatch/erigon/eth/ethconfig" "github.com/ledgerwatch/erigon/node/nodecfg" - p2p_enode "github.com/ledgerwatch/erigon/p2p/enode" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/turbo/debug" enode "github.com/ledgerwatch/erigon/turbo/node" @@ -26,13 +23,13 @@ import ( type Node interface { requests.RequestGenerator - Name() string + GetName() string ChainID() *big.Int GetHttpPort() int GetEnodeURL() string Account() *accounts.Account IsBlockProducer() bool - Configure(baseNode args.Node, nodeNumber int) (interface{}, error) + Configure(baseNode args.NodeArgs, nodeNumber int) error } type NodeSelector interface { @@ -46,7 +43,7 @@ func (f NodeSelectorFunc) Test(ctx context.Context, node Node) bool { } func HTTPHost(n Node) string { - if n, ok := n.(*node); ok { + if n, ok := n.(*devnetNode); ok { host := n.nodeCfg.Http.HttpListenAddress if host == "" { @@ -59,10 +56,10 @@ func HTTPHost(n Node) string { return "" } -type node struct { +type devnetNode struct { sync.Mutex requests.RequestGenerator - args interface{} + nodeArgs Node wg *sync.WaitGroup network *Network startErr chan error @@ -71,7 +68,7 @@ type node struct { ethNode *enode.ErigonNode } -func (n *node) Stop() { +func (n *devnetNode) Stop() { var toClose *enode.ErigonNode n.Lock() @@ -88,13 +85,13 @@ func (n *node) Stop() { n.done() } -func (n *node) running() bool { +func (n *devnetNode) running() bool { n.Lock() defer n.Unlock() return n.startErr == nil && n.ethNode != nil } -func (n *node) done() { +func (n *devnetNode) done() { n.Lock() defer n.Unlock() if n.wg != nil { @@ -104,50 +101,36 @@ func (n *node) done() { } } -func (n *node) Configure(args.Node, int) (interface{}, error) { - return nil, errors.New("N/A") +func (n *devnetNode) Configure(args.NodeArgs, int) error { + return nil } -func (n *node) IsBlockProducer() bool { - _, isBlockProducer := n.args.(args.BlockProducer) - return isBlockProducer +func (n *devnetNode) IsBlockProducer() bool { + return n.nodeArgs.IsBlockProducer() } -func (n *node) Account() *accounts.Account { - if miner, ok := n.args.(args.BlockProducer); ok { - return miner.Account() - } - - return nil +func (n *devnetNode) Account() *accounts.Account { + return n.nodeArgs.Account() } -func (n *node) Name() string { - if named, ok := n.args.(interface{ Name() string }); ok { - return named.Name() - } - - return "" +func (n *devnetNode) GetName() string { + return n.nodeArgs.GetName() } -func (n *node) ChainID() *big.Int { - if n.ethCfg != nil { - return n.ethCfg.Genesis.Config.ChainID - } - - return nil +func (n *devnetNode) ChainID() *big.Int { + return n.nodeArgs.ChainID() } -func (n *node) GetHttpPort() int { - return n.nodeCfg.HTTPPort +func (n *devnetNode) GetHttpPort() int { + return n.nodeArgs.GetHttpPort() } -func (n *node) GetEnodeURL() string { - port := n.nodeCfg.P2P.ListenPort() - return p2p_enode.NewV4(&n.nodeCfg.P2P.PrivateKey.PublicKey, net.ParseIP("127.0.0.1"), port, port).URLv4() +func (n *devnetNode) GetEnodeURL() string { + return n.nodeArgs.GetEnodeURL() } // run configures, creates and serves an erigon node -func (n *node) run(ctx *cli.Context) error { +func (n *devnetNode) run(ctx *cli.Context) error { var logger log.Logger var err error var metricsMux *http.ServeMux diff --git a/cmd/devnet/main.go b/cmd/devnet/main.go index fa944d61453..5de9d579018 100644 --- a/cmd/devnet/main.go +++ b/cmd/devnet/main.go @@ -346,7 +346,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { }, Nodes: []devnet.Node{ &args.BlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "5", WithoutHeimdall: true, @@ -354,7 +354,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { AccountSlots: 200, }, &args.NonBlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "5", WithoutHeimdall: true, @@ -405,7 +405,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { }, Nodes: []devnet.Node{ &args.BlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "5", HeimdallGRpc: heimdallGrpc, @@ -413,7 +413,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { AccountSlots: 200, }, &args.BlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "5", HeimdallGRpc: heimdallGrpc, @@ -429,7 +429,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { AccountSlots: 200, },*/ &args.NonBlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "5", HeimdallGRpc: heimdallGrpc, @@ -452,7 +452,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { }, Nodes: []devnet.Node{ &args.BlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "5", VMDebug: true, @@ -462,7 +462,7 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { AccountSlots: 200, }, &args.NonBlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "3", }, @@ -488,14 +488,14 @@ func initDevnet(ctx *cli.Context, logger log.Logger) (devnet.Devnet, error) { }, Nodes: []devnet.Node{ &args.BlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "5", }, AccountSlots: 200, }, &args.NonBlockProducer{ - Node: args.Node{ + NodeArgs: args.NodeArgs{ ConsoleVerbosity: "0", DirVerbosity: "5", }, diff --git a/cmd/devnet/requests/account.go b/cmd/devnet/requests/account.go index 92d14ec5dec..30e1fa7e506 100644 --- a/cmd/devnet/requests/account.go +++ b/cmd/devnet/requests/account.go @@ -36,7 +36,7 @@ type StorageResult struct { func (reqGen *requestGenerator) GetCode(address libcommon.Address, blockRef rpc.BlockReference) (hexutility.Bytes, error) { var result hexutility.Bytes - if err := reqGen.callCli(&result, Methods.ETHGetCode, address, blockRef); err != nil { + if err := reqGen.rpcCall(&result, Methods.ETHGetCode, address, blockRef); err != nil { return nil, err } @@ -46,7 +46,7 @@ func (reqGen *requestGenerator) GetCode(address libcommon.Address, blockRef rpc. func (reqGen *requestGenerator) GetBalance(address libcommon.Address, blockRef rpc.BlockReference) (*big.Int, error) { var result hexutil.Big - if err := reqGen.callCli(&result, Methods.ETHGetBalance, address, blockRef); err != nil { + if err := reqGen.rpcCall(&result, Methods.ETHGetBalance, address, blockRef); err != nil { return nil, err } @@ -56,7 +56,7 @@ func (reqGen *requestGenerator) GetBalance(address libcommon.Address, blockRef r func (reqGen *requestGenerator) GetTransactionCount(address libcommon.Address, blockRef rpc.BlockReference) (*big.Int, error) { var result hexutil.Big - if err := reqGen.callCli(&result, Methods.ETHGetTransactionCount, address, blockRef); err != nil { + if err := reqGen.rpcCall(&result, Methods.ETHGetTransactionCount, address, blockRef); err != nil { return nil, err } @@ -67,7 +67,7 @@ func (reqGen *requestGenerator) DebugAccountAt(blockHash libcommon.Hash, txIndex var b DebugAccountAt method, body := reqGen.debugAccountAt(blockHash, txIndex, account) - if res := reqGen.call(method, body, &b); res.Err != nil { + if res := reqGen.rpcCallJSON(method, body, &b); res.Err != nil { return nil, fmt.Errorf("failed to get account: %v", res.Err) } diff --git a/cmd/devnet/requests/admin.go b/cmd/devnet/requests/admin.go index be9f6447003..6fb4567d162 100644 --- a/cmd/devnet/requests/admin.go +++ b/cmd/devnet/requests/admin.go @@ -7,7 +7,7 @@ import ( func (reqGen *requestGenerator) AdminNodeInfo() (p2p.NodeInfo, error) { var result p2p.NodeInfo - if err := reqGen.callCli(&result, Methods.AdminNodeInfo); err != nil { + if err := reqGen.rpcCall(&result, Methods.AdminNodeInfo); err != nil { return p2p.NodeInfo{}, err } diff --git a/cmd/devnet/requests/block.go b/cmd/devnet/requests/block.go index b8d4a5e603e..b5d719adf46 100644 --- a/cmd/devnet/requests/block.go +++ b/cmd/devnet/requests/block.go @@ -40,33 +40,63 @@ var BlockNumbers = struct { Pending: "pending", } -type Block struct { +type BlockWithTxHashes struct { *types.Header - Hash libcommon.Hash `json:"hash"` - Transactions []*jsonrpc.RPCTransaction `json:"transactions"` + Hash libcommon.Hash `json:"hash"` + TransactionHashes []libcommon.Hash } -func (b *Block) UnmarshalJSON(input []byte) error { - type body struct { - Hash libcommon.Hash `json:"hash"` - Transactions []*jsonrpc.RPCTransaction `json:"transactions"` +func (b *BlockWithTxHashes) UnmarshalJSON(input []byte) error { + var header types.Header + if err := json.Unmarshal(input, &header); err != nil { + return err } - bd := body{} - + var bd struct { + Hash libcommon.Hash `json:"hash"` + TransactionHashes []libcommon.Hash `json:"transactions"` + } if err := json.Unmarshal(input, &bd); err != nil { return err } - header := types.Header{} + b.Header = &header + b.Hash = bd.Hash + b.TransactionHashes = bd.TransactionHashes + + return nil +} +type Block struct { + BlockWithTxHashes + Transactions []*jsonrpc.RPCTransaction `json:"transactions"` +} + +func (b *Block) UnmarshalJSON(input []byte) error { + var header types.Header if err := json.Unmarshal(input, &header); err != nil { return err } + var bd struct { + Hash libcommon.Hash `json:"hash"` + Transactions []*jsonrpc.RPCTransaction `json:"transactions"` + } + if err := json.Unmarshal(input, &bd); err != nil { + return err + } + b.Header = &header b.Hash = bd.Hash b.Transactions = bd.Transactions + + if bd.Transactions != nil { + b.TransactionHashes = make([]libcommon.Hash, len(b.Transactions)) + for _, t := range bd.Transactions { + b.TransactionHashes = append(b.TransactionHashes, t.Hash) + } + } + return nil } @@ -78,7 +108,7 @@ type EthGetTransactionCount struct { func (reqGen *requestGenerator) BlockNumber() (uint64, error) { var result hexutil2.Uint64 - if err := reqGen.callCli(&result, Methods.ETHBlockNumber); err != nil { + if err := reqGen.rpcCall(&result, Methods.ETHBlockNumber); err != nil { return 0, err } @@ -87,8 +117,15 @@ func (reqGen *requestGenerator) BlockNumber() (uint64, error) { func (reqGen *requestGenerator) GetBlockByNumber(blockNum rpc.BlockNumber, withTxs bool) (*Block, error) { var result Block + var err error + + if withTxs { + err = reqGen.rpcCall(&result, Methods.ETHGetBlockByNumber, blockNum, withTxs) + } else { + err = reqGen.rpcCall(&result.BlockWithTxHashes, Methods.ETHGetBlockByNumber, blockNum, withTxs) + } - if err := reqGen.callCli(&result, Methods.ETHGetBlockByNumber, blockNum, withTxs); err != nil { + if err != nil { return nil, err } @@ -98,7 +135,7 @@ func (reqGen *requestGenerator) GetBlockByNumber(blockNum rpc.BlockNumber, withT func (req *requestGenerator) GetRootHash(startBlock uint64, endBlock uint64) (libcommon.Hash, error) { var result string - if err := req.callCli(&result, Methods.BorGetRootHash, startBlock, endBlock); err != nil { + if err := req.rpcCall(&result, Methods.BorGetRootHash, startBlock, endBlock); err != nil { return libcommon.Hash{}, err } diff --git a/cmd/devnet/requests/event.go b/cmd/devnet/requests/event.go index e1ca8178376..379b78a77c1 100644 --- a/cmd/devnet/requests/event.go +++ b/cmd/devnet/requests/event.go @@ -50,7 +50,7 @@ func NewLog(hash libcommon.Hash, blockNum uint64, address libcommon.Address, top func (reqGen *requestGenerator) FilterLogs(ctx context.Context, query ethereum.FilterQuery) ([]types.Log, error) { var result []types.Log - if err := reqGen.callCli(&result, Methods.ETHGetLogs, query); err != nil { + if err := reqGen.rpcCall(&result, Methods.ETHGetLogs, query); err != nil { return nil, err } diff --git a/cmd/devnet/requests/request_generator.go b/cmd/devnet/requests/request_generator.go index 80bbe5f5708..fa0b3c1196f 100644 --- a/cmd/devnet/requests/request_generator.go +++ b/cmd/devnet/requests/request_generator.go @@ -3,9 +3,11 @@ package requests import ( "context" "encoding/json" + "errors" "fmt" "io" "math/big" + "net" "net/http" "strings" "sync" @@ -151,11 +153,15 @@ var Methods = struct { ETHCall: "eth_call", } -func (req *requestGenerator) call(method RPCMethod, body string, response interface{}) callResult { +func (req *requestGenerator) rpcCallJSON(method RPCMethod, body string, response interface{}) callResult { + ctx := context.Background() + req.reqID++ start := time.Now() targetUrl := "http://" + req.target - err := post(req.client, targetUrl, string(method), body, response, req.logger) - req.reqID++ + + err := retryConnects(ctx, func(ctx context.Context) error { + return post(ctx, req.client, targetUrl, string(method), body, response, req.logger) + }) return callResult{ RequestBody: body, @@ -167,14 +173,56 @@ func (req *requestGenerator) call(method RPCMethod, body string, response interf } } -func (req *requestGenerator) callCli(result interface{}, method RPCMethod, args ...interface{}) error { - cli, err := req.cli(context.Background()) - +func (req *requestGenerator) rpcCall(result interface{}, method RPCMethod, args ...interface{}) error { + ctx := context.Background() + client, err := req.rpcClient(ctx) if err != nil { return err } - return cli.Call(result, string(method), args...) + return retryConnects(ctx, func(ctx context.Context) error { + return client.CallContext(ctx, result, string(method), args...) + }) +} + +const connectionTimeout = time.Second * 5 + +func isConnectionError(err error) bool { + var opErr *net.OpError + if errors.As(err, &opErr) { + return opErr.Op == "dial" + } + return false +} + +func retryConnects(ctx context.Context, op func(context.Context) error) error { + ctx, cancel := context.WithTimeout(ctx, connectionTimeout) + defer cancel() + return retry(ctx, op, isConnectionError, time.Millisecond*200, nil) +} + +func retry(ctx context.Context, op func(context.Context) error, isRecoverableError func(error) bool, delay time.Duration, lastErr error) error { + err := op(ctx) + if err == nil { + return nil + } + if errors.Is(err, context.DeadlineExceeded) && lastErr != nil { + return lastErr + } + if !isRecoverableError(err) { + return err + } + + delayTimer := time.NewTimer(delay) + select { + case <-delayTimer.C: + return retry(ctx, op, isRecoverableError, delay, err) + case <-ctx.Done(): + if errors.Is(ctx.Err(), context.DeadlineExceeded) { + return err + } + return ctx.Err() + } } type PingResult callResult @@ -231,17 +279,15 @@ func NewRequestGenerator(target string, logger log.Logger) RequestGenerator { client: &http.Client{ Timeout: time.Second * 10, }, - reqID: 1, logger: logger, target: target, } } -func (req *requestGenerator) cli(ctx context.Context) (*rpc.Client, error) { +func (req *requestGenerator) rpcClient(ctx context.Context) (*rpc.Client, error) { if req.requestClient == nil { var err error req.requestClient, err = rpc.DialContext(ctx, "http://"+req.target, req.logger) - if err != nil { return nil, err } @@ -250,14 +296,23 @@ func (req *requestGenerator) cli(ctx context.Context) (*rpc.Client, error) { return req.requestClient, nil } -func post(client *http.Client, url, method, request string, response interface{}, logger log.Logger) error { +func post(ctx context.Context, client *http.Client, url, method, request string, response interface{}, logger log.Logger) error { start := time.Now() - r, err := client.Post(url, "application/json", strings.NewReader(request)) // nolint:bodyclose + + req, err := http.NewRequest("POST", url, strings.NewReader(request)) + if err != nil { + return err + } + req.Header.Set("Content-Type", "application/json") + req = req.WithContext(ctx) + + r, err := client.Do(req) // nolint:bodyclose if err != nil { return fmt.Errorf("client failed to make post request: %w", err) } - defer func(Body io.ReadCloser) { - closeErr := Body.Close() + + defer func(body io.ReadCloser) { + closeErr := body.Close() if closeErr != nil { logger.Warn("body close", "err", closeErr) } @@ -288,11 +343,12 @@ func post(client *http.Client, url, method, request string, response interface{} // subscribe connects to a websocket client and returns the subscription handler and a channel buffer func (req *requestGenerator) Subscribe(ctx context.Context, method SubMethod, subChan interface{}, args ...interface{}) (ethereum.Subscription, error) { - var err error - if req.subscriptionClient == nil { - req.subscriptionClient, err = rpc.DialWebsocket(ctx, "ws://"+req.target, "", req.logger) - + err := retryConnects(ctx, func(ctx context.Context) error { + var err error + req.subscriptionClient, err = rpc.DialWebsocket(ctx, "ws://"+req.target, "", req.logger) + return err + }) if err != nil { return nil, fmt.Errorf("failed to dial websocket: %v", err) } diff --git a/cmd/devnet/requests/trace.go b/cmd/devnet/requests/trace.go index 7d5b7938949..9ebc7b43729 100644 --- a/cmd/devnet/requests/trace.go +++ b/cmd/devnet/requests/trace.go @@ -113,7 +113,7 @@ func (reqGen *requestGenerator) TraceCall(blockRef rpc.BlockReference, args etha } method, body := reqGen.traceCall(blockRef, string(argsVal), string(optsVal)) - res := reqGen.call(method, body, &b) + res := reqGen.rpcCallJSON(method, body, &b) if res.Err != nil { return nil, fmt.Errorf("TraceCall rpc failed: %w", res.Err) @@ -134,7 +134,7 @@ func (req *requestGenerator) traceCall(blockRef rpc.BlockReference, callArgs str func (reqGen *requestGenerator) TraceTransaction(hash libcommon.Hash) ([]TransactionTrace, error) { var result []TransactionTrace - if err := reqGen.callCli(&result, Methods.TraceTransaction, hash); err != nil { + if err := reqGen.rpcCall(&result, Methods.TraceTransaction, hash); err != nil { return nil, err } diff --git a/cmd/devnet/requests/transaction.go b/cmd/devnet/requests/transaction.go index 2df6d068bfc..06d0be67618 100644 --- a/cmd/devnet/requests/transaction.go +++ b/cmd/devnet/requests/transaction.go @@ -78,7 +78,7 @@ func (reqGen *requestGenerator) EstimateGas(args ethereum.CallMsg, blockRef Bloc } method, body := reqGen.estimateGas(string(argsVal), blockRef) - res := reqGen.call(method, body, &b) + res := reqGen.rpcCallJSON(method, body, &b) if res.Err != nil { return 0, fmt.Errorf("EstimateGas rpc failed: %w", res.Err) @@ -100,7 +100,7 @@ func (req *requestGenerator) estimateGas(callArgs string, blockRef BlockNumber) func (reqGen *requestGenerator) GasPrice() (*big.Int, error) { var result hexutil.Big - if err := reqGen.callCli(&result, Methods.ETHGasPrice); err != nil { + if err := reqGen.rpcCall(&result, Methods.ETHGasPrice); err != nil { return nil, err } @@ -110,7 +110,7 @@ func (reqGen *requestGenerator) GasPrice() (*big.Int, error) { func (reqGen *requestGenerator) Call(args ethapi.CallArgs, blockRef rpc.BlockReference, overrides *ethapi.StateOverrides) ([]byte, error) { var result hexutility.Bytes - if err := reqGen.callCli(&result, Methods.ETHCall, args, blockRef, overrides); err != nil { + if err := reqGen.rpcCall(&result, Methods.ETHCall, args, blockRef, overrides); err != nil { return nil, err } @@ -125,7 +125,7 @@ func (reqGen *requestGenerator) SendTransaction(signedTx types.Transaction) (lib return libcommon.Hash{}, fmt.Errorf("failed to marshal binary: %v", err) } - if err := reqGen.callCli(&result, Methods.ETHSendRawTransaction, hexutility.Bytes(buf.Bytes())); err != nil { + if err := reqGen.rpcCall(&result, Methods.ETHSendRawTransaction, hexutility.Bytes(buf.Bytes())); err != nil { return libcommon.Hash{}, err } @@ -148,7 +148,7 @@ func (reqGen *requestGenerator) SendTransaction(signedTx types.Transaction) (lib func (req *requestGenerator) GetTransactionByHash(hash libcommon.Hash) (*jsonrpc.RPCTransaction, error) { var result jsonrpc.RPCTransaction - if err := req.callCli(&result, Methods.ETHGetTransactionByHash, hash); err != nil { + if err := req.rpcCall(&result, Methods.ETHGetTransactionByHash, hash); err != nil { return nil, err } @@ -158,7 +158,7 @@ func (req *requestGenerator) GetTransactionByHash(hash libcommon.Hash) (*jsonrpc func (req *requestGenerator) GetTransactionReceipt(hash libcommon.Hash) (*types.Receipt, error) { var result types.Receipt - if err := req.callCli(&result, Methods.ETHGetTransactionReceipt, hash); err != nil { + if err := req.rpcCall(&result, Methods.ETHGetTransactionReceipt, hash); err != nil { return nil, err } diff --git a/cmd/devnet/requests/tx.go b/cmd/devnet/requests/tx.go index 2d32a776221..ec2da47133e 100644 --- a/cmd/devnet/requests/tx.go +++ b/cmd/devnet/requests/tx.go @@ -18,7 +18,7 @@ func (reqGen *requestGenerator) TxpoolContent() (int, int, int, error) { ) method, body := reqGen.txpoolContent() - if res := reqGen.call(method, body, &b); res.Err != nil { + if res := reqGen.rpcCallJSON(method, body, &b); res.Err != nil { return len(pending), len(queued), len(baseFee), fmt.Errorf("failed to fetch txpool content: %v", res.Err) } diff --git a/cmd/devnet/services/accounts/faucet.go b/cmd/devnet/services/accounts/faucet.go index 92279992d76..5a0b88b6dd4 100644 --- a/cmd/devnet/services/accounts/faucet.go +++ b/cmd/devnet/services/accounts/faucet.go @@ -214,7 +214,7 @@ func (f *Faucet) NodeCreated(ctx context.Context, node devnet.Node) { func (f *Faucet) NodeStarted(ctx context.Context, node devnet.Node) { logger := devnet.Logger(ctx) - if strings.HasPrefix(node.Name(), f.chainName) && node.IsBlockProducer() { + if strings.HasPrefix(node.GetName(), f.chainName) && node.IsBlockProducer() { f.Lock() defer f.Unlock() diff --git a/cmd/devnet/services/polygon/checkpoint.go b/cmd/devnet/services/polygon/checkpoint.go index 9e8af1f5e8b..5dcd0d0164b 100644 --- a/cmd/devnet/services/polygon/checkpoint.go +++ b/cmd/devnet/services/polygon/checkpoint.go @@ -126,7 +126,11 @@ func (h *Heimdall) startChildHeaderSubscription(ctx context.Context) { for childHeader := range childHeaderChan { if err := h.handleChildHeader(ctx, childHeader); err != nil { - h.logger.Error("L2 header processing failed", "header", childHeader.Number, "err", err) + if errors.Is(err, notEnoughChildChainTxConfirmationsError) { + h.logger.Info("L2 header processing skipped", "header", childHeader.Number, "err", err) + } else { + h.logger.Error("L2 header processing failed", "header", childHeader.Number, "err", err) + } } } } @@ -149,6 +153,8 @@ func (h *Heimdall) startRootHeaderBlockSubscription() { } } +var notEnoughChildChainTxConfirmationsError = errors.New("the chain doesn't have enough blocks for ChildChainTxConfirmations") + func (h *Heimdall) handleChildHeader(ctx context.Context, header *types.Header) error { h.logger.Debug("no of checkpoint confirmations required", "childChainTxConfirmations", h.checkpointConfig.ChildChainTxConfirmations) @@ -156,9 +162,7 @@ func (h *Heimdall) handleChildHeader(ctx context.Context, header *types.Header) latestConfirmedChildBlock := header.Number.Int64() - int64(h.checkpointConfig.ChildChainTxConfirmations) if latestConfirmedChildBlock <= 0 { - h.logger.Error("no of blocks on childchain is less than confirmations required", - "childChainBlocks", header.Number.Uint64(), "confirmationsRequired", h.checkpointConfig.ChildChainTxConfirmations) - return errors.New("no of blocks on childchain is less than confirmations required") + return notEnoughChildChainTxConfirmationsError } timeStamp := uint64(time.Now().Unix()) diff --git a/cmd/devnet/services/polygon/heimdall.go b/cmd/devnet/services/polygon/heimdall.go index 3eb6d3f1837..a55ce00491e 100644 --- a/cmd/devnet/services/polygon/heimdall.go +++ b/cmd/devnet/services/polygon/heimdall.go @@ -256,14 +256,18 @@ func (h *Heimdall) NodeCreated(ctx context.Context, node devnet.Node) { h.Lock() defer h.Unlock() - if strings.HasPrefix(node.Name(), "bor") && node.IsBlockProducer() && node.Account() != nil { + if strings.HasPrefix(node.GetName(), "bor") && node.IsBlockProducer() && node.Account() != nil { // TODO configurable voting power h.addValidator(node.Account().Address, 1000, 0) } } func (h *Heimdall) NodeStarted(ctx context.Context, node devnet.Node) { - if !strings.HasPrefix(node.Name(), "bor") && node.IsBlockProducer() { + if h.validatorSet == nil { + panic("Heimdall devnet service: unexpected empty validator set! Call addValidator() before starting nodes.") + } + + if !strings.HasPrefix(node.GetName(), "bor") && node.IsBlockProducer() { h.Lock() defer h.Unlock() @@ -276,7 +280,9 @@ func (h *Heimdall) NodeStarted(ctx context.Context, node devnet.Node) { transactOpts, err := bind.NewKeyedTransactorWithChainID(accounts.SigKey(node.Account().Address), node.ChainID()) if err != nil { + h.Unlock() h.unsubscribe() + h.Lock() h.logger.Error("Failed to deploy state sender", "err", err) return } @@ -320,7 +326,7 @@ func (h *Heimdall) NodeStarted(ctx context.Context, node devnet.Node) { h.logger.Info("RootChain deployed", "chain", h.chainConfig.ChainName, "block", blocks[syncTx.Hash()].Number, "addr", h.rootChainAddress) h.logger.Info("StateSender deployed", "chain", h.chainConfig.ChainName, "block", blocks[syncTx.Hash()].Number, "addr", h.syncSenderAddress) - go h.startStateSyncSubacription() + go h.startStateSyncSubscription() go h.startChildHeaderSubscription(deployCtx) go h.startRootHeaderBlockSubscription() }() diff --git a/cmd/devnet/services/polygon/proofgenerator.go b/cmd/devnet/services/polygon/proofgenerator.go index 05216c07890..3326639d7b0 100644 --- a/cmd/devnet/services/polygon/proofgenerator.go +++ b/cmd/devnet/services/polygon/proofgenerator.go @@ -38,7 +38,7 @@ func NewProofGenerator() *ProofGenerator { func (pg *ProofGenerator) NodeCreated(ctx context.Context, node devnet.Node) { if pg.heimdall == nil { - if strings.HasPrefix(node.Name(), "bor") { + if strings.HasPrefix(node.GetName(), "bor") { if network := devnet.CurrentNetwork(ctx); network != nil { for _, service := range network.Services { if heimdall, ok := service.(*Heimdall); ok { diff --git a/cmd/devnet/services/polygon/statesync.go b/cmd/devnet/services/polygon/statesync.go index d055b6397ef..0429f5085db 100644 --- a/cmd/devnet/services/polygon/statesync.go +++ b/cmd/devnet/services/polygon/statesync.go @@ -23,7 +23,7 @@ type EventRecordWithBlock struct { BlockNumber uint64 } -func (h *Heimdall) startStateSyncSubacription() { +func (h *Heimdall) startStateSyncSubscription() { var err error syncChan := make(chan *contracts.TestStateSenderStateSynced, 100) diff --git a/cmd/devnet/transactions/tx.go b/cmd/devnet/transactions/tx.go index 7298fb41089..f56775094e9 100644 --- a/cmd/devnet/transactions/tx.go +++ b/cmd/devnet/transactions/tx.go @@ -41,7 +41,7 @@ func CheckTxPoolContent(ctx context.Context, expectedPendingSize, expectedQueued } if expectedPendingSize >= 0 && pendingSize != expectedPendingSize { - logger.Error("FAILURE mismatched pending subpool size", "expected", expectedPendingSize, "got", pendingSize) + logger.Debug("FAILURE mismatched pending subpool size", "expected", expectedPendingSize, "got", pendingSize) return } @@ -51,7 +51,7 @@ func CheckTxPoolContent(ctx context.Context, expectedPendingSize, expectedQueued } if expectedBaseFeeSize >= 0 && baseFeeSize != expectedBaseFeeSize { - logger.Error("FAILURE mismatched basefee subpool size", "expected", expectedBaseFeeSize, "got", baseFeeSize) + logger.Debug("FAILURE mismatched basefee subpool size", "expected", expectedBaseFeeSize, "got", baseFeeSize) } logger.Info("Subpool sizes", "pending", pendingSize, "queued", queuedSize, "basefee", baseFeeSize) @@ -335,7 +335,12 @@ func signEIP1559TxsHigherThanBaseFee(ctx context.Context, n int, baseFeePerGas u devnet.Logger(ctx).Info("HIGHER", "transaction", i, "nonce", transaction.Nonce, "value", transaction.Value, "feecap", transaction.FeeCap) - signedTransaction, err := types.SignTx(transaction, signer, accounts.SigKey(fromAddress)) + signerKey := accounts.SigKey(fromAddress) + if signerKey == nil { + return nil, fmt.Errorf("devnet.signEIP1559TxsHigherThanBaseFee failed to SignTx: private key not found for address %s", fromAddress) + } + + signedTransaction, err := types.SignTx(transaction, signer, signerKey) if err != nil { return nil, err } diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index e1e1164b0e0..6296546a60d 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -1625,7 +1625,7 @@ func SetEthConfig(ctx *cli.Context, nodeConfig *nodecfg.Config, cfg *ethconfig.C } case networkname.DevChainName: if !ctx.IsSet(NetworkIdFlag.Name) { - cfg.NetworkID = 1337 + cfg.NetworkID = params.NetworkIDByChainName(chain) } // Create new developer account or reuse existing one diff --git a/consensus/bor/bor.go b/consensus/bor/bor.go index 103e9d32aa3..b9434fa9e2b 100644 --- a/consensus/bor/bor.go +++ b/consensus/bor/bor.go @@ -1214,12 +1214,6 @@ func (c *Bor) Seal(chain consensus.ChainHeaderReader, block *types.Block, result // wiggle was already accounted for in header.Time, this is just for logging wiggle := time.Duration(successionNumber) * time.Duration(c.config.CalculateBackupMultiplier(number)) * time.Second - // temp for testing - if wiggle > 0 { - wiggle = 500 * time.Millisecond - } - // temp for testing - // Sign all the things! sighash, err := signFn(signer, accounts.MimetypeBor, BorRLP(header, c.config)) if err != nil { diff --git a/params/config.go b/params/config.go index 4d001b7eccd..c9ea236f520 100644 --- a/params/config.go +++ b/params/config.go @@ -195,6 +195,8 @@ func ChainConfigByChainName(chain string) *chain.Config { switch chain { case networkname.MainnetChainName: return MainnetChainConfig + case networkname.DevChainName: + return AllCliqueProtocolChanges case networkname.HoleskyChainName: return HoleskyChainConfig case networkname.SepoliaChainName: @@ -267,16 +269,11 @@ func ChainConfigByGenesisHash(genesisHash libcommon.Hash) *chain.Config { } func NetworkIDByChainName(chain string) uint64 { - switch chain { - case networkname.DevChainName: - return 1337 - default: - config := ChainConfigByChainName(chain) - if config == nil { - return 0 - } - return config.ChainID.Uint64() + config := ChainConfigByChainName(chain) + if config == nil { + return 0 } + return config.ChainID.Uint64() } func IsChainPoS(chainConfig *chain.Config, currentTDProvider func() *big.Int) bool { diff --git a/rpc/http.go b/rpc/http.go index f6812a6cfc3..a1938b585b2 100644 --- a/rpc/http.go +++ b/rpc/http.go @@ -108,21 +108,11 @@ func DialHTTP(endpoint string, logger log.Logger) (*Client, error) { func (c *Client) sendHTTP(ctx context.Context, op *requestOp, msg interface{}) error { hc := c.writeConn.(*httpConn) respBody, err := hc.doRequest(ctx, msg) - if respBody != nil { - defer respBody.Close() - } - if err != nil { - if respBody != nil { - buf := new(bytes.Buffer) - if _, err2 := buf.ReadFrom(respBody); err2 == nil { - return fmt.Errorf("%w: %v", err, buf.String()) - } - } return err } var respmsg jsonrpcMessage - if err := json.NewDecoder(respBody).Decode(&respmsg); err != nil { + if err := json.Unmarshal(respBody, &respmsg); err != nil { return err } op.resp <- &respmsg @@ -135,9 +125,8 @@ func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonr if err != nil { return err } - defer respBody.Close() var respmsgs []jsonrpcMessage - if err := json.NewDecoder(respBody).Decode(&respmsgs); err != nil { + if err := json.Unmarshal(respBody, &respmsgs); err != nil { return err } for i := 0; i < len(respmsgs); i++ { @@ -146,7 +135,7 @@ func (c *Client) sendBatchHTTP(ctx context.Context, op *requestOp, msgs []*jsonr return nil } -func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadCloser, error) { +func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) ([]byte, error) { body, err := json.Marshal(msg) if err != nil { return nil, err @@ -167,10 +156,19 @@ func (hc *httpConn) doRequest(ctx context.Context, msg interface{}) (io.ReadClos if err != nil { return nil, err } + defer func() { _ = resp.Body.Close() }() + + // read the response body + respBody, err := io.ReadAll(resp.Body) + if err != nil { + return nil, err + } + if resp.StatusCode < 200 || resp.StatusCode >= 300 { - return resp.Body, errors.New(resp.Status) + return nil, fmt.Errorf("%s: %s", resp.Status, string(respBody)) } - return resp.Body, nil + + return respBody, nil } // httpServerConn turns a HTTP connection into a Conn. diff --git a/rpc/websocket.go b/rpc/websocket.go index 1901a9f655a..ce945e656de 100644 --- a/rpc/websocket.go +++ b/rpc/websocket.go @@ -125,6 +125,10 @@ func (e wsHandshakeError) Error() string { return s } +func (e wsHandshakeError) Unwrap() error { + return e.err +} + func originIsAllowed(allowedOrigins mapset.Set[string], browserOrigin string, logger log.Logger) bool { it := allowedOrigins.Iterator() for origin := range it.C { From 35696afca12476612d93a7bd6c57393fc9b69d6d Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Wed, 1 Nov 2023 11:44:01 +0100 Subject: [PATCH 39/44] tests: test that erigon can be used as a library (#8494) --- .github/workflows/test-integration.yml | 5 +++++ Makefile | 18 ++++++++++-------- tests/erigon-ext-test/.gitignore | 1 + tests/erigon-ext-test/go.mod | 2 ++ tests/erigon-ext-test/go.mod.template | 9 +++++++++ tests/erigon-ext-test/main.go | 18 ++++++++++++++++++ tests/erigon-ext-test/test.sh | 10 ++++++++++ 7 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 tests/erigon-ext-test/.gitignore create mode 100644 tests/erigon-ext-test/go.mod create mode 100644 tests/erigon-ext-test/go.mod.template create mode 100644 tests/erigon-ext-test/main.go create mode 100755 tests/erigon-ext-test/test.sh diff --git a/.github/workflows/test-integration.yml b/.github/workflows/test-integration.yml index ec526d3f3fa..dd90ea72721 100644 --- a/.github/workflows/test-integration.yml +++ b/.github/workflows/test-integration.yml @@ -29,6 +29,11 @@ jobs: - name: test-integration run: make test-integration + - name: Test erigon as a library + env: + GIT_COMMIT: ${{ github.event.pull_request.head.sha || github.sha }} + run: make test-erigon-ext GIT_COMMIT=$GIT_COMMIT + # name: history-v3-test-integration # run: make test3-integration diff --git a/Makefile b/Makefile index 54270f7870f..c7f1cab165d 100644 --- a/Makefile +++ b/Makefile @@ -140,22 +140,24 @@ db-tools: rm -rf vendor @echo "Run \"$(GOBIN)/mdbx_stat -h\" to get info about mdbx db file." -## test: run unit tests with a 100s timeout -test: +test-erigon-lib: @cd erigon-lib && $(MAKE) test + +test-erigon-ext: + @cd tests/erigon-ext-test && ./test.sh $(GIT_COMMIT) + +## test: run unit tests with a 100s timeout +test: test-erigon-lib $(GOTEST) --timeout 10m -test3: - @cd erigon-lib && $(MAKE) test +test3: test-erigon-lib $(GOTEST) --timeout 10m -tags $(BUILD_TAGS),e3 ## test-integration: run integration tests with a 30m timeout -test-integration: - @cd erigon-lib && $(MAKE) test +test-integration: test-erigon-lib $(GOTEST) --timeout 240m -tags $(BUILD_TAGS),integration -test3-integration: - @cd erigon-lib && $(MAKE) test +test3-integration: test-erigon-lib $(GOTEST) --timeout 240m -tags $(BUILD_TAGS),integration,e3 ## lint-deps: install lint dependencies diff --git a/tests/erigon-ext-test/.gitignore b/tests/erigon-ext-test/.gitignore new file mode 100644 index 00000000000..08cb523c182 --- /dev/null +++ b/tests/erigon-ext-test/.gitignore @@ -0,0 +1 @@ +go.sum diff --git a/tests/erigon-ext-test/go.mod b/tests/erigon-ext-test/go.mod new file mode 100644 index 00000000000..64cb7ad1672 --- /dev/null +++ b/tests/erigon-ext-test/go.mod @@ -0,0 +1,2 @@ +// this is a dummy file needed to exclude this folder from the root folder unit tests suite +// the actual go.mod for the test is generated by test.sh from go.mod.template diff --git a/tests/erigon-ext-test/go.mod.template b/tests/erigon-ext-test/go.mod.template new file mode 100644 index 00000000000..515b3b14281 --- /dev/null +++ b/tests/erigon-ext-test/go.mod.template @@ -0,0 +1,9 @@ +module example.com/erigon-ext-test + +go 1.20 + +require github.com/ledgerwatch/erigon $COMMIT_SHA + +replace github.com/ledgerwatch/erigon-lib => github.com/ledgerwatch/erigon/erigon-lib $COMMIT_SHA + +require github.com/ethereum/go-ethereum v1.13.3 diff --git a/tests/erigon-ext-test/main.go b/tests/erigon-ext-test/main.go new file mode 100644 index 00000000000..b8322f5973e --- /dev/null +++ b/tests/erigon-ext-test/main.go @@ -0,0 +1,18 @@ +package main + +import ( + geth_params "github.com/ethereum/go-ethereum/params" + // geth_crypto "github.com/ethereum/go-ethereum/crypto" + erigon_lib_common "github.com/ledgerwatch/erigon-lib/common" + erigon_crypto "github.com/ledgerwatch/erigon/crypto" + erigon_params "github.com/ledgerwatch/erigon/params" +) + +func main() { + println("Erigon version: ", erigon_params.Version) + println("geth version: ", geth_params.Version) + println("Erigon lib common eth Wei: ", erigon_lib_common.Wei) + println("Erigon crypto secp256k1 S256 BitSize: ", erigon_crypto.S256().Params().BitSize) + // not working due to duplicate symbols errors + // println("geth crypto secp256k1 S256 BitSize: ", geth_crypto.S256().Params().BitSize) +} diff --git a/tests/erigon-ext-test/test.sh b/tests/erigon-ext-test/test.sh new file mode 100755 index 00000000000..362028e5fe7 --- /dev/null +++ b/tests/erigon-ext-test/test.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +COMMIT_SHA="$1" + +sed "s/\$COMMIT_SHA/$COMMIT_SHA/" go.mod.template > go.mod + +rm -f go.sum +go mod tidy + +go run main.go From 329d18ef6fa53ba77559d9953c89dd377476767f Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Wed, 1 Nov 2023 23:22:35 +0700 Subject: [PATCH 40/44] snapshots: reduce merge limit of blocks to 100K (#8614) Reason: - produce and seed snapshots earlier on chain tip. reduce depnedency on "good peers with history" at p2p-network. Some networks have no much archive peers, also ConsensusLayer clients are not-good(not-incentivised) at serving history. - avoiding having too much files: more files(shards) - means "more metadata", "more lookups for non-indexed queries", "more dictionaries", "more bittorrent connections", ... less files - means small files will be removed after merge (no peers for this files). ToDo: [x] Recent 500K - merge up to 100K [x] Older than 500K - merge up to 500K [x] Start seeding 100k files [x] Stop seeding 100k files after merge (right before delete) In next PR: [] Old version of Erigon must be able download recent hashes. To achieve it - at first start erigon will download preverified hashes .toml from s3 - if it's newer that what we have (build-in) - use it. --- cmd/downloader/main.go | 2 + cmd/integration/commands/stages.go | 2 +- erigon-lib/direct/downloader_client.go | 3 + .../downloader/downloader_grpc_server.go | 31 ++- .../downloader/downloadercfg/downloadercfg.go | 6 +- erigon-lib/downloader/snaptype/files.go | 10 +- erigon-lib/go.mod | 4 +- erigon-lib/go.sum | 8 +- .../gointerfaces/downloader/downloader.pb.go | 201 ++++++++++++------ .../downloader/downloader_grpc.pb.go | 37 ++++ eth/backend.go | 2 +- eth/stagedsync/stage_snapshots.go | 14 +- go.mod | 2 +- go.sum | 4 +- turbo/app/snapshots_cmd.go | 4 +- turbo/services/interfaces.go | 2 +- .../freezeblocks/block_snapshots.go | 110 ++++++---- .../freezeblocks/block_snapshots_test.go | 74 +++++-- .../freezeblocks/bor_snapshots.go | 79 ++++--- turbo/snapshotsync/snapshotsync.go | 6 +- turbo/stages/mock/mock_sentry.go | 2 +- 21 files changed, 414 insertions(+), 189 deletions(-) diff --git a/cmd/downloader/main.go b/cmd/downloader/main.go index 7ae1bcdf6be..4d702b102e5 100644 --- a/cmd/downloader/main.go +++ b/cmd/downloader/main.go @@ -7,6 +7,7 @@ import ( "net" "os" "path/filepath" + "runtime" "strings" "time" @@ -177,6 +178,7 @@ func Downloader(ctx context.Context, logger log.Logger) error { return err } + cfg.ClientConfig.PieceHashersPerTorrent = 4 * runtime.NumCPU() cfg.ClientConfig.DisableIPv6 = disableIPV6 cfg.ClientConfig.DisableIPv4 = disableIPV4 diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index 9849a7bad80..8896ae7b27d 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -1551,7 +1551,7 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig, } notifications := &shards.Notifications{} - blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, freezeblocks.MergeSteps, db, notifications.Events, logger) + blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, db, notifications.Events, logger) stages := stages2.NewDefaultStages(context.Background(), db, p2p.Config{}, &cfg, sentryControlServer, notifications, nil, blockReader, blockRetire, agg, nil, nil, heimdallClient, logger) sync := stagedsync.New(stages, stagedsync.DefaultUnwindOrder, stagedsync.DefaultPruneOrder, logger) diff --git a/erigon-lib/direct/downloader_client.go b/erigon-lib/direct/downloader_client.go index a6924a1ebe7..abb85adc88f 100644 --- a/erigon-lib/direct/downloader_client.go +++ b/erigon-lib/direct/downloader_client.go @@ -35,6 +35,9 @@ func NewDownloaderClient(server proto_downloader.DownloaderServer) *DownloaderCl func (c *DownloaderClient) Download(ctx context.Context, in *proto_downloader.DownloadRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { return c.server.Download(ctx, in) } +func (c *DownloaderClient) Delete(ctx context.Context, in *proto_downloader.DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + return c.server.Delete(ctx, in) +} func (c *DownloaderClient) Verify(ctx context.Context, in *proto_downloader.VerifyRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { return c.server.Verify(ctx, in) } diff --git a/erigon-lib/downloader/downloader_grpc_server.go b/erigon-lib/downloader/downloader_grpc_server.go index 8ac52512871..61398d74bcd 100644 --- a/erigon-lib/downloader/downloader_grpc_server.go +++ b/erigon-lib/downloader/downloader_grpc_server.go @@ -19,6 +19,8 @@ package downloader import ( "context" "fmt" + "os" + "path/filepath" "time" "github.com/anacrolix/torrent/metainfo" @@ -44,6 +46,7 @@ type GrpcServer struct { // Download - create new .torrent ONLY if initialSync, everything else Erigon can generate by itself func (s *GrpcServer) Download(ctx context.Context, request *proto_downloader.DownloadRequest) (*emptypb.Empty, error) { + defer s.d.ReCalcStats(10 * time.Second) // immediately call ReCalc to set stat.Complete flag logEvery := time.NewTicker(20 * time.Second) defer logEvery.Stop() @@ -70,7 +73,33 @@ func (s *GrpcServer) Download(ctx context.Context, request *proto_downloader.Dow return nil, err } } - s.d.ReCalcStats(10 * time.Second) // immediately call ReCalc to set stat.Complete flag + return &emptypb.Empty{}, nil +} + +// Delete - stop seeding, remove file, remove .torrent +func (s *GrpcServer) Delete(ctx context.Context, request *proto_downloader.DeleteRequest) (*emptypb.Empty, error) { + defer s.d.ReCalcStats(10 * time.Second) // immediately call ReCalc to set stat.Complete flag + torrents := s.d.torrentClient.Torrents() + for _, name := range request.Paths { + if name == "" { + return nil, fmt.Errorf("field 'path' is required") + } + for _, t := range torrents { + select { + case <-t.GotInfo(): + continue + default: + } + if t.Name() == name { + t.Drop() + break + } + } + + fPath := filepath.Join(s.d.SnapDir(), name) + _ = os.Remove(fPath) + _ = os.Remove(fPath + ".torrent") + } return &emptypb.Empty{}, nil } diff --git a/erigon-lib/downloader/downloadercfg/downloadercfg.go b/erigon-lib/downloader/downloadercfg/downloadercfg.go index dadc4d3376b..b9e1d0dc289 100644 --- a/erigon-lib/downloader/downloadercfg/downloadercfg.go +++ b/erigon-lib/downloader/downloadercfg/downloadercfg.go @@ -29,7 +29,6 @@ import ( lg "github.com/anacrolix/log" "github.com/anacrolix/torrent" "github.com/c2h5oh/datasize" - "github.com/ledgerwatch/erigon-lib/common/cmp" "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/ledgerwatch/erigon-lib/common/dir" "github.com/ledgerwatch/log/v3" @@ -60,7 +59,10 @@ type Cfg struct { func Default() *torrent.ClientConfig { torrentConfig := torrent.NewDefaultClientConfig() - torrentConfig.PieceHashersPerTorrent = cmp.Max(1, runtime.NumCPU()-1) + // better don't increase because erigon periodically producing "new seedable files" - and adding them to downloader. + // it must not impact chain tip sync - so, limit resources to minimum by default. + // but when downloader is started as a separated process - rise it to max + //torrentConfig.PieceHashersPerTorrent = cmp.Max(1, runtime.NumCPU()-1) torrentConfig.MinDialTimeout = 6 * time.Second //default: 3s torrentConfig.HandshakesTimeout = 8 * time.Second //default: 4s diff --git a/erigon-lib/downloader/snaptype/files.go b/erigon-lib/downloader/snaptype/files.go index 562fe159f4f..069707cfe29 100644 --- a/erigon-lib/downloader/snaptype/files.go +++ b/erigon-lib/downloader/snaptype/files.go @@ -44,6 +44,8 @@ const ( BeaconBlocks ) +var BorSnapshotTypes = []Type{BorEvents, BorSpans} + func (ft Type) String() string { switch ft { case Headers: @@ -90,7 +92,7 @@ const ( func (it IdxType) String() string { return string(it) } -var AllSnapshotTypes = []Type{Headers, Bodies, Transactions} +var BlockSnapshotTypes = []Type{Headers, Bodies, Transactions} var ( ErrInvalidFileName = fmt.Errorf("invalid compressed file name") @@ -175,8 +177,10 @@ type FileInfo struct { } func (f FileInfo) TorrentFileExists() bool { return dir.FileExist(f.Path + ".torrent") } -func (f FileInfo) Seedable() bool { return f.To-f.From == Erigon2MergeLimit } -func (f FileInfo) NeedTorrentFile() bool { return f.Seedable() && !f.TorrentFileExists() } +func (f FileInfo) Seedable() bool { + return f.To-f.From == Erigon2MergeLimit || f.To-f.From == Erigon2RecentMergeLimit +} +func (f FileInfo) NeedTorrentFile() bool { return f.Seedable() && !f.TorrentFileExists() } func IdxFiles(dir string) (res []FileInfo, err error) { return FilesWithExt(dir, ".idx") } func Segments(dir string) (res []FileInfo, err error) { return FilesWithExt(dir, ".seg") } diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index 109b392334f..0b664a64784 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -4,8 +4,8 @@ go 1.20 require ( github.com/erigontech/mdbx-go v0.35.2-0.20231101074031-9f999220e9ed - github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3 - github.com/ledgerwatch/interfaces v0.0.0-20231011121315-f58b806039f0 + github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66 + github.com/ledgerwatch/interfaces v0.0.0-20231031050643-c86352e41520 github.com/ledgerwatch/log/v3 v3.9.0 github.com/ledgerwatch/secp256k1 v1.0.0 ) diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index e99a7f6a4e8..b979ec8ea6e 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -291,10 +291,10 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3 h1:59TKwBsS+Fn4iGh+PCxw7s73+/0WmDeK6bskDe3tFzY= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231019214918-3eb2303a41f3/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= -github.com/ledgerwatch/interfaces v0.0.0-20231011121315-f58b806039f0 h1:7z6cyoCKP6qxtKSO74eAY6XiHWKaOi+melvPeMCXLl8= -github.com/ledgerwatch/interfaces v0.0.0-20231011121315-f58b806039f0/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66 h1:0GY0mXeC6ThOw1x50tF1dDWso0kL6a5SS7k/zrsIF60= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= +github.com/ledgerwatch/interfaces v0.0.0-20231031050643-c86352e41520 h1:j/PRJWbPrbk8wpVjU77SWS8xJ/N+dcxPs1relNSolUs= +github.com/ledgerwatch/interfaces v0.0.0-20231031050643-c86352e41520/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= github.com/ledgerwatch/log/v3 v3.9.0/go.mod h1:EiAY6upmI/6LkNhOVxb4eVsmsP11HZCnZ3PlJMjYiqE= github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= diff --git a/erigon-lib/gointerfaces/downloader/downloader.pb.go b/erigon-lib/gointerfaces/downloader/downloader.pb.go index 773282e315b..e7dfe2f04cd 100644 --- a/erigon-lib/gointerfaces/downloader/downloader.pb.go +++ b/erigon-lib/gointerfaces/downloader/downloader.pb.go @@ -127,6 +127,54 @@ func (x *DownloadRequest) GetItems() []*DownloadItem { return nil } +// DeleteRequest: stop seeding, delete file, delete .torrent +type DeleteRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Paths []string `protobuf:"bytes,1,rep,name=paths,proto3" json:"paths,omitempty"` +} + +func (x *DeleteRequest) Reset() { + *x = DeleteRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_downloader_downloader_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *DeleteRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*DeleteRequest) ProtoMessage() {} + +func (x *DeleteRequest) ProtoReflect() protoreflect.Message { + mi := &file_downloader_downloader_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use DeleteRequest.ProtoReflect.Descriptor instead. +func (*DeleteRequest) Descriptor() ([]byte, []int) { + return file_downloader_downloader_proto_rawDescGZIP(), []int{2} +} + +func (x *DeleteRequest) GetPaths() []string { + if x != nil { + return x.Paths + } + return nil +} + type VerifyRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -136,7 +184,7 @@ type VerifyRequest struct { func (x *VerifyRequest) Reset() { *x = VerifyRequest{} if protoimpl.UnsafeEnabled { - mi := &file_downloader_downloader_proto_msgTypes[2] + mi := &file_downloader_downloader_proto_msgTypes[3] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -149,7 +197,7 @@ func (x *VerifyRequest) String() string { func (*VerifyRequest) ProtoMessage() {} func (x *VerifyRequest) ProtoReflect() protoreflect.Message { - mi := &file_downloader_downloader_proto_msgTypes[2] + mi := &file_downloader_downloader_proto_msgTypes[3] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -162,7 +210,7 @@ func (x *VerifyRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use VerifyRequest.ProtoReflect.Descriptor instead. func (*VerifyRequest) Descriptor() ([]byte, []int) { - return file_downloader_downloader_proto_rawDescGZIP(), []int{2} + return file_downloader_downloader_proto_rawDescGZIP(), []int{3} } type StatsRequest struct { @@ -174,7 +222,7 @@ type StatsRequest struct { func (x *StatsRequest) Reset() { *x = StatsRequest{} if protoimpl.UnsafeEnabled { - mi := &file_downloader_downloader_proto_msgTypes[3] + mi := &file_downloader_downloader_proto_msgTypes[4] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -187,7 +235,7 @@ func (x *StatsRequest) String() string { func (*StatsRequest) ProtoMessage() {} func (x *StatsRequest) ProtoReflect() protoreflect.Message { - mi := &file_downloader_downloader_proto_msgTypes[3] + mi := &file_downloader_downloader_proto_msgTypes[4] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -200,7 +248,7 @@ func (x *StatsRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use StatsRequest.ProtoReflect.Descriptor instead. func (*StatsRequest) Descriptor() ([]byte, []int) { - return file_downloader_downloader_proto_rawDescGZIP(), []int{3} + return file_downloader_downloader_proto_rawDescGZIP(), []int{4} } type StatsReply struct { @@ -228,7 +276,7 @@ type StatsReply struct { func (x *StatsReply) Reset() { *x = StatsReply{} if protoimpl.UnsafeEnabled { - mi := &file_downloader_downloader_proto_msgTypes[4] + mi := &file_downloader_downloader_proto_msgTypes[5] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -241,7 +289,7 @@ func (x *StatsReply) String() string { func (*StatsReply) ProtoMessage() {} func (x *StatsReply) ProtoReflect() protoreflect.Message { - mi := &file_downloader_downloader_proto_msgTypes[4] + mi := &file_downloader_downloader_proto_msgTypes[5] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -254,7 +302,7 @@ func (x *StatsReply) ProtoReflect() protoreflect.Message { // Deprecated: Use StatsReply.ProtoReflect.Descriptor instead. func (*StatsReply) Descriptor() ([]byte, []int) { - return file_downloader_downloader_proto_rawDescGZIP(), []int{4} + return file_downloader_downloader_proto_rawDescGZIP(), []int{5} } func (x *StatsReply) GetMetadataReady() int32 { @@ -345,47 +393,53 @@ var file_downloader_downloader_proto_rawDesc = []byte{ 0x12, 0x2e, 0x0a, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x49, 0x74, 0x65, 0x6d, 0x52, 0x05, 0x69, 0x74, 0x65, 0x6d, 0x73, - 0x22, 0x0f, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0xee, 0x02, 0x0a, 0x0a, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, - 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x72, 0x65, 0x61, - 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, - 0x74, 0x61, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x65, 0x73, - 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x66, 0x69, - 0x6c, 0x65, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x21, 0x0a, 0x0c, 0x70, 0x65, 0x65, 0x72, - 0x73, 0x5f, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, - 0x70, 0x65, 0x65, 0x72, 0x73, 0x55, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x63, - 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6d, - 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, - 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x02, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, - 0x73, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0e, 0x62, 0x79, 0x74, - 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, - 0x79, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, - 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, - 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x04, 0x52, 0x0a, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, - 0x0d, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x0b, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x61, - 0x74, 0x65, 0x32, 0xcb, 0x01, 0x0a, 0x0a, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, - 0x72, 0x12, 0x41, 0x0a, 0x08, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1b, 0x2e, - 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, - 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x06, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x12, 0x19, - 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x56, 0x65, 0x72, 0x69, - 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x05, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x64, + 0x22, 0x25, 0x0a, 0x0d, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, + 0x52, 0x05, 0x70, 0x61, 0x74, 0x68, 0x73, 0x22, 0x0f, 0x0a, 0x0d, 0x56, 0x65, 0x72, 0x69, 0x66, + 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x0e, 0x0a, 0x0c, 0x53, 0x74, 0x61, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0xee, 0x02, 0x0a, 0x0a, 0x53, 0x74, 0x61, + 0x74, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x25, 0x0a, 0x0e, 0x6d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x5f, 0x72, 0x65, 0x61, 0x64, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, + 0x0d, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x1f, + 0x0a, 0x0b, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, + 0x21, 0x0a, 0x0c, 0x70, 0x65, 0x65, 0x72, 0x73, 0x5f, 0x75, 0x6e, 0x69, 0x71, 0x75, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x70, 0x65, 0x65, 0x72, 0x73, 0x55, 0x6e, 0x69, 0x71, + 0x75, 0x65, 0x12, 0x2b, 0x0a, 0x11, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x10, 0x63, + 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x12, + 0x1c, 0x0a, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x1a, 0x0a, + 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x18, 0x07, 0x20, 0x01, 0x28, 0x02, 0x52, + 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x62, 0x79, 0x74, + 0x65, 0x73, 0x5f, 0x63, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x04, 0x52, 0x0e, 0x62, 0x79, 0x74, 0x65, 0x73, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x62, 0x79, 0x74, 0x65, 0x73, 0x5f, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x62, 0x79, 0x74, 0x65, 0x73, 0x54, 0x6f, + 0x74, 0x61, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x5f, 0x72, 0x61, + 0x74, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0a, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, + 0x52, 0x61, 0x74, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, + 0x5f, 0x72, 0x61, 0x74, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x04, 0x52, 0x0c, 0x64, 0x6f, 0x77, + 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x61, 0x74, 0x65, 0x32, 0x8a, 0x02, 0x0a, 0x0a, 0x44, 0x6f, + 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x12, 0x41, 0x0a, 0x08, 0x44, 0x6f, 0x77, 0x6e, + 0x6c, 0x6f, 0x61, 0x64, 0x12, 0x1b, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x44, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x06, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, + 0x65, 0x72, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x06, 0x56, 0x65, + 0x72, 0x69, 0x66, 0x79, 0x12, 0x19, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, + 0x72, 0x2e, 0x56, 0x65, 0x72, 0x69, 0x66, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x3b, 0x0a, 0x05, 0x53, 0x74, 0x61, + 0x74, 0x73, 0x12, 0x18, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, + 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, - 0x64, 0x65, 0x72, 0x2e, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, - 0x42, 0x19, 0x5a, 0x17, 0x2e, 0x2f, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, - 0x3b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x33, + 0x65, 0x70, 0x6c, 0x79, 0x22, 0x00, 0x42, 0x19, 0x5a, 0x17, 0x2e, 0x2f, 0x64, 0x6f, 0x77, 0x6e, + 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x72, 0x3b, 0x64, 0x6f, 0x77, 0x6e, 0x6c, 0x6f, 0x61, 0x64, 0x65, + 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -400,27 +454,30 @@ func file_downloader_downloader_proto_rawDescGZIP() []byte { return file_downloader_downloader_proto_rawDescData } -var file_downloader_downloader_proto_msgTypes = make([]protoimpl.MessageInfo, 5) +var file_downloader_downloader_proto_msgTypes = make([]protoimpl.MessageInfo, 6) var file_downloader_downloader_proto_goTypes = []interface{}{ (*DownloadItem)(nil), // 0: downloader.DownloadItem (*DownloadRequest)(nil), // 1: downloader.DownloadRequest - (*VerifyRequest)(nil), // 2: downloader.VerifyRequest - (*StatsRequest)(nil), // 3: downloader.StatsRequest - (*StatsReply)(nil), // 4: downloader.StatsReply - (*types.H160)(nil), // 5: types.H160 - (*emptypb.Empty)(nil), // 6: google.protobuf.Empty + (*DeleteRequest)(nil), // 2: downloader.DeleteRequest + (*VerifyRequest)(nil), // 3: downloader.VerifyRequest + (*StatsRequest)(nil), // 4: downloader.StatsRequest + (*StatsReply)(nil), // 5: downloader.StatsReply + (*types.H160)(nil), // 6: types.H160 + (*emptypb.Empty)(nil), // 7: google.protobuf.Empty } var file_downloader_downloader_proto_depIdxs = []int32{ - 5, // 0: downloader.DownloadItem.torrent_hash:type_name -> types.H160 + 6, // 0: downloader.DownloadItem.torrent_hash:type_name -> types.H160 0, // 1: downloader.DownloadRequest.items:type_name -> downloader.DownloadItem 1, // 2: downloader.Downloader.Download:input_type -> downloader.DownloadRequest - 2, // 3: downloader.Downloader.Verify:input_type -> downloader.VerifyRequest - 3, // 4: downloader.Downloader.Stats:input_type -> downloader.StatsRequest - 6, // 5: downloader.Downloader.Download:output_type -> google.protobuf.Empty - 6, // 6: downloader.Downloader.Verify:output_type -> google.protobuf.Empty - 4, // 7: downloader.Downloader.Stats:output_type -> downloader.StatsReply - 5, // [5:8] is the sub-list for method output_type - 2, // [2:5] is the sub-list for method input_type + 2, // 3: downloader.Downloader.Delete:input_type -> downloader.DeleteRequest + 3, // 4: downloader.Downloader.Verify:input_type -> downloader.VerifyRequest + 4, // 5: downloader.Downloader.Stats:input_type -> downloader.StatsRequest + 7, // 6: downloader.Downloader.Download:output_type -> google.protobuf.Empty + 7, // 7: downloader.Downloader.Delete:output_type -> google.protobuf.Empty + 7, // 8: downloader.Downloader.Verify:output_type -> google.protobuf.Empty + 5, // 9: downloader.Downloader.Stats:output_type -> downloader.StatsReply + 6, // [6:10] is the sub-list for method output_type + 2, // [2:6] is the sub-list for method input_type 2, // [2:2] is the sub-list for extension type_name 2, // [2:2] is the sub-list for extension extendee 0, // [0:2] is the sub-list for field type_name @@ -457,7 +514,7 @@ func file_downloader_downloader_proto_init() { } } file_downloader_downloader_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*VerifyRequest); i { + switch v := v.(*DeleteRequest); i { case 0: return &v.state case 1: @@ -469,7 +526,7 @@ func file_downloader_downloader_proto_init() { } } file_downloader_downloader_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*StatsRequest); i { + switch v := v.(*VerifyRequest); i { case 0: return &v.state case 1: @@ -481,6 +538,18 @@ func file_downloader_downloader_proto_init() { } } file_downloader_downloader_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*StatsRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_downloader_downloader_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*StatsReply); i { case 0: return &v.state @@ -499,7 +568,7 @@ func file_downloader_downloader_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_downloader_downloader_proto_rawDesc, NumEnums: 0, - NumMessages: 5, + NumMessages: 6, NumExtensions: 0, NumServices: 1, }, diff --git a/erigon-lib/gointerfaces/downloader/downloader_grpc.pb.go b/erigon-lib/gointerfaces/downloader/downloader_grpc.pb.go index 831743bbc71..d4520105f64 100644 --- a/erigon-lib/gointerfaces/downloader/downloader_grpc.pb.go +++ b/erigon-lib/gointerfaces/downloader/downloader_grpc.pb.go @@ -21,6 +21,7 @@ const _ = grpc.SupportPackageIsVersion7 const ( Downloader_Download_FullMethodName = "/downloader.Downloader/Download" + Downloader_Delete_FullMethodName = "/downloader.Downloader/Delete" Downloader_Verify_FullMethodName = "/downloader.Downloader/Verify" Downloader_Stats_FullMethodName = "/downloader.Downloader/Stats" ) @@ -30,6 +31,7 @@ const ( // For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream. type DownloaderClient interface { Download(ctx context.Context, in *DownloadRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) + Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) Verify(ctx context.Context, in *VerifyRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) Stats(ctx context.Context, in *StatsRequest, opts ...grpc.CallOption) (*StatsReply, error) } @@ -51,6 +53,15 @@ func (c *downloaderClient) Download(ctx context.Context, in *DownloadRequest, op return out, nil } +func (c *downloaderClient) Delete(ctx context.Context, in *DeleteRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { + out := new(emptypb.Empty) + err := c.cc.Invoke(ctx, Downloader_Delete_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *downloaderClient) Verify(ctx context.Context, in *VerifyRequest, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, Downloader_Verify_FullMethodName, in, out, opts...) @@ -74,6 +85,7 @@ func (c *downloaderClient) Stats(ctx context.Context, in *StatsRequest, opts ... // for forward compatibility type DownloaderServer interface { Download(context.Context, *DownloadRequest) (*emptypb.Empty, error) + Delete(context.Context, *DeleteRequest) (*emptypb.Empty, error) Verify(context.Context, *VerifyRequest) (*emptypb.Empty, error) Stats(context.Context, *StatsRequest) (*StatsReply, error) mustEmbedUnimplementedDownloaderServer() @@ -86,6 +98,9 @@ type UnimplementedDownloaderServer struct { func (UnimplementedDownloaderServer) Download(context.Context, *DownloadRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Download not implemented") } +func (UnimplementedDownloaderServer) Delete(context.Context, *DeleteRequest) (*emptypb.Empty, error) { + return nil, status.Errorf(codes.Unimplemented, "method Delete not implemented") +} func (UnimplementedDownloaderServer) Verify(context.Context, *VerifyRequest) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method Verify not implemented") } @@ -123,6 +138,24 @@ func _Downloader_Download_Handler(srv interface{}, ctx context.Context, dec func return interceptor(ctx, in, info, handler) } +func _Downloader_Delete_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(DeleteRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DownloaderServer).Delete(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Downloader_Delete_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DownloaderServer).Delete(ctx, req.(*DeleteRequest)) + } + return interceptor(ctx, in, info, handler) +} + func _Downloader_Verify_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(VerifyRequest) if err := dec(in); err != nil { @@ -170,6 +203,10 @@ var Downloader_ServiceDesc = grpc.ServiceDesc{ MethodName: "Download", Handler: _Downloader_Download_Handler, }, + { + MethodName: "Delete", + Handler: _Downloader_Delete_Handler, + }, { MethodName: "Verify", Handler: _Downloader_Verify_Handler, diff --git a/eth/backend.go b/eth/backend.go index 288f84238e9..5e5a806247e 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -621,7 +621,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger // intiialize engine backend var engine *execution_client.ExecutionClientDirect - blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, freezeblocks.MergeSteps, backend.chainDB, backend.notifications.Events, logger) + blockRetire := freezeblocks.NewBlockRetire(1, dirs, blockReader, blockWriter, backend.chainDB, backend.notifications.Events, logger) miningRPC = privateapi.NewMiningServer(ctx, backend, ethashApi, logger) diff --git a/eth/stagedsync/stage_snapshots.go b/eth/stagedsync/stage_snapshots.go index 5332ae54c89..3da1d60ba74 100644 --- a/eth/stagedsync/stage_snapshots.go +++ b/eth/stagedsync/stage_snapshots.go @@ -314,12 +314,16 @@ func SnapshotsPrune(s *PruneState, initialCycle bool, cfg SnapshotsCfg, ctx cont } cfg.blockRetire.RetireBlocksInBackground(ctx, s.ForwardProgress, cfg.chainConfig.Bor != nil, log.LvlInfo, func(downloadRequest []services.DownloadRequest) error { - if cfg.snapshotDownloader != nil && !reflect.ValueOf(cfg.snapshotDownloader).IsNil() { - if err := snapshotsync.RequestSnapshotsDownload(ctx, downloadRequest, cfg.snapshotDownloader); err != nil { - return err - } + if cfg.snapshotDownloader == nil || reflect.ValueOf(cfg.snapshotDownloader).IsNil() { + return nil } - return nil + return snapshotsync.RequestSnapshotsDownload(ctx, downloadRequest, cfg.snapshotDownloader) + }, func(l []string) error { + if cfg.snapshotDownloader == nil || reflect.ValueOf(cfg.snapshotDownloader).IsNil() { + return nil + } + _, err := cfg.snapshotDownloader.Delete(ctx, &proto_downloader.DeleteRequest{Paths: l}) + return err }) //cfg.agg.BuildFilesInBackground() } diff --git a/go.mod b/go.mod index b7b2c0a2837..da91f15babf 100644 --- a/go.mod +++ b/go.mod @@ -186,7 +186,7 @@ require ( github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231027092055-45ee9d86a6cb // indirect + github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect diff --git a/go.sum b/go.sum index 02969b32912..749effc2a21 100644 --- a/go.sum +++ b/go.sum @@ -539,8 +539,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231027092055-45ee9d86a6cb h1:Y6eZ4D8rMrAdDoy2za2Lkf8qSHbNNSPGnSdl/B78G4Y= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231027092055-45ee9d86a6cb/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66 h1:0GY0mXeC6ThOw1x50tF1dDWso0kL6a5SS7k/zrsIF60= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= github.com/ledgerwatch/log/v3 v3.9.0/go.mod h1:EiAY6upmI/6LkNhOVxb4eVsmsP11HZCnZ3PlJMjYiqE= github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= diff --git a/turbo/app/snapshots_cmd.go b/turbo/app/snapshots_cmd.go index 47f10f625d3..5b906088046 100644 --- a/turbo/app/snapshots_cmd.go +++ b/turbo/app/snapshots_cmd.go @@ -404,7 +404,7 @@ func doRetireCommand(cliCtx *cli.Context) error { blockReader := freezeblocks.NewBlockReader(blockSnapshots, borSnapshots) blockWriter := blockio.NewBlockWriter(fromdb.HistV3(db)) - br := freezeblocks.NewBlockRetire(estimate.CompressSnapshot.Workers(), dirs, blockReader, blockWriter, freezeblocks.MergeSteps, db, nil, logger) + br := freezeblocks.NewBlockRetire(estimate.CompressSnapshot.Workers(), dirs, blockReader, blockWriter, db, nil, logger) agg, err := libstate.NewAggregatorV3(ctx, dirs.SnapHistory, dirs.Tmp, ethconfig.HistoryV3AggregationStep, db, logger) if err != nil { return err @@ -460,7 +460,7 @@ func doRetireCommand(cliCtx *cli.Context) error { } for i := from; i < to; i += every { - if err := br.RetireBlocks(ctx, i, i+every, log.LvlInfo, nil); err != nil { + if err := br.RetireBlocks(ctx, i, i+every, log.LvlInfo, nil, nil); err != nil { panic(err) } if err := db.Update(ctx, func(tx kv.RwTx) error { diff --git a/turbo/services/interfaces.go b/turbo/services/interfaces.go index 592006477d2..2b86e736f16 100644 --- a/turbo/services/interfaces.go +++ b/turbo/services/interfaces.go @@ -93,7 +93,7 @@ type BlockSnapshots interface { // BlockRetire - freezing blocks: moving old data from DB to snapshot files type BlockRetire interface { PruneAncientBlocks(tx kv.RwTx, limit int, includeBor bool) error - RetireBlocksInBackground(ctx context.Context, maxBlockNumInDB uint64, includeBor bool, lvl log.Lvl, seedNewSnapshots func(downloadRequest []DownloadRequest) error) + RetireBlocksInBackground(ctx context.Context, maxBlockNumInDB uint64, includeBor bool, lvl log.Lvl, seedNewSnapshots func(downloadRequest []DownloadRequest) error, onDelete func(l []string) error) HasNewFrozenFiles() bool BuildMissedIndicesIfNeed(ctx context.Context, logPrefix string, notifier DBEventNotifier, cc *chain.Config) error } diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots.go b/turbo/snapshotsync/freezeblocks/block_snapshots.go index dd36b794662..dc21c29f275 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots.go @@ -953,7 +953,7 @@ func BuildMissedIndices(logPrefix string, ctx context.Context, dirs datadir.Dirs } }() - for _, t := range snaptype.AllSnapshotTypes { + for _, t := range snaptype.BlockSnapshotTypes { for index := range segments { segment := segments[index] if segment.T != t { @@ -1059,7 +1059,7 @@ MainLoop: if f.From == f.To { continue } - for _, t := range snaptype.AllSnapshotTypes { + for _, t := range snaptype.BlockSnapshotTypes { p := filepath.Join(dir, snaptype.SegmentFileName(f.From, f.To, t)) if !dir2.FileExist(p) { continue MainLoop @@ -1202,12 +1202,10 @@ type BlockRetire struct { blockReader services.FullBlockReader blockWriter *blockio.BlockWriter dirs datadir.Dirs - - mergeSteps []uint64 } -func NewBlockRetire(workers int, dirs datadir.Dirs, blockReader services.FullBlockReader, blockWriter *blockio.BlockWriter, mergeSteps []uint64, db kv.RoDB, notifier services.DBEventNotifier, logger log.Logger) *BlockRetire { - return &BlockRetire{workers: workers, tmpDir: dirs.Tmp, dirs: dirs, blockReader: blockReader, blockWriter: blockWriter, mergeSteps: mergeSteps, db: db, notifier: notifier, logger: logger} +func NewBlockRetire(workers int, dirs datadir.Dirs, blockReader services.FullBlockReader, blockWriter *blockio.BlockWriter, db kv.RoDB, notifier services.DBEventNotifier, logger log.Logger) *BlockRetire { + return &BlockRetire{workers: workers, tmpDir: dirs.Tmp, dirs: dirs, blockReader: blockReader, blockWriter: blockWriter, db: db, notifier: notifier, logger: logger} } func (br *BlockRetire) snapshots() *RoSnapshots { return br.blockReader.Snapshots().(*RoSnapshots) } @@ -1268,7 +1266,7 @@ func CanDeleteTo(curBlockNum uint64, blocksInSnapshots uint64) (blockTo uint64) return cmp.Min(hardLimit, blocksInSnapshots+1) } -func (br *BlockRetire) RetireBlocks(ctx context.Context, blockFrom, blockTo uint64, lvl log.Lvl, seedNewSnapshots func(downloadRequest []services.DownloadRequest) error) error { +func (br *BlockRetire) RetireBlocks(ctx context.Context, blockFrom, blockTo uint64, lvl log.Lvl, seedNewSnapshots func(downloadRequest []services.DownloadRequest) error, onDelete func(l []string) error) error { chainConfig := fromdb.ChainConfig(br.db) notifier, logger, blockReader, tmpDir, db, workers := br.notifier, br.logger, br.blockReader, br.tmpDir, br.db, br.workers logger.Log(lvl, "[snapshots] Retire Blocks", "range", fmt.Sprintf("%dk-%dk", blockFrom/1000, blockTo/1000)) @@ -1286,34 +1284,31 @@ func (br *BlockRetire) RetireBlocks(ctx context.Context, blockFrom, blockTo uint if notifier != nil && !reflect.ValueOf(notifier).IsNil() { // notify about new snapshots of any size notifier.OnNewSnapshot() } - merger := NewMerger(tmpDir, workers, lvl, br.mergeSteps, db, chainConfig, notifier, logger) - rangesToMerge := merger.FindMergeRanges(snapshots.Ranges()) + merger := NewMerger(tmpDir, workers, lvl, db, chainConfig, logger) + rangesToMerge := merger.FindMergeRanges(snapshots.Ranges(), snapshots.BlocksAvailable()) if len(rangesToMerge) == 0 { return nil } - err := merger.Merge(ctx, snapshots, rangesToMerge, snapshots.Dir(), true /* doIndex */) + onMerge := func(r Range) error { + if notifier != nil && !reflect.ValueOf(notifier).IsNil() { // notify about new snapshots of any size + notifier.OnNewSnapshot() + } + + if seedNewSnapshots != nil { + downloadRequest := []services.DownloadRequest{ + services.NewDownloadRequest(&services.Range{From: r.from, To: r.to}, "", "", false /* Bor */), + } + if err := seedNewSnapshots(downloadRequest); err != nil { + return err + } + } + return nil + } + err := merger.Merge(ctx, snapshots, rangesToMerge, snapshots.Dir(), true /* doIndex */, onMerge, onDelete) if err != nil { return err } - if err := snapshots.ReopenFolder(); err != nil { - return fmt.Errorf("reopen: %w", err) - } - snapshots.LogStat() - if notifier != nil && !reflect.ValueOf(notifier).IsNil() { // notify about new snapshots of any size - notifier.OnNewSnapshot() - } - - downloadRequest := make([]services.DownloadRequest, 0, len(rangesToMerge)) - for i := range rangesToMerge { - r := &services.Range{From: rangesToMerge[i].from, To: rangesToMerge[i].to} - downloadRequest = append(downloadRequest, services.NewDownloadRequest(r, "", "", false /* Bor */)) - } - if seedNewSnapshots != nil { - if err := seedNewSnapshots(downloadRequest); err != nil { - return err - } - } return nil } @@ -1338,7 +1333,7 @@ func (br *BlockRetire) PruneAncientBlocks(tx kv.RwTx, limit int, includeBor bool return nil } -func (br *BlockRetire) RetireBlocksInBackground(ctx context.Context, forwardProgress uint64, includeBor bool, lvl log.Lvl, seedNewSnapshots func(downloadRequest []services.DownloadRequest) error) { +func (br *BlockRetire) RetireBlocksInBackground(ctx context.Context, forwardProgress uint64, includeBor bool, lvl log.Lvl, seedNewSnapshots func(downloadRequest []services.DownloadRequest) error, onDeleteSnapshots func(l []string) error) { ok := br.working.CompareAndSwap(false, true) if !ok { // go-routine is still working @@ -1349,7 +1344,7 @@ func (br *BlockRetire) RetireBlocksInBackground(ctx context.Context, forwardProg blockFrom, blockTo, ok := CanRetire(forwardProgress, br.blockReader.FrozenBlocks()) if ok { - if err := br.RetireBlocks(ctx, blockFrom, blockTo, lvl, seedNewSnapshots); err != nil { + if err := br.RetireBlocks(ctx, blockFrom, blockTo, lvl, seedNewSnapshots, onDeleteSnapshots); err != nil { br.logger.Warn("[snapshots] retire blocks", "err", err, "fromBlock", blockFrom, "toBlock", blockTo) } } @@ -2172,32 +2167,43 @@ type Merger struct { tmpDir string chainConfig *chain.Config chainDB kv.RoDB - notifier services.DBEventNotifier logger log.Logger - mergeSteps []uint64 } -func NewMerger(tmpDir string, compressWorkers int, lvl log.Lvl, mergeSteps []uint64, chainDB kv.RoDB, chainConfig *chain.Config, notifier services.DBEventNotifier, logger log.Logger) *Merger { - return &Merger{tmpDir: tmpDir, compressWorkers: compressWorkers, lvl: lvl, mergeSteps: mergeSteps, chainDB: chainDB, chainConfig: chainConfig, notifier: notifier, logger: logger} +func NewMerger(tmpDir string, compressWorkers int, lvl log.Lvl, chainDB kv.RoDB, chainConfig *chain.Config, logger log.Logger) *Merger { + return &Merger{tmpDir: tmpDir, compressWorkers: compressWorkers, lvl: lvl, chainDB: chainDB, chainConfig: chainConfig, logger: logger} } type Range struct { from, to uint64 } -func (r Range) From() uint64 { return r.from } -func (r Range) To() uint64 { return r.to } +func (r Range) From() uint64 { return r.from } +func (r Range) To() uint64 { return r.to } +func (r Range) IsRecent(max uint64) bool { return max-r.to < snaptype.Erigon2MergeLimit } + +type Ranges []Range + +func (r Ranges) String() string { + return fmt.Sprintf("%d", r) +} var MergeSteps = []uint64{500_000, 100_000, 10_000} +var RecentMergeSteps = []uint64{100_000, 10_000} -func (m *Merger) FindMergeRanges(currentRanges []Range) (toMerge []Range) { +func (m *Merger) FindMergeRanges(currentRanges []Range, maxBlockNum uint64) (toMerge []Range) { for i := len(currentRanges) - 1; i > 0; i-- { r := currentRanges[i] - if r.to-r.from >= snaptype.Erigon2MergeLimit { // is complete .seg - continue + isRecent := r.IsRecent(maxBlockNum) + mergeLimit, mergeSteps := uint64(snaptype.Erigon2MergeLimit), MergeSteps + if isRecent { + mergeLimit, mergeSteps = snaptype.Erigon2RecentMergeLimit, RecentMergeSteps } - for _, span := range m.mergeSteps { + if r.to-r.from >= mergeLimit { + continue + } + for _, span := range mergeSteps { if r.to%span != 0 { continue } @@ -2294,7 +2300,7 @@ func (m *Merger) filesByRange(snapshots *RoSnapshots, from, to uint64) (map[snap } // Merge does merge segments in given ranges -func (m *Merger) Merge(ctx context.Context, snapshots *RoSnapshots, mergeRanges []Range, snapDir string, doIndex bool) error { +func (m *Merger) Merge(ctx context.Context, snapshots *RoSnapshots, mergeRanges []Range, snapDir string, doIndex bool, onMerge func(r Range) error, onDelete func(l []string) error) error { if len(mergeRanges) == 0 { return nil } @@ -2306,7 +2312,7 @@ func (m *Merger) Merge(ctx context.Context, snapshots *RoSnapshots, mergeRanges return err } - for _, t := range snaptype.AllSnapshotTypes { + for _, t := range snaptype.BlockSnapshotTypes { segName := snaptype.SegmentFileName(r.from, r.to, t) f, ok := snaptype.ParseFileName(snapDir, segName) if !ok { @@ -2326,11 +2332,20 @@ func (m *Merger) Merge(ctx context.Context, snapshots *RoSnapshots, mergeRanges return fmt.Errorf("ReopenSegments: %w", err) } snapshots.LogStat() - if m.notifier != nil { // notify about new snapshots of any size - m.notifier.OnNewSnapshot() - time.Sleep(1 * time.Second) // i working on blocking API - to ensure client does not use old snapsthos - and then delete them + + if err := onMerge(r); err != nil { + return err + } + for _, t := range snaptype.BlockSnapshotTypes { + if len(toMerge[t]) == 0 { + continue + } + if err := onDelete(toMerge[t]); err != nil { + return err + } } - for _, t := range snaptype.AllSnapshotTypes { + time.Sleep(1 * time.Second) // i working on blocking API - to ensure client does not use old snapsthos - and then delete them + for _, t := range snaptype.BlockSnapshotTypes { m.removeOldFiles(toMerge[t], snapDir) } } @@ -2358,6 +2373,9 @@ func (m *Merger) merge(ctx context.Context, toMerge []string, targetFile string, } defer f.Close() + _, fName := filepath.Split(targetFile) + m.logger.Debug("[snapshots] merge", "file", fName) + for _, d := range cList { if err := d.WithReadAhead(func() error { g := d.MakeGetter() diff --git a/turbo/snapshotsync/freezeblocks/block_snapshots_test.go b/turbo/snapshotsync/freezeblocks/block_snapshots_test.go index eb663df0911..bfb051dbb04 100644 --- a/turbo/snapshotsync/freezeblocks/block_snapshots_test.go +++ b/turbo/snapshotsync/freezeblocks/block_snapshots_test.go @@ -58,19 +58,55 @@ func createTestSegmentFile(t *testing.T, from, to uint64, name snaptype.Type, di } func TestFindMergeRange(t *testing.T) { + merger := NewMerger("x", 1, log.LvlInfo, nil, params.MainnetChainConfig, nil) t.Run("big", func(t *testing.T) { - merger := NewMerger("x", 1, log.LvlInfo, MergeSteps, nil, params.MainnetChainConfig, nil, nil) var ranges []Range for i := 0; i < 24; i++ { ranges = append(ranges, Range{from: uint64(i * 100_000), to: uint64((i + 1) * 100_000)}) } - found := merger.FindMergeRanges(ranges) + found := merger.FindMergeRanges(ranges, uint64(24*100_000)) - var expect []Range - for i := 0; i < 4; i++ { - expect = append(expect, Range{from: uint64(i * snaptype.Erigon2MergeLimit), to: uint64((i + 1) * snaptype.Erigon2MergeLimit)}) + expect := []Range{ + {0, 500_000}, + {500_000, 1_000_000}, + {1_000_000, 1_500_000}, } - require.Equal(t, expect, found) + require.Equal(t, Ranges(expect).String(), Ranges(found).String()) + }) + + t.Run("small", func(t *testing.T) { + var ranges Ranges + for i := 0; i < 240; i++ { + ranges = append(ranges, Range{from: uint64(i * 10_000), to: uint64((i + 1) * 10_000)}) + } + found := merger.FindMergeRanges(ranges, uint64(240*10_000)) + + expect := Ranges{ + {0, 500_000}, + {500_000, 1_000_000}, + {1_000_000, 1_500_000}, + {1_500_000, 1_600_000}, + {1_600_000, 1_700_000}, + {1_700_000, 1_800_000}, + {1_800_000, 1_900_000}, + {1_900_000, 2_000_000}, + {2_000_000, 2_100_000}, + {2_100_000, 2_200_000}, + {2_200_000, 2_300_000}, + {2_300_000, 2_400_000}, + } + + require.Equal(t, expect.String(), Ranges(found).String()) + }) + + t.Run("IsRecent", func(t *testing.T) { + require.True(t, Range{500_000, 599_000}.IsRecent(1_000_000)) + require.True(t, Range{500_000, 501_000}.IsRecent(1_000_000)) + require.False(t, Range{499_000, 500_000}.IsRecent(1_000_000)) + require.False(t, Range{400_000, 500_000}.IsRecent(1_000_000)) + require.False(t, Range{400_000, 401_000}.IsRecent(1_000_000)) + + require.False(t, Range{500_000, 501_000}.IsRecent(1_100_000)) }) } @@ -79,12 +115,12 @@ func TestMergeSnapshots(t *testing.T) { logger := log.New() dir, require := t.TempDir(), require.New(t) createFile := func(from, to uint64) { - for _, snT := range snaptype.AllSnapshotTypes { + for _, snT := range snaptype.BlockSnapshotTypes { createTestSegmentFile(t, from, to, snT, dir, logger) } } - N := uint64(7) + N := uint64(17) createFile(0, snaptype.Erigon2MergeLimit) for i := uint64(snaptype.Erigon2MergeLimit); i < snaptype.Erigon2MergeLimit+N*100_000; i += 100_000 { createFile(i, i+100_000) @@ -93,10 +129,14 @@ func TestMergeSnapshots(t *testing.T) { defer s.Close() require.NoError(s.ReopenFolder()) { - merger := NewMerger(dir, 1, log.LvlInfo, MergeSteps, nil, params.MainnetChainConfig, nil, logger) - ranges := merger.FindMergeRanges(s.Ranges()) + merger := NewMerger(dir, 1, log.LvlInfo, nil, params.MainnetChainConfig, logger) + ranges := merger.FindMergeRanges(s.Ranges(), s.SegmentsMax()) require.True(len(ranges) > 0) - err := merger.Merge(context.Background(), s, ranges, s.Dir(), false) + err := merger.Merge(context.Background(), s, ranges, s.Dir(), false, func(r Range) error { + return nil + }, func(l []string) error { + return nil + }) require.NoError(err) } @@ -108,14 +148,18 @@ func TestMergeSnapshots(t *testing.T) { require.Equal(5, a) { - merger := NewMerger(dir, 1, log.LvlInfo, MergeSteps, nil, params.MainnetChainConfig, nil, logger) - ranges := merger.FindMergeRanges(s.Ranges()) + merger := NewMerger(dir, 1, log.LvlInfo, nil, params.MainnetChainConfig, logger) + ranges := merger.FindMergeRanges(s.Ranges(), s.SegmentsMax()) require.True(len(ranges) == 0) - err := merger.Merge(context.Background(), s, ranges, s.Dir(), false) + err := merger.Merge(context.Background(), s, ranges, s.Dir(), false, func(r Range) error { + return nil + }, func(l []string) error { + return nil + }) require.NoError(err) } - expectedFileName = snaptype.SegmentFileName(1_100_000, 1_200_000, snaptype.Transactions) + expectedFileName = snaptype.SegmentFileName(1_800_000, 1_900_000, snaptype.Transactions) d, err = compress.NewDecompressor(filepath.Join(dir, expectedFileName)) require.NoError(err) defer d.Close() diff --git a/turbo/snapshotsync/freezeblocks/bor_snapshots.go b/turbo/snapshotsync/freezeblocks/bor_snapshots.go index 26846a64e54..a1240ccb52f 100644 --- a/turbo/snapshotsync/freezeblocks/bor_snapshots.go +++ b/turbo/snapshotsync/freezeblocks/bor_snapshots.go @@ -191,32 +191,33 @@ func (br *BlockRetire) RetireBorBlocks(ctx context.Context, blockFrom, blockTo u if notifier != nil && !reflect.ValueOf(notifier).IsNil() { // notify about new snapshots of any size notifier.OnNewSnapshot() } - merger := NewBorMerger(tmpDir, workers, lvl, br.mergeSteps, db, chainConfig, notifier, logger) - rangesToMerge := merger.FindMergeRanges(snapshots.Ranges()) + merger := NewBorMerger(tmpDir, workers, lvl, db, chainConfig, notifier, logger) + rangesToMerge := merger.FindMergeRanges(snapshots.Ranges(), snapshots.BlocksAvailable()) if len(rangesToMerge) == 0 { return nil } - err := merger.Merge(ctx, snapshots, rangesToMerge, snapshots.Dir(), true /* doIndex */) - if err != nil { - return err - } - if err := snapshots.ReopenFolder(); err != nil { - return fmt.Errorf("reopen: %w", err) - } - snapshots.LogStat() - if notifier != nil && !reflect.ValueOf(notifier).IsNil() { // notify about new snapshots of any size - notifier.OnNewSnapshot() - } - downloadRequest := make([]services.DownloadRequest, 0, len(rangesToMerge)) - for i := range rangesToMerge { - r := &services.Range{From: rangesToMerge[i].from, To: rangesToMerge[i].to} - downloadRequest = append(downloadRequest, services.NewDownloadRequest(r, "", "", true /* Bor */)) - } + onMerge := func(r Range) error { + if notifier != nil && !reflect.ValueOf(notifier).IsNil() { // notify about new snapshots of any size + notifier.OnNewSnapshot() + } - if seedNewSnapshots != nil { - if err := seedNewSnapshots(downloadRequest); err != nil { - return err + if seedNewSnapshots != nil { + downloadRequest := []services.DownloadRequest{ + services.NewDownloadRequest(&services.Range{From: r.from, To: r.to}, "", "", true /* Bor */), + } + if err := seedNewSnapshots(downloadRequest); err != nil { + return err + } } + return nil + } + onDelete := func(files []string) error { + //TODO: add Downloader API to delete files + return nil + } + err := merger.Merge(ctx, snapshots, rangesToMerge, snapshots.Dir(), true /* doIndex */, onMerge, onDelete) + if err != nil { + return err } return nil } @@ -1059,21 +1060,25 @@ type BorMerger struct { chainDB kv.RoDB notifier services.DBEventNotifier logger log.Logger - mergeSteps []uint64 } -func NewBorMerger(tmpDir string, compressWorkers int, lvl log.Lvl, mergeSteps []uint64, chainDB kv.RoDB, chainConfig *chain.Config, notifier services.DBEventNotifier, logger log.Logger) *BorMerger { - return &BorMerger{tmpDir: tmpDir, compressWorkers: compressWorkers, lvl: lvl, mergeSteps: mergeSteps, chainDB: chainDB, chainConfig: chainConfig, notifier: notifier, logger: logger} +func NewBorMerger(tmpDir string, compressWorkers int, lvl log.Lvl, chainDB kv.RoDB, chainConfig *chain.Config, notifier services.DBEventNotifier, logger log.Logger) *BorMerger { + return &BorMerger{tmpDir: tmpDir, compressWorkers: compressWorkers, lvl: lvl, chainDB: chainDB, chainConfig: chainConfig, notifier: notifier, logger: logger} } -func (m *BorMerger) FindMergeRanges(currentRanges []Range) (toMerge []Range) { +func (m *BorMerger) FindMergeRanges(currentRanges []Range, maxBlockNum uint64) (toMerge []Range) { for i := len(currentRanges) - 1; i > 0; i-- { r := currentRanges[i] - if r.to-r.from >= snaptype.Erigon2MergeLimit { // is complete .seg - continue + isRecent := r.IsRecent(maxBlockNum) + mergeLimit, mergeSteps := uint64(snaptype.Erigon2RecentMergeLimit), MergeSteps + if isRecent { + mergeLimit, mergeSteps = snaptype.Erigon2MergeLimit, RecentMergeSteps } - for _, span := range m.mergeSteps { + if r.to-r.from >= mergeLimit { + continue + } + for _, span := range mergeSteps { if r.to%span != 0 { continue } @@ -1115,7 +1120,7 @@ func (m *BorMerger) filesByRange(snapshots *BorRoSnapshots, from, to uint64) (ma } // Merge does merge segments in given ranges -func (m *BorMerger) Merge(ctx context.Context, snapshots *BorRoSnapshots, mergeRanges []Range, snapDir string, doIndex bool) error { +func (m *BorMerger) Merge(ctx context.Context, snapshots *BorRoSnapshots, mergeRanges []Range, snapDir string, doIndex bool, onMerge func(r Range) error, onDelete func(l []string) error) error { if len(mergeRanges) == 0 { return nil } @@ -1147,11 +1152,19 @@ func (m *BorMerger) Merge(ctx context.Context, snapshots *BorRoSnapshots, mergeR return fmt.Errorf("ReopenSegments: %w", err) } snapshots.LogStat() - if m.notifier != nil { // notify about new snapshots of any size - m.notifier.OnNewSnapshot() - time.Sleep(1 * time.Second) // i working on blocking API - to ensure client does not use old snapsthos - and then delete them + if err := onMerge(r); err != nil { + return err + } + for _, t := range snaptype.BlockSnapshotTypes { + if len(toMerge[t]) == 0 { + continue + } + if err := onDelete(toMerge[t]); err != nil { + return err + } } - for _, t := range []snaptype.Type{snaptype.BorEvents} { + time.Sleep(1 * time.Second) // i working on blocking API - to ensure client does not use old snapsthos - and then delete them + for _, t := range snaptype.BlockSnapshotTypes { m.removeOldFiles(toMerge[t], snapDir) } } diff --git a/turbo/snapshotsync/snapshotsync.go b/turbo/snapshotsync/snapshotsync.go index 06c0a4a6fef..2298ba8ed79 100644 --- a/turbo/snapshotsync/snapshotsync.go +++ b/turbo/snapshotsync/snapshotsync.go @@ -35,7 +35,7 @@ const ( ) func BuildProtoRequest(downloadRequest []services.DownloadRequest) *proto_downloader.DownloadRequest { - req := &proto_downloader.DownloadRequest{Items: make([]*proto_downloader.DownloadItem, 0, len(snaptype.AllSnapshotTypes))} + req := &proto_downloader.DownloadRequest{Items: make([]*proto_downloader.DownloadItem, 0, len(snaptype.BlockSnapshotTypes))} for _, r := range downloadRequest { if r.Path != "" { if r.TorrentHash != "" { @@ -50,13 +50,13 @@ func BuildProtoRequest(downloadRequest []services.DownloadRequest) *proto_downlo } } else { if r.Bor { - for _, t := range []snaptype.Type{snaptype.BorEvents, snaptype.BorSpans} { + for _, t := range snaptype.BorSnapshotTypes { req.Items = append(req.Items, &proto_downloader.DownloadItem{ Path: snaptype.SegmentFileName(r.Ranges.From, r.Ranges.To, t), }) } } else { - for _, t := range snaptype.AllSnapshotTypes { + for _, t := range snaptype.BlockSnapshotTypes { req.Items = append(req.Items, &proto_downloader.DownloadItem{ Path: snaptype.SegmentFileName(r.Ranges.From, r.Ranges.To, t), }) diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index ada1746a563..df9e7df5f54 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -417,7 +417,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK return block, nil } - blockRetire := freezeblocks.NewBlockRetire(1, dirs, mock.BlockReader, blockWriter, freezeblocks.MergeSteps, mock.DB, mock.Notifications.Events, logger) + blockRetire := freezeblocks.NewBlockRetire(1, dirs, mock.BlockReader, blockWriter, mock.DB, mock.Notifications.Events, logger) mock.Sync = stagedsync.New( stagedsync.DefaultStages(mock.Ctx, stagedsync.StageSnapshotsCfg(mock.DB, *mock.ChainConfig, dirs, blockRetire, snapshotsDownloader, mock.BlockReader, mock.Notifications.Events, mock.HistoryV3, mock.agg, nil), From d92898a5081b577a8e8f120226674c9de096ebe7 Mon Sep 17 00:00:00 2001 From: battlmonstr Date: Thu, 2 Nov 2023 02:35:13 +0100 Subject: [PATCH 41/44] p2p: silkworm sentry (#8527) --- cmd/integration/commands/stages.go | 4 +- cmd/sentry/main.go | 2 +- cmd/utils/flags.go | 29 +- eth/backend.go | 112 ++++-- eth/ethconfig/config.go | 11 +- eth/ethconfig/gen_config.go | 6 - ethstats/ethstats.go | 2 +- {cmd/sentry => p2p}/sentry/eth_handshake.go | 0 .../sentry/eth_handshake_test.go | 0 .../sentry/sentry_grpc_server.go | 0 .../sentry/sentry_grpc_server_test.go | 0 .../sentry/sentry_multi_client}/broadcast.go | 2 +- .../sentry/sentry_multi_client}/sentry_api.go | 7 +- .../sentry_multi_client.go | 15 +- p2p/server.go | 3 + tests/bor/helper/miner.go | 1 - turbo/cli/default_flags.go | 3 + turbo/silkworm/load.go | 19 - .../silkworm/{load_linux.go => load_unix.go} | 2 + turbo/silkworm/load_windows.go | 16 + turbo/silkworm/silkworm.go | 333 +++++++++--------- turbo/silkworm/silkworm_api.h | 206 +++++++++++ turbo/silkworm/silkworm_api_bridge.h | 75 ++++ turbo/stages/mock/mock_sentry.go | 6 +- turbo/stages/stageloop.go | 21 +- 25 files changed, 623 insertions(+), 252 deletions(-) rename {cmd/sentry => p2p}/sentry/eth_handshake.go (100%) rename {cmd/sentry => p2p}/sentry/eth_handshake_test.go (100%) rename {cmd/sentry => p2p}/sentry/sentry_grpc_server.go (100%) rename {cmd/sentry => p2p}/sentry/sentry_grpc_server_test.go (100%) rename {cmd/sentry/sentry => p2p/sentry/sentry_multi_client}/broadcast.go (98%) rename {cmd/sentry/sentry => p2p/sentry/sentry_multi_client}/sentry_api.go (96%) rename {cmd/sentry/sentry => p2p/sentry/sentry_multi_client}/sentry_multi_client.go (98%) delete mode 100644 turbo/silkworm/load.go rename turbo/silkworm/{load_linux.go => load_unix.go} (97%) create mode 100644 turbo/silkworm/load_windows.go create mode 100644 turbo/silkworm/silkworm_api.h create mode 100644 turbo/silkworm/silkworm_api_bridge.h diff --git a/cmd/integration/commands/stages.go b/cmd/integration/commands/stages.go index 8896ae7b27d..5ac02ddfb6f 100644 --- a/cmd/integration/commands/stages.go +++ b/cmd/integration/commands/stages.go @@ -15,6 +15,7 @@ import ( "github.com/ledgerwatch/erigon/consensus/bor/heimdallgrpc" "github.com/ledgerwatch/erigon/core/rawdb/blockio" "github.com/ledgerwatch/erigon/node/nodecfg" + "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" "github.com/ledgerwatch/erigon/turbo/builder" "github.com/ledgerwatch/erigon/turbo/snapshotsync/freezeblocks" "github.com/ledgerwatch/log/v3" @@ -33,7 +34,6 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/rawdbv3" libstate "github.com/ledgerwatch/erigon-lib/state" "github.com/ledgerwatch/erigon/cmd/hack/tool/fromdb" - "github.com/ledgerwatch/erigon/cmd/sentry/sentry" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/core" "github.com/ledgerwatch/erigon/core/rawdb" @@ -1529,7 +1529,7 @@ func newSync(ctx context.Context, db kv.RwDB, miningConfig *params.MiningConfig, maxBlockBroadcastPeers := func(header *types.Header) uint { return 0 } - sentryControlServer, err := sentry.NewMultiClient( + sentryControlServer, err := sentry_multi_client.NewMultiClient( db, "", chainConfig, diff --git a/cmd/sentry/main.go b/cmd/sentry/main.go index 146ee737baf..abd86dca1a9 100644 --- a/cmd/sentry/main.go +++ b/cmd/sentry/main.go @@ -8,9 +8,9 @@ import ( "github.com/ledgerwatch/erigon-lib/common/datadir" "github.com/spf13/cobra" - "github.com/ledgerwatch/erigon/cmd/sentry/sentry" "github.com/ledgerwatch/erigon/cmd/utils" "github.com/ledgerwatch/erigon/common/paths" + "github.com/ledgerwatch/erigon/p2p/sentry" "github.com/ledgerwatch/erigon/turbo/debug" "github.com/ledgerwatch/erigon/turbo/logging" node2 "github.com/ledgerwatch/erigon/turbo/node" diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go index 6296546a60d..a8236b51694 100644 --- a/cmd/utils/flags.go +++ b/cmd/utils/flags.go @@ -838,9 +838,21 @@ var ( SilkwormPathFlag = cli.StringFlag{ Name: "silkworm.path", - Usage: "Path to the silkworm_api library (enables embedded Silkworm execution)", + Usage: "Path to the Silkworm library", Value: "", } + SilkwormExecutionFlag = cli.BoolFlag{ + Name: "silkworm.exec", + Usage: "Enable Silkworm block execution", + } + SilkwormRpcDaemonFlag = cli.BoolFlag{ + Name: "silkworm.rpcd", + Usage: "Enable embedded Silkworm RPC daemon", + } + SilkwormSentryFlag = cli.BoolFlag{ + Name: "silkworm.sentry", + Usage: "Enable embedded Silkworm Sentry service", + } ) var MetricFlags = []cli.Flag{&MetricsEnabledFlag, &MetricsHTTPFlag, &MetricsPortFlag} @@ -1031,6 +1043,7 @@ func NewP2PConfig( return nil, fmt.Errorf("invalid nat option %s: %w", natSetting, err) } cfg.NAT = natif + cfg.NATSpec = natSetting return cfg, nil } @@ -1079,11 +1092,13 @@ func setListenAddress(ctx *cli.Context, cfg *p2p.Config) { // setNAT creates a port mapper from command line flags. func setNAT(ctx *cli.Context, cfg *p2p.Config) { if ctx.IsSet(NATFlag.Name) { - natif, err := nat.Parse(ctx.String(NATFlag.Name)) + natSetting := ctx.String(NATFlag.Name) + natif, err := nat.Parse(natSetting) if err != nil { Fatalf("Option %s: %v", NATFlag.Name, err) } cfg.NAT = natif + cfg.NATSpec = natSetting } } @@ -1161,7 +1176,6 @@ func SetP2PConfig(ctx *cli.Context, cfg *p2p.Config, nodeName, datadir string, l } ethPeers := cfg.MaxPeers - cfg.Name = nodeName logger.Info("Maximum peer count", "ETH", ethPeers, "total", cfg.MaxPeers) if netrestrict := ctx.String(NetrestrictFlag.Name); netrestrict != "" { @@ -1460,10 +1474,12 @@ func setWhitelist(ctx *cli.Context, cfg *ethconfig.Config) { } func setSilkworm(ctx *cli.Context, cfg *ethconfig.Config) { - cfg.SilkwormEnabled = ctx.IsSet(SilkwormPathFlag.Name) - if cfg.SilkwormEnabled { - cfg.SilkwormPath = ctx.String(SilkwormPathFlag.Name) + cfg.SilkwormPath = ctx.String(SilkwormPathFlag.Name) + if ctx.IsSet(SilkwormExecutionFlag.Name) { + cfg.SilkwormExecution = ctx.Bool(SilkwormExecutionFlag.Name) } + cfg.SilkwormRpcDaemon = ctx.Bool(SilkwormRpcDaemonFlag.Name) + cfg.SilkwormSentry = ctx.Bool(SilkwormSentryFlag.Name) } // CheckExclusive verifies that only a single instance of the provided flags was @@ -1576,7 +1592,6 @@ func SetEthConfig(ctx *cli.Context, nodeConfig *nodecfg.Config, cfg *ethconfig.C setSilkworm(ctx, cfg) cfg.Ethstats = ctx.String(EthStatsURLFlag.Name) - cfg.P2PEnabled = len(nodeConfig.P2P.SentryAddr) == 0 cfg.HistoryV3 = ctx.Bool(HistoryV3Flag.Name) if ctx.IsSet(NetworkIdFlag.Name) { cfg.NetworkID = ctx.Uint64(NetworkIdFlag.Name) diff --git a/eth/backend.go b/eth/backend.go index 5e5a806247e..0cad97d9819 100644 --- a/eth/backend.go +++ b/eth/backend.go @@ -47,6 +47,8 @@ import ( "github.com/ledgerwatch/erigon/core/rawdb/blockio" "github.com/ledgerwatch/erigon/ethdb/prune" + "github.com/ledgerwatch/erigon/p2p/sentry" + "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" "github.com/ledgerwatch/erigon/turbo/builder" "github.com/ledgerwatch/erigon/turbo/engineapi" "github.com/ledgerwatch/erigon/turbo/engineapi/engine_block_downloader" @@ -87,7 +89,6 @@ import ( "github.com/ledgerwatch/erigon/cmd/caplin/caplin1" "github.com/ledgerwatch/erigon/cmd/rpcdaemon/cli" - "github.com/ledgerwatch/erigon/cmd/sentry/sentry" "github.com/ledgerwatch/erigon/common/debug" rpcsentinel "github.com/ledgerwatch/erigon-lib/gointerfaces/sentinel" @@ -165,7 +166,7 @@ type Ethereum struct { // downloader fields sentryCtx context.Context sentryCancel context.CancelFunc - sentriesClient *sentry.MultiClient + sentriesClient *sentry_multi_client.MultiClient sentryServers []*sentry.GrpcServer stagedSync *stagedsync.Sync @@ -200,7 +201,10 @@ type Ethereum struct { logger log.Logger sentinel rpcsentinel.SentinelClient - silkworm *silkworm.Silkworm + + silkworm *silkworm.Silkworm + silkwormRPCDaemonService *silkworm.RpcDaemonService + silkwormSentryService *silkworm.SentryService } func splitAddrIntoHostAndPort(addr string) (host string, port int, err error) { @@ -339,15 +343,56 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger backend.gasPrice, _ = uint256.FromBig(config.Miner.GasPrice) + if config.SilkwormPath != "" { + backend.silkworm, err = silkworm.New(config.SilkwormPath, config.Dirs.DataDir) + if err != nil { + return nil, err + } + } + var sentries []direct.SentryClient if len(stack.Config().P2P.SentryAddr) > 0 { for _, addr := range stack.Config().P2P.SentryAddr { - sentryClient, err := sentry.GrpcClient(backend.sentryCtx, addr) + sentryClient, err := sentry_multi_client.GrpcClient(backend.sentryCtx, addr) if err != nil { return nil, err } sentries = append(sentries, sentryClient) } + } else if config.SilkwormSentry { + apiPort := 53774 + apiAddr := fmt.Sprintf("127.0.0.1:%d", apiPort) + p2pConfig := stack.Config().P2P + + collectNodeURLs := func(nodes []*enode.Node) []string { + var urls []string + for _, n := range nodes { + urls = append(urls, n.URLv4()) + } + return urls + } + + settings := silkworm.SentrySettings{ + ClientId: p2pConfig.Name, + ApiPort: apiPort, + Port: p2pConfig.ListenPort(), + Nat: p2pConfig.NATSpec, + NetworkId: config.NetworkID, + NodeKey: crypto.FromECDSA(p2pConfig.PrivateKey), + StaticPeers: collectNodeURLs(p2pConfig.StaticNodes), + Bootnodes: collectNodeURLs(p2pConfig.BootstrapNodes), + NoDiscover: p2pConfig.NoDiscovery, + MaxPeers: p2pConfig.MaxPeers, + } + + silkwormSentryService := backend.silkworm.NewSentryService(settings) + backend.silkwormSentryService = &silkwormSentryService + + sentryClient, err := sentry_multi_client.GrpcClient(backend.sentryCtx, apiAddr) + if err != nil { + return nil, err + } + sentries = append(sentries, sentryClient) } else { var readNodeInfo = func() *eth.NodeInfo { var res *eth.NodeInfo @@ -478,13 +523,6 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger backend.engine = ethconsensusconfig.CreateConsensusEngine(ctx, stack.Config(), chainConfig, consensusConfig, config.Miner.Notify, config.Miner.Noverify, heimdallClient, config.WithoutHeimdall, blockReader, false /* readonly */, logger) - if config.SilkwormEnabled { - backend.silkworm, err = silkworm.New(config.SilkwormPath) - if err != nil { - return nil, err - } - } - inMemoryExecution := func(batch kv.RwTx, header *types.Header, body *types.RawBody, unwindPoint uint64, headersChain []*types.Header, bodiesChain []*types.RawBody, notifications *shards.Notifications) error { terseLogger := log.New() @@ -529,7 +567,7 @@ func New(ctx context.Context, stack *node.Node, config *ethconfig.Config, logger } } - backend.sentriesClient, err = sentry.NewMultiClient( + backend.sentriesClient, err = sentry_multi_client.NewMultiClient( chainKv, stack.Config().NodeName(), chainConfig, @@ -862,24 +900,17 @@ func (s *Ethereum) Init(stack *node.Node, config *ethconfig.Config) error { } s.apiList = jsonrpc.APIList(chainKv, ethRpcClient, txPoolRpcClient, miningRpcClient, ff, stateCache, blockReader, s.agg, httpRpcCfg, s.engine, s.logger) - go func() { - if config.SilkwormEnabled && httpRpcCfg.Enabled { - go func() { - <-ctx.Done() - s.silkworm.StopRpcDaemon() - }() - err = s.silkworm.StartRpcDaemon(chainKv) - if err != nil { - s.logger.Error(err.Error()) - return - } - } else { + + if config.SilkwormRpcDaemon && httpRpcCfg.Enabled { + silkwormRPCDaemonService := s.silkworm.NewRpcDaemonService(chainKv) + s.silkwormRPCDaemonService = &silkwormRPCDaemonService + } else { + go func() { if err := cli.StartRpcServer(ctx, httpRpcCfg, s.apiList, s.logger); err != nil { - s.logger.Error(err.Error()) - return + s.logger.Error("cli.StartRpcServer error", "err", err) } - } - }() + }() + } go s.engineBackendRPC.Start(httpRpcCfg, s.chainDB, s.blockReader, ff, stateCache, s.agg, s.engine, ethRpcClient, txPoolRpcClient, miningRpcClient) @@ -1265,6 +1296,17 @@ func (s *Ethereum) Start() error { s.engine.(*bor.Bor).Start(s.chainDB) } + if s.silkwormRPCDaemonService != nil { + if err := s.silkwormRPCDaemonService.Start(); err != nil { + s.logger.Error("silkworm.StartRpcDaemon error", "err", err) + } + } + if s.silkwormSentryService != nil { + if err := s.silkwormSentryService.Start(); err != nil { + s.logger.Error("silkworm.SentryStart error", "err", err) + } + } + return nil } @@ -1310,7 +1352,17 @@ func (s *Ethereum) Stop() error { } s.chainDB.Close() - if s.config.SilkwormEnabled { + if s.silkwormRPCDaemonService != nil { + if err := s.silkwormRPCDaemonService.Stop(); err != nil { + s.logger.Error("silkworm.StopRpcDaemon error", "err", err) + } + } + if s.silkwormSentryService != nil { + if err := s.silkwormSentryService.Stop(); err != nil { + s.logger.Error("silkworm.SentryStop error", "err", err) + } + } + if s.silkworm != nil { s.silkworm.Close() } @@ -1337,7 +1389,7 @@ func (s *Ethereum) SentryCtx() context.Context { return s.sentryCtx } -func (s *Ethereum) SentryControlServer() *sentry.MultiClient { +func (s *Ethereum) SentryControlServer() *sentry_multi_client.MultiClient { return s.sentriesClient } func (s *Ethereum) BlockIO() (services.FullBlockReader, *blockio.BlockWriter) { diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go index 83ea6a406ca..fe0000506eb 100644 --- a/eth/ethconfig/config.go +++ b/eth/ethconfig/config.go @@ -102,7 +102,8 @@ var Defaults = Config{ Produce: true, }, - SilkwormEnabled: false, + // applies if SilkwormPath is set + SilkwormExecution: true, } func init() { @@ -178,8 +179,6 @@ type Config struct { // for nodes to connect to. EthDiscoveryURLs []string - P2PEnabled bool - Prune prune.Mode BatchSize datasize.ByteSize // Batch size for execution stage @@ -253,8 +252,10 @@ type Config struct { ForcePartialCommit bool // Embedded Silkworm support - SilkwormEnabled bool - SilkwormPath string + SilkwormPath string + SilkwormExecution bool + SilkwormRpcDaemon bool + SilkwormSentry bool } type Sync struct { diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go index 5d9db0e26cb..f5432c115b4 100644 --- a/eth/ethconfig/gen_config.go +++ b/eth/ethconfig/gen_config.go @@ -22,7 +22,6 @@ func (c Config) MarshalTOML() (interface{}, error) { Genesis *types.Genesis `toml:",omitempty"` NetworkID uint64 EthDiscoveryURLs []string - P2PEnabled bool Prune prune.Mode BatchSize datasize.ByteSize ImportMode bool @@ -47,7 +46,6 @@ func (c Config) MarshalTOML() (interface{}, error) { enc.Genesis = c.Genesis enc.NetworkID = c.NetworkID enc.EthDiscoveryURLs = c.EthDiscoveryURLs - enc.P2PEnabled = c.P2PEnabled enc.Prune = c.Prune enc.BatchSize = c.BatchSize enc.ImportMode = c.ImportMode @@ -73,7 +71,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { Genesis *types.Genesis `toml:",omitempty"` NetworkID *uint64 EthDiscoveryURLs []string - P2PEnabled *bool Prune *prune.Mode BatchSize *datasize.ByteSize ImportMode *bool @@ -107,9 +104,6 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error { if dec.EthDiscoveryURLs != nil { c.EthDiscoveryURLs = dec.EthDiscoveryURLs } - if dec.P2PEnabled != nil { - c.P2PEnabled = *dec.P2PEnabled - } if dec.Prune != nil { c.Prune = *dec.Prune } diff --git a/ethstats/ethstats.go b/ethstats/ethstats.go index 45f67ab8de2..a2556f9b551 100644 --- a/ethstats/ethstats.go +++ b/ethstats/ethstats.go @@ -37,12 +37,12 @@ import ( "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/log/v3" - "github.com/ledgerwatch/erigon/cmd/sentry/sentry" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/core/rawdb" "github.com/ledgerwatch/erigon/core/types" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/node" + "github.com/ledgerwatch/erigon/p2p/sentry" ) const ( diff --git a/cmd/sentry/sentry/eth_handshake.go b/p2p/sentry/eth_handshake.go similarity index 100% rename from cmd/sentry/sentry/eth_handshake.go rename to p2p/sentry/eth_handshake.go diff --git a/cmd/sentry/sentry/eth_handshake_test.go b/p2p/sentry/eth_handshake_test.go similarity index 100% rename from cmd/sentry/sentry/eth_handshake_test.go rename to p2p/sentry/eth_handshake_test.go diff --git a/cmd/sentry/sentry/sentry_grpc_server.go b/p2p/sentry/sentry_grpc_server.go similarity index 100% rename from cmd/sentry/sentry/sentry_grpc_server.go rename to p2p/sentry/sentry_grpc_server.go diff --git a/cmd/sentry/sentry/sentry_grpc_server_test.go b/p2p/sentry/sentry_grpc_server_test.go similarity index 100% rename from cmd/sentry/sentry/sentry_grpc_server_test.go rename to p2p/sentry/sentry_grpc_server_test.go diff --git a/cmd/sentry/sentry/broadcast.go b/p2p/sentry/sentry_multi_client/broadcast.go similarity index 98% rename from cmd/sentry/sentry/broadcast.go rename to p2p/sentry/sentry_multi_client/broadcast.go index e3f961aafde..f210d8ea5f1 100644 --- a/cmd/sentry/sentry/broadcast.go +++ b/p2p/sentry/sentry_multi_client/broadcast.go @@ -1,4 +1,4 @@ -package sentry +package sentry_multi_client import ( "context" diff --git a/cmd/sentry/sentry/sentry_api.go b/p2p/sentry/sentry_multi_client/sentry_api.go similarity index 96% rename from cmd/sentry/sentry/sentry_api.go rename to p2p/sentry/sentry_multi_client/sentry_api.go index f850e677eb7..210e91d1d42 100644 --- a/cmd/sentry/sentry/sentry_api.go +++ b/p2p/sentry/sentry_multi_client/sentry_api.go @@ -1,7 +1,8 @@ -package sentry +package sentry_multi_client import ( "context" + "github.com/ledgerwatch/erigon/p2p/sentry" "math/rand" "github.com/holiman/uint256" @@ -72,7 +73,7 @@ func (cs *MultiClient) SendBodyRequest(ctx context.Context, req *bodydownload.Bo if sentPeers == nil || len(sentPeers.Peers) == 0 { continue } - return ConvertH512ToPeerID(sentPeers.Peers[0]), true + return sentry.ConvertH512ToPeerID(sentPeers.Peers[0]), true } return [64]byte{}, false } @@ -119,7 +120,7 @@ func (cs *MultiClient) SendHeaderRequest(ctx context.Context, req *headerdownloa if sentPeers == nil || len(sentPeers.Peers) == 0 { continue } - return ConvertH512ToPeerID(sentPeers.Peers[0]), true + return sentry.ConvertH512ToPeerID(sentPeers.Peers[0]), true } return [64]byte{}, false } diff --git a/cmd/sentry/sentry/sentry_multi_client.go b/p2p/sentry/sentry_multi_client/sentry_multi_client.go similarity index 98% rename from cmd/sentry/sentry/sentry_multi_client.go rename to p2p/sentry/sentry_multi_client/sentry_multi_client.go index f117020119f..1766e399eca 100644 --- a/cmd/sentry/sentry/sentry_multi_client.go +++ b/p2p/sentry/sentry_multi_client/sentry_multi_client.go @@ -1,4 +1,4 @@ -package sentry +package sentry_multi_client import ( "bytes" @@ -6,6 +6,7 @@ import ( "encoding/hex" "errors" "fmt" + sentry2 "github.com/ledgerwatch/erigon/p2p/sentry" "math/rand" "sort" "sync" @@ -441,7 +442,7 @@ func (cs *MultiClient) blockHeaders(ctx context.Context, pkt eth.BlockHeadersPac return err } defer tx.Rollback() - penalties, err := cs.Hd.ProcessHeadersPOS(csHeaders, tx, ConvertH512ToPeerID(peerID)) + penalties, err := cs.Hd.ProcessHeadersPOS(csHeaders, tx, sentry2.ConvertH512ToPeerID(peerID)) if err != nil { return err } @@ -450,7 +451,7 @@ func (cs *MultiClient) blockHeaders(ctx context.Context, pkt eth.BlockHeadersPac } } else { sort.Sort(headerdownload.HeadersSort(csHeaders)) // Sorting by order of block heights - canRequestMore := cs.Hd.ProcessHeaders(csHeaders, false /* newBlock */, ConvertH512ToPeerID(peerID)) + canRequestMore := cs.Hd.ProcessHeaders(csHeaders, false /* newBlock */, sentry2.ConvertH512ToPeerID(peerID)) if canRequestMore { currentTime := time.Now() @@ -520,7 +521,7 @@ func (cs *MultiClient) newBlock66(ctx context.Context, inreq *proto_sentry.Inbou }) } - cs.Hd.ProcessHeaders(segments, true /* newBlock */, ConvertH512ToPeerID(inreq.PeerId)) // There is only one segment in this case + cs.Hd.ProcessHeaders(segments, true /* newBlock */, sentry2.ConvertH512ToPeerID(inreq.PeerId)) // There is only one segment in this case } else { outreq := proto_sentry.PenalizePeerRequest{ PeerId: inreq.PeerId, @@ -546,7 +547,7 @@ func (cs *MultiClient) newBlock66(ctx context.Context, inreq *proto_sentry.Inbou if _, err1 := sentry.PeerMinBlock(ctx, &outreq, &grpc.EmptyCallOption{}); err1 != nil { cs.logger.Error("Could not send min block for peer", "err", err1) } - cs.logger.Trace(fmt.Sprintf("NewBlockMsg{blockNumber: %d} from [%s]", request.Block.NumberU64(), ConvertH512ToPeerID(inreq.PeerId))) + cs.logger.Trace(fmt.Sprintf("NewBlockMsg{blockNumber: %d} from [%s]", request.Block.NumberU64(), sentry2.ConvertH512ToPeerID(inreq.PeerId))) return nil } @@ -560,7 +561,7 @@ func (cs *MultiClient) blockBodies66(ctx context.Context, inreq *proto_sentry.In // No point processing empty response return nil } - cs.Bd.DeliverBodies(txs, uncles, withdrawals, uint64(len(inreq.Data)), ConvertH512ToPeerID(inreq.PeerId)) + cs.Bd.DeliverBodies(txs, uncles, withdrawals, uint64(len(inreq.Data)), sentry2.ConvertH512ToPeerID(inreq.PeerId)) return nil } @@ -751,7 +752,7 @@ func (cs *MultiClient) handleInboundMessage(ctx context.Context, inreq *proto_se func (cs *MultiClient) HandlePeerEvent(ctx context.Context, event *proto_sentry.PeerEvent, sentry direct.SentryClient) error { eventID := event.EventId.String() - peerID := ConvertH512ToPeerID(event.PeerId) + peerID := sentry2.ConvertH512ToPeerID(event.PeerId) peerIDStr := hex.EncodeToString(peerID[:]) if !cs.logPeerInfo { diff --git a/p2p/server.go b/p2p/server.go index b9b3ed456a5..4a32e45b35f 100644 --- a/p2p/server.go +++ b/p2p/server.go @@ -156,6 +156,9 @@ type Config struct { // Internet. NAT nat.Interface `toml:",omitempty"` + // NAT interface description (see NAT.Parse()). + NATSpec string + // If Dialer is set to a non-nil value, the given Dialer // is used to dial outbound peer connections. Dialer NodeDialer `toml:"-"` diff --git a/tests/bor/helper/miner.go b/tests/bor/helper/miner.go index 875ed01d655..fc420100a16 100644 --- a/tests/bor/helper/miner.go +++ b/tests/bor/helper/miner.go @@ -142,7 +142,6 @@ func InitMiner(ctx context.Context, genesis *types.Genesis, privKey *ecdsa.Priva RPCGasCap: 50000000, RPCTxFeeCap: 1, // 1 ether Snapshot: ethconfig.BlocksFreezing{NoDownloader: true}, - P2PEnabled: true, StateStream: true, } ethCfg.TxPool.DBDir = nodeCfg.Dirs.TxPool diff --git a/turbo/cli/default_flags.go b/turbo/cli/default_flags.go index 978b96d974b..a65180a7137 100644 --- a/turbo/cli/default_flags.go +++ b/turbo/cli/default_flags.go @@ -165,6 +165,9 @@ var DefaultFlags = []cli.Flag{ &utils.OtsSearchMaxCapFlag, &utils.SilkwormPathFlag, + &utils.SilkwormExecutionFlag, + &utils.SilkwormRpcDaemonFlag, + &utils.SilkwormSentryFlag, &utils.TrustedSetupFile, } diff --git a/turbo/silkworm/load.go b/turbo/silkworm/load.go deleted file mode 100644 index 4ae890436f4..00000000000 --- a/turbo/silkworm/load.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build !linux -// +build !linux - -package silkworm - -import ( - "errors" - "unsafe" -) - -func OpenLibrary(dllPath string) (unsafe.Pointer, error) { - // See https://github.com/golang/go/issues/28024 - return nil, errors.New("Silkworm is only supported on Linux") -} - -func LoadFunction(dllHandle unsafe.Pointer, funcName string) (unsafe.Pointer, error) { - // See https://github.com/golang/go/issues/28024 - return nil, errors.New("Silkworm is only supported on Linux") -} diff --git a/turbo/silkworm/load_linux.go b/turbo/silkworm/load_unix.go similarity index 97% rename from turbo/silkworm/load_linux.go rename to turbo/silkworm/load_unix.go index 5f3113103da..11a22c74822 100644 --- a/turbo/silkworm/load_linux.go +++ b/turbo/silkworm/load_unix.go @@ -1,3 +1,5 @@ +//go:build unix + package silkworm /* diff --git a/turbo/silkworm/load_windows.go b/turbo/silkworm/load_windows.go new file mode 100644 index 00000000000..537411083c1 --- /dev/null +++ b/turbo/silkworm/load_windows.go @@ -0,0 +1,16 @@ +//go:build windows + +package silkworm + +import ( + "errors" + "unsafe" +) + +func OpenLibrary(dllPath string) (unsafe.Pointer, error) { + return nil, errors.New("not implemented") +} + +func LoadFunction(dllHandle unsafe.Pointer, funcName string) (unsafe.Pointer, error) { + return nil, errors.New("not implemented") +} diff --git a/turbo/silkworm/silkworm.go b/turbo/silkworm/silkworm.go index 1463637aff0..d27e6a929c8 100644 --- a/turbo/silkworm/silkworm.go +++ b/turbo/silkworm/silkworm.go @@ -1,156 +1,28 @@ package silkworm /* -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// START silkworm_api.h: C API exported by Silkworm to be used in Erigon. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -#ifndef SILKWORM_API_H_ -#define SILKWORM_API_H_ - -#include -#include -#include #include - -#if defined _MSC_VER -#define SILKWORM_EXPORT __declspec(dllexport) -#else -#define SILKWORM_EXPORT __attribute__((visibility("default"))) -#endif - -#if __cplusplus -#define SILKWORM_NOEXCEPT noexcept -#else -#define SILKWORM_NOEXCEPT -#endif - -#if __cplusplus -extern "C" { -#endif - -typedef struct MDBX_env MDBX_env; -typedef struct MDBX_txn MDBX_txn; - -#define SILKWORM_OK 0 -#define SILKWORM_INTERNAL_ERROR 1 -#define SILKWORM_UNKNOWN_ERROR 2 -#define SILKWORM_INVALID_HANDLE 3 -#define SILKWORM_INVALID_PATH 4 -#define SILKWORM_INVALID_SNAPSHOT 5 -#define SILKWORM_INVALID_MDBX_TXN 6 -#define SILKWORM_INVALID_BLOCK_RANGE 7 -#define SILKWORM_BLOCK_NOT_FOUND 8 -#define SILKWORM_UNKNOWN_CHAIN_ID 9 -#define SILKWORM_MDBX_ERROR 10 -#define SILKWORM_INVALID_BLOCK 11 -#define SILKWORM_DECODING_ERROR 12 -#define SILKWORM_TOO_MANY_INSTANCES 13 -#define SILKWORM_INSTANCE_NOT_FOUND 14 -#define SILKWORM_TERMINATION_SIGNAL 15 - -typedef struct SilkwormHandle SilkwormHandle; - -SILKWORM_EXPORT int silkworm_init(SilkwormHandle** handle) SILKWORM_NOEXCEPT; - -struct SilkwormMemoryMappedFile { - const char* file_path; - uint8_t* memory_address; - uint64_t memory_length; -}; - -struct SilkwormHeadersSnapshot { - struct SilkwormMemoryMappedFile segment; - struct SilkwormMemoryMappedFile header_hash_index; -}; - -struct SilkwormBodiesSnapshot { - struct SilkwormMemoryMappedFile segment; - struct SilkwormMemoryMappedFile block_num_index; -}; - -struct SilkwormTransactionsSnapshot { - struct SilkwormMemoryMappedFile segment; - struct SilkwormMemoryMappedFile tx_hash_index; - struct SilkwormMemoryMappedFile tx_hash_2_block_index; -}; - -struct SilkwormChainSnapshot { - struct SilkwormHeadersSnapshot headers; - struct SilkwormBodiesSnapshot bodies; - struct SilkwormTransactionsSnapshot transactions; -}; - -SILKWORM_EXPORT int silkworm_add_snapshot(SilkwormHandle* handle, struct SilkwormChainSnapshot* snapshot) SILKWORM_NOEXCEPT; - -SILKWORM_EXPORT int silkworm_start_rpcdaemon(SilkwormHandle* handle, MDBX_env* env) SILKWORM_NOEXCEPT; - -SILKWORM_EXPORT int silkworm_stop_rpcdaemon(SilkwormHandle* handle) SILKWORM_NOEXCEPT; - -SILKWORM_EXPORT int silkworm_execute_blocks( - SilkwormHandle* handle, MDBX_txn* txn, uint64_t chain_id, uint64_t start_block, uint64_t max_block, - uint64_t batch_size, bool write_change_sets, bool write_receipts, bool write_call_traces, - uint64_t* last_executed_block, int* mdbx_error_code) SILKWORM_NOEXCEPT; - -SILKWORM_EXPORT int silkworm_fini(SilkwormHandle* handle) SILKWORM_NOEXCEPT; - -#if __cplusplus -} -#endif - -#endif // SILKWORM_API_H_ - -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// -// END silkworm_api.h: C API exported by Silkworm to be used in Erigon. -//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// - -typedef int (*silkworm_init_func)(SilkwormHandle** handle); - -int call_silkworm_init_func(void* func_ptr, SilkwormHandle** handle) { - return ((silkworm_init_func)func_ptr)(handle); -} - -typedef int (*silkworm_add_snapshot_func)(SilkwormHandle* handle, struct SilkwormChainSnapshot* snapshot); - -int call_silkworm_add_snapshot_func(void* func_ptr, SilkwormHandle* handle, struct SilkwormChainSnapshot* snapshot) { - return ((silkworm_add_snapshot_func)func_ptr)(handle, snapshot); -} - -typedef int (*silkworm_start_rpcdaemon_func)(SilkwormHandle* handle, MDBX_env* env); - -int call_silkworm_start_rpcdaemon_func(void* func_ptr, SilkwormHandle* handle, MDBX_env* env) { - return ((silkworm_start_rpcdaemon_func)func_ptr)(handle, env); -} - -typedef int (*silkworm_stop_rpcdaemon_func)(SilkwormHandle* handle); - -int call_silkworm_stop_rpcdaemon_func(void* func_ptr, SilkwormHandle* handle) { - return ((silkworm_stop_rpcdaemon_func)func_ptr)(handle); -} - -typedef int (*silkworm_execute_blocks_func)(SilkwormHandle* handle, MDBX_txn* txn, uint64_t chain_id, uint64_t start_block, - uint64_t max_block, uint64_t batch_size, bool write_change_sets, bool write_receipts, bool write_call_traces, - uint64_t* last_executed_block, int* mdbx_error_code); - -int call_silkworm_execute_blocks_func(void* func_ptr, SilkwormHandle* handle, MDBX_txn* txn, uint64_t chain_id, uint64_t start_block, - uint64_t max_block, uint64_t batch_size, bool write_change_sets, bool write_receipts, bool write_call_traces, - uint64_t* last_executed_block, int* mdbx_error_code) { - return ((silkworm_execute_blocks_func)func_ptr)(handle, txn, chain_id, start_block, max_block, batch_size, write_change_sets, - write_receipts, write_call_traces, last_executed_block, mdbx_error_code); -} - -typedef int (*silkworm_fini_func)(SilkwormHandle* handle); - -int call_silkworm_fini_func(void* func_ptr, SilkwormHandle* handle) { - return ((silkworm_fini_func)func_ptr)(handle); +#include +#include "silkworm_api_bridge.h" + +static bool go_string_copy(_GoString_ s, char *dest, size_t size) { + size_t len = _GoStringLen(s); + if (len >= size) return false; + const char *src = _GoStringPtr(s); + strncpy(dest, src, len); + dest[len] = '\0'; + return true; } */ import "C" + import ( "errors" "fmt" "math/big" + "runtime" "unsafe" "github.com/ledgerwatch/erigon-lib/kv" @@ -158,22 +30,23 @@ import ( ) const ( - SILKWORM_OK = iota - SILKWORM_INTERNAL_ERROR - SILKWORM_UNKNOWN_ERROR - SILKWORM_INVALID_HANDLE - SILKWORM_INVALID_PATH - SILKWORM_INVALID_SNAPSHOT - SILKWORM_INVALID_MDBX_TXN - SILKWORM_INVALID_BLOCK_RANGE - SILKWORM_BLOCK_NOT_FOUND - SILKWORM_UNKNOWN_CHAIN_ID - SILKWORM_MDBX_ERROR - SILKWORM_INVALID_BLOCK - SILKWORM_DECODING_ERROR - SILKWORM_TOO_MANY_INSTANCES - SILKWORM_INSTANCE_NOT_FOUND - SILKWORM_TERMINATION_SIGNAL + SILKWORM_OK = C.SILKWORM_OK + SILKWORM_INTERNAL_ERROR = C.SILKWORM_INTERNAL_ERROR + SILKWORM_UNKNOWN_ERROR = C.SILKWORM_UNKNOWN_ERROR + SILKWORM_INVALID_HANDLE = C.SILKWORM_INVALID_HANDLE + SILKWORM_INVALID_PATH = C.SILKWORM_INVALID_PATH + SILKWORM_INVALID_SNAPSHOT = C.SILKWORM_INVALID_SNAPSHOT + SILKWORM_INVALID_MDBX_TXN = C.SILKWORM_INVALID_MDBX_TXN + SILKWORM_INVALID_BLOCK_RANGE = C.SILKWORM_INVALID_BLOCK_RANGE + SILKWORM_BLOCK_NOT_FOUND = C.SILKWORM_BLOCK_NOT_FOUND + SILKWORM_UNKNOWN_CHAIN_ID = C.SILKWORM_UNKNOWN_CHAIN_ID + SILKWORM_MDBX_ERROR = C.SILKWORM_MDBX_ERROR + SILKWORM_INVALID_BLOCK = C.SILKWORM_INVALID_BLOCK + SILKWORM_DECODING_ERROR = C.SILKWORM_DECODING_ERROR + SILKWORM_TOO_MANY_INSTANCES = C.SILKWORM_TOO_MANY_INSTANCES + SILKWORM_INVALID_SETTINGS = C.SILKWORM_INVALID_SETTINGS + SILKWORM_TERMINATION_SIGNAL = C.SILKWORM_TERMINATION_SIGNAL + SILKWORM_SERVICE_ALREADY_STARTED = C.SILKWORM_SERVICE_ALREADY_STARTED ) // ErrInterrupted is the error returned by Silkworm APIs when stopped by any termination signal. @@ -187,10 +60,12 @@ type Silkworm struct { addSnapshot unsafe.Pointer startRpcDaemon unsafe.Pointer stopRpcDaemon unsafe.Pointer + sentryStart unsafe.Pointer + sentryStop unsafe.Pointer executeBlocks unsafe.Pointer } -func New(dllPath string) (*Silkworm, error) { +func New(dllPath string, dataDirPath string) (*Silkworm, error) { dllHandle, err := OpenLibrary(dllPath) if err != nil { return nil, fmt.Errorf("failed to load silkworm library from path %s: %w", dllPath, err) @@ -216,6 +91,14 @@ func New(dllPath string) (*Silkworm, error) { if err != nil { return nil, fmt.Errorf("failed to load silkworm function silkworm_stop_rpcdaemon: %w", err) } + sentryStart, err := LoadFunction(dllHandle, "silkworm_sentry_start") + if err != nil { + return nil, fmt.Errorf("failed to load silkworm function silkworm_sentry_start: %w", err) + } + sentryStop, err := LoadFunction(dllHandle, "silkworm_sentry_stop") + if err != nil { + return nil, fmt.Errorf("failed to load silkworm function silkworm_sentry_stop: %w", err) + } executeBlocks, err := LoadFunction(dllHandle, "silkworm_execute_blocks") if err != nil { return nil, fmt.Errorf("failed to load silkworm function silkworm_execute_blocks: %w", err) @@ -223,14 +106,24 @@ func New(dllPath string) (*Silkworm, error) { silkworm := &Silkworm{ dllHandle: dllHandle, + instance: nil, initFunc: initFunc, finiFunc: finiFunc, addSnapshot: addSnapshot, startRpcDaemon: startRpcDaemon, stopRpcDaemon: stopRpcDaemon, + sentryStart: sentryStart, + sentryStop: sentryStop, executeBlocks: executeBlocks, } - status := C.call_silkworm_init_func(silkworm.initFunc, &silkworm.instance) //nolint:gocritic + + settings := &C.struct_SilkwormSettings{} + + if !C.go_string_copy(dataDirPath, &settings.data_dir_path[0], C.SILKWORM_PATH_SIZE) { + return nil, errors.New("silkworm.New failed to copy dataDirPath") + } + + status := C.call_silkworm_init_func(silkworm.initFunc, &silkworm.instance, settings) //nolint:gocritic if status == SILKWORM_OK { return silkworm, nil } @@ -333,7 +226,129 @@ func (s *Silkworm) StopRpcDaemon() error { return fmt.Errorf("silkworm_stop_rpcdaemon error %d", status) } +type RpcDaemonService struct { + silkworm *Silkworm + db kv.RoDB +} + +func (s *Silkworm) NewRpcDaemonService(db kv.RoDB) RpcDaemonService { + return RpcDaemonService{ + silkworm: s, + db: db, + } +} + +func (service RpcDaemonService) Start() error { + return service.silkworm.StartRpcDaemon(service.db) +} + +func (service RpcDaemonService) Stop() error { + return service.silkworm.StopRpcDaemon() +} + +type SentrySettings struct { + ClientId string + ApiPort int + Port int + Nat string + NetworkId uint64 + NodeKey []byte + StaticPeers []string + Bootnodes []string + NoDiscover bool + MaxPeers int +} + +func copyPeerURLs(list []string, cList *[C.SILKWORM_SENTRY_SETTINGS_PEERS_MAX][C.SILKWORM_SENTRY_SETTINGS_PEER_URL_SIZE]C.char) error { + listLen := len(list) + if listLen > C.SILKWORM_SENTRY_SETTINGS_PEERS_MAX { + return errors.New("copyPeerURLs: peers URL list has too many items") + } + // mark the list end with an empty string + if listLen < C.SILKWORM_SENTRY_SETTINGS_PEERS_MAX { + cList[listLen][0] = 0 + } + for i, url := range list { + if !C.go_string_copy(url, &cList[i][0], C.SILKWORM_SENTRY_SETTINGS_PEER_URL_SIZE) { + return fmt.Errorf("copyPeerURLs: failed to copy peer URL %d", i) + } + } + return nil +} + +func makeCSentrySettings(settings SentrySettings) (*C.struct_SilkwormSentrySettings, error) { + cSettings := &C.struct_SilkwormSentrySettings{ + api_port: C.uint16_t(settings.ApiPort), + port: C.uint16_t(settings.Port), + network_id: C.uint64_t(settings.NetworkId), + no_discover: C.bool(settings.NoDiscover), + max_peers: C.size_t(settings.MaxPeers), + } + if !C.go_string_copy(settings.ClientId, &cSettings.client_id[0], C.SILKWORM_SENTRY_SETTINGS_CLIENT_ID_SIZE) { + return nil, errors.New("makeCSentrySettings failed to copy ClientId") + } + if !C.go_string_copy(settings.Nat, &cSettings.nat[0], C.SILKWORM_SENTRY_SETTINGS_NAT_SIZE) { + return nil, errors.New("makeCSentrySettings failed to copy Nat") + } + if len(settings.NodeKey) == C.SILKWORM_SENTRY_SETTINGS_NODE_KEY_SIZE { + C.memcpy(unsafe.Pointer(&cSettings.node_key[0]), unsafe.Pointer(&settings.NodeKey[0]), C.SILKWORM_SENTRY_SETTINGS_NODE_KEY_SIZE) //nolint:gocritic + } else { + return nil, errors.New("makeCSentrySettings failed to copy NodeKey") + } + if err := copyPeerURLs(settings.StaticPeers, &cSettings.static_peers); err != nil { + return nil, fmt.Errorf("copyPeerURLs failed to copy StaticPeers: %w", err) + } + if err := copyPeerURLs(settings.Bootnodes, &cSettings.bootnodes); err != nil { + return nil, fmt.Errorf("copyPeerURLs failed to copy Bootnodes: %w", err) + } + return cSettings, nil +} + +func (s *Silkworm) SentryStart(settings SentrySettings) error { + cSettings, err := makeCSentrySettings(settings) + if err != nil { + return err + } + status := C.call_silkworm_sentry_start_func(s.sentryStart, s.instance, cSettings) + if status == SILKWORM_OK { + return nil + } + return fmt.Errorf("silkworm_sentry_start error %d", status) +} + +func (s *Silkworm) SentryStop() error { + status := C.call_silkworm_stop_rpcdaemon_func(s.sentryStop, s.instance) + if status == SILKWORM_OK { + return nil + } + return fmt.Errorf("silkworm_sentry_stop error %d", status) +} + +type SentryService struct { + silkworm *Silkworm + settings SentrySettings +} + +func (s *Silkworm) NewSentryService(settings SentrySettings) SentryService { + return SentryService{ + silkworm: s, + settings: settings, + } +} + +func (service SentryService) Start() error { + return service.silkworm.SentryStart(service.settings) +} + +func (service SentryService) Stop() error { + return service.silkworm.SentryStop() +} + func (s *Silkworm) ExecuteBlocks(txn kv.Tx, chainID *big.Int, startBlock uint64, maxBlock uint64, batchSize uint64, writeChangeSets, writeReceipts, writeCallTraces bool) (lastExecutedBlock uint64, err error) { + if runtime.GOOS == "darwin" { + return 0, errors.New("silkworm execution is incompatible with Go runtime on macOS due to stack size mismatch (see https://github.com/golang/go/issues/28024)") + } + cTxn := (*C.MDBX_txn)(txn.CHandle()) cChainId := C.uint64_t(chainID.Uint64()) cStartBlock := C.uint64_t(startBlock) @@ -351,7 +366,7 @@ func (s *Silkworm) ExecuteBlocks(txn kv.Tx, chainID *big.Int, startBlock uint64, if status == SILKWORM_OK { return lastExecutedBlock, nil } - // Handle special erros + // Handle special errors if status == SILKWORM_INVALID_BLOCK { return lastExecutedBlock, consensus.ErrInvalidBlock } diff --git a/turbo/silkworm/silkworm_api.h b/turbo/silkworm/silkworm_api.h new file mode 100644 index 00000000000..91ea519551b --- /dev/null +++ b/turbo/silkworm/silkworm_api.h @@ -0,0 +1,206 @@ +/* + Copyright 2023 The Silkworm Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef SILKWORM_API_H_ +#define SILKWORM_API_H_ + +// C API exported by Silkworm to be used in Erigon. + +#include // NOLINT(*-deprecated-headers) +#include // NOLINT(*-deprecated-headers) +#include // NOLINT(*-deprecated-headers) + +#if defined _MSC_VER +#define SILKWORM_EXPORT __declspec(dllexport) +#else +#define SILKWORM_EXPORT __attribute__((visibility("default"))) +#endif + +#if __cplusplus +#define SILKWORM_NOEXCEPT noexcept +#else +#define SILKWORM_NOEXCEPT +#endif + +#if __cplusplus +extern "C" { +#endif + +// Silkworm library error codes (SILKWORM_OK indicates no error, i.e. success) + +#define SILKWORM_OK 0 +#define SILKWORM_INTERNAL_ERROR 1 +#define SILKWORM_UNKNOWN_ERROR 2 +#define SILKWORM_INVALID_HANDLE 3 +#define SILKWORM_INVALID_PATH 4 +#define SILKWORM_INVALID_SNAPSHOT 5 +#define SILKWORM_INVALID_MDBX_TXN 6 +#define SILKWORM_INVALID_BLOCK_RANGE 7 +#define SILKWORM_BLOCK_NOT_FOUND 8 +#define SILKWORM_UNKNOWN_CHAIN_ID 9 +#define SILKWORM_MDBX_ERROR 10 +#define SILKWORM_INVALID_BLOCK 11 +#define SILKWORM_DECODING_ERROR 12 +#define SILKWORM_TOO_MANY_INSTANCES 13 +#define SILKWORM_INVALID_SETTINGS 14 +#define SILKWORM_TERMINATION_SIGNAL 15 +#define SILKWORM_SERVICE_ALREADY_STARTED 16 + +typedef struct MDBX_env MDBX_env; +typedef struct MDBX_txn MDBX_txn; +typedef struct SilkwormHandle SilkwormHandle; + +struct SilkwormMemoryMappedFile { + const char* file_path; + uint8_t* memory_address; + uint64_t memory_length; +}; + +struct SilkwormHeadersSnapshot { + struct SilkwormMemoryMappedFile segment; + struct SilkwormMemoryMappedFile header_hash_index; +}; + +struct SilkwormBodiesSnapshot { + struct SilkwormMemoryMappedFile segment; + struct SilkwormMemoryMappedFile block_num_index; +}; + +struct SilkwormTransactionsSnapshot { + struct SilkwormMemoryMappedFile segment; + struct SilkwormMemoryMappedFile tx_hash_index; + struct SilkwormMemoryMappedFile tx_hash_2_block_index; +}; + +struct SilkwormChainSnapshot { + struct SilkwormHeadersSnapshot headers; + struct SilkwormBodiesSnapshot bodies; + struct SilkwormTransactionsSnapshot transactions; +}; + +#define SILKWORM_PATH_SIZE 260 + +struct SilkwormSettings { + //! Data directory path in UTF-8. + char data_dir_path[SILKWORM_PATH_SIZE]; +}; + +/** + * \brief Initialize the Silkworm C API library. + * \param[in,out] handle Silkworm instance handle returned on successful initialization. + * \param[in] settings General Silkworm settings. + * \return SILKWORM_OK (=0) on success, a non-zero error value on failure. + */ +SILKWORM_EXPORT int silkworm_init( + SilkwormHandle** handle, + const struct SilkwormSettings* settings) SILKWORM_NOEXCEPT; + +/** + * \brief Build a set of indexes for the given snapshots. + * \param[in] handle A valid Silkworm instance handle, got with silkworm_init. + * \param[in] snapshots An array of snapshots to index. + * \param[in] indexPaths An array of paths to write indexes to. + * Note that the name of the index is a part of the path and it is used to determine the index type. + * \param[in] len The number of snapshots and paths. + * \return SILKWORM_OK (=0) on success, a non-zero error value on failure on some or all indexes. + */ +SILKWORM_EXPORT int silkworm_build_recsplit_indexes(SilkwormHandle* handle, struct SilkwormMemoryMappedFile* snapshots[], int len) SILKWORM_NOEXCEPT; + +/** + * \brief Notify Silkworm about a new snapshot to use. + * \param[in] handle A valid Silkworm instance handle, got with silkworm_init. + * \param[in] snapshot A snapshot to use. + * \return SILKWORM_OK (=0) on success, a non-zero error value on failure. + */ +SILKWORM_EXPORT int silkworm_add_snapshot(SilkwormHandle* handle, struct SilkwormChainSnapshot* snapshot) SILKWORM_NOEXCEPT; + +/** + * \brief Start Silkworm RPC daemon. + * \param[in] handle A valid Silkworm instance handle, got with silkworm_init.Must not be zero. + * \param[in] env An valid MDBX environment. Must not be zero. + * \return SILKWORM_OK (=0) on success, a non-zero error value on failure. + */ +SILKWORM_EXPORT int silkworm_start_rpcdaemon(SilkwormHandle* handle, MDBX_env* env) SILKWORM_NOEXCEPT; + +/** + * \brief Stop Silkworm RPC daemon and wait for its termination. + * \param[in] handle A valid Silkworm instance handle, got with silkworm_init. Must not be zero. + * \param[in] snapshot A snapshot to use. + * \return SILKWORM_OK (=0) on success, a non-zero error value on failure. + */ +SILKWORM_EXPORT int silkworm_stop_rpcdaemon(SilkwormHandle* handle) SILKWORM_NOEXCEPT; + +#define SILKWORM_SENTRY_SETTINGS_CLIENT_ID_SIZE 128 +#define SILKWORM_SENTRY_SETTINGS_NAT_SIZE 50 +#define SILKWORM_SENTRY_SETTINGS_NODE_KEY_SIZE 32 +#define SILKWORM_SENTRY_SETTINGS_PEERS_MAX 128 +#define SILKWORM_SENTRY_SETTINGS_PEER_URL_SIZE 200 + +struct SilkwormSentrySettings { + char client_id[SILKWORM_SENTRY_SETTINGS_CLIENT_ID_SIZE]; + uint16_t api_port; + uint16_t port; + char nat[SILKWORM_SENTRY_SETTINGS_NAT_SIZE]; + uint64_t network_id; + uint8_t node_key[SILKWORM_SENTRY_SETTINGS_NODE_KEY_SIZE]; + char static_peers[SILKWORM_SENTRY_SETTINGS_PEERS_MAX][SILKWORM_SENTRY_SETTINGS_PEER_URL_SIZE]; + char bootnodes[SILKWORM_SENTRY_SETTINGS_PEERS_MAX][SILKWORM_SENTRY_SETTINGS_PEER_URL_SIZE]; + bool no_discover; + size_t max_peers; +}; + +SILKWORM_EXPORT int silkworm_sentry_start(SilkwormHandle* handle, const struct SilkwormSentrySettings* settings) SILKWORM_NOEXCEPT; +SILKWORM_EXPORT int silkworm_sentry_stop(SilkwormHandle* handle) SILKWORM_NOEXCEPT; + +/** + * \brief Execute a batch of blocks and write resulting changes into the database. + * \param[in] handle A valid Silkworm instance handle, got with silkworm_init. + * \param[in] txn A valid read-write MDBX transaction. Must not be zero. + * This function does not commit nor abort the transaction. + * \param[in] chain_id EIP-155 chain ID. SILKWORM_UNKNOWN_CHAIN_ID is returned in case of an unknown or unsupported chain. + * \param[in] start_block The block height to start the execution from. + * \param[in] max_block Do not execute after this block. + * max_block may be executed, or the execution may stop earlier if the batch is full. + * \param[in] batch_size The size of DB changes to accumulate before returning from this method. + * Pass 0 if you want to execute just 1 block. + * \param[in] write_change_sets Whether to write state changes into the DB. + * \param[in] write_receipts Whether to write CBOR-encoded receipts into the DB. + * \param[in] write_call_traces Whether to write call traces into the DB. + * \param[out] last_executed_block The height of the last successfully executed block. + * Not written to if no blocks were executed, otherwise *last_executed_block ≤ max_block. + * \param[out] mdbx_error_code If an MDBX error occurs (this function returns kSilkwormMdbxError) + * and mdbx_error_code isn't NULL, it's populated with the relevant MDBX error code. + * \return SILKWORM_OK (=0) on success, a non-zero error value on failure. + * SILKWORM_BLOCK_NOT_FOUND is probably OK: it simply means that the execution reached the end of the chain + * (blocks up to and incl. last_executed_block were still executed). + */ +SILKWORM_EXPORT int silkworm_execute_blocks( + SilkwormHandle* handle, MDBX_txn* txn, uint64_t chain_id, uint64_t start_block, uint64_t max_block, + uint64_t batch_size, bool write_change_sets, bool write_receipts, bool write_call_traces, + uint64_t* last_executed_block, int* mdbx_error_code) SILKWORM_NOEXCEPT; + +/** + * \brief Finalize the Silkworm C API library. + * \param[in] handle A valid Silkworm instance handle got with silkworm_init. + * \return SILKWORM_OK (=0) on success, a non-zero error value on failure. + */ +SILKWORM_EXPORT int silkworm_fini(SilkwormHandle* handle) SILKWORM_NOEXCEPT; + +#if __cplusplus +} +#endif + +#endif // SILKWORM_API_H_ diff --git a/turbo/silkworm/silkworm_api_bridge.h b/turbo/silkworm/silkworm_api_bridge.h new file mode 100644 index 00000000000..2969ca62e6f --- /dev/null +++ b/turbo/silkworm/silkworm_api_bridge.h @@ -0,0 +1,75 @@ +/* + Copyright 2023 The Silkworm Authors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef SILKWORM_API_FUNC_H_ +#define SILKWORM_API_FUNC_H_ + +#include "silkworm_api.h" + +typedef int (*silkworm_init_func)(SilkwormHandle** handle, const struct SilkwormSettings* settings); + +int call_silkworm_init_func(void* func_ptr, SilkwormHandle** handle, const struct SilkwormSettings* settings) { + return ((silkworm_init_func)func_ptr)(handle, settings); +} + +typedef int (*silkworm_add_snapshot_func)(SilkwormHandle* handle, struct SilkwormChainSnapshot* snapshot); + +int call_silkworm_add_snapshot_func(void* func_ptr, SilkwormHandle* handle, struct SilkwormChainSnapshot* snapshot) { + return ((silkworm_add_snapshot_func)func_ptr)(handle, snapshot); +} + +typedef int (*silkworm_start_rpcdaemon_func)(SilkwormHandle* handle, MDBX_env* env); + +int call_silkworm_start_rpcdaemon_func(void* func_ptr, SilkwormHandle* handle, MDBX_env* env) { + return ((silkworm_start_rpcdaemon_func)func_ptr)(handle, env); +} + +typedef int (*silkworm_stop_rpcdaemon_func)(SilkwormHandle* handle); + +int call_silkworm_stop_rpcdaemon_func(void* func_ptr, SilkwormHandle* handle) { + return ((silkworm_stop_rpcdaemon_func)func_ptr)(handle); +} + +typedef int (*silkworm_sentry_start_func)(SilkwormHandle* handle, const struct SilkwormSentrySettings* settings); + +int call_silkworm_sentry_start_func(void* func_ptr, SilkwormHandle* handle, const struct SilkwormSentrySettings* settings) { + return ((silkworm_sentry_start_func)func_ptr)(handle, settings); +} + +typedef int (*silkworm_sentry_stop_func)(SilkwormHandle* handle); + +int call_silkworm_sentry_stop_func(void* func_ptr, SilkwormHandle* handle) { + return ((silkworm_sentry_stop_func)func_ptr)(handle); +} + +typedef int (*silkworm_execute_blocks_func)(SilkwormHandle* handle, MDBX_txn* txn, uint64_t chain_id, uint64_t start_block, + uint64_t max_block, uint64_t batch_size, bool write_change_sets, bool write_receipts, bool write_call_traces, + uint64_t* last_executed_block, int* mdbx_error_code); + +int call_silkworm_execute_blocks_func(void* func_ptr, SilkwormHandle* handle, MDBX_txn* txn, uint64_t chain_id, uint64_t start_block, + uint64_t max_block, uint64_t batch_size, bool write_change_sets, bool write_receipts, bool write_call_traces, + uint64_t* last_executed_block, int* mdbx_error_code) { + return ((silkworm_execute_blocks_func)func_ptr)(handle, txn, chain_id, start_block, max_block, batch_size, write_change_sets, + write_receipts, write_call_traces, last_executed_block, mdbx_error_code); +} + +typedef int (*silkworm_fini_func)(SilkwormHandle* handle); + +int call_silkworm_fini_func(void* func_ptr, SilkwormHandle* handle) { + return ((silkworm_fini_func)func_ptr)(handle); +} + +#endif // SILKWORM_API_FUNC_H_ diff --git a/turbo/stages/mock/mock_sentry.go b/turbo/stages/mock/mock_sentry.go index df9e7df5f54..de6ba517f34 100644 --- a/turbo/stages/mock/mock_sentry.go +++ b/turbo/stages/mock/mock_sentry.go @@ -33,7 +33,6 @@ import ( "github.com/ledgerwatch/erigon-lib/txpool/txpoolcfg" types2 "github.com/ledgerwatch/erigon-lib/types" - "github.com/ledgerwatch/erigon/cmd/sentry/sentry" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor" "github.com/ledgerwatch/erigon/consensus/ethash" @@ -51,6 +50,7 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/ethdb/prune" + "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" "github.com/ledgerwatch/erigon/params" "github.com/ledgerwatch/erigon/rlp" "github.com/ledgerwatch/erigon/turbo/builder" @@ -84,7 +84,7 @@ type MockSentry struct { MiningSync *stagedsync.Sync PendingBlocks chan *types.Block MinedBlocks chan *types.Block - sentriesClient *sentry.MultiClient + sentriesClient *sentry_multi_client.MultiClient Key *ecdsa.PrivateKey Genesis *types.Block SentryClient direct.SentryClient @@ -367,7 +367,7 @@ func MockWithEverything(tb testing.TB, gspec *types.Genesis, key *ecdsa.PrivateK networkID := uint64(1) maxBlockBroadcastPeers := func(header *types.Header) uint { return 0 } - mock.sentriesClient, err = sentry.NewMultiClient( + mock.sentriesClient, err = sentry_multi_client.NewMultiClient( mock.DB, "mock", mock.ChainConfig, diff --git a/turbo/stages/stageloop.go b/turbo/stages/stageloop.go index 3ee7d432fe3..56a1bbd6082 100644 --- a/turbo/stages/stageloop.go +++ b/turbo/stages/stageloop.go @@ -19,7 +19,6 @@ import ( "github.com/ledgerwatch/erigon-lib/kv/membatchwithdb" "github.com/ledgerwatch/erigon-lib/state" - "github.com/ledgerwatch/erigon/cmd/sentry/sentry" "github.com/ledgerwatch/erigon/consensus" "github.com/ledgerwatch/erigon/consensus/bor/finality/flags" "github.com/ledgerwatch/erigon/consensus/bor/heimdall" @@ -32,6 +31,7 @@ import ( "github.com/ledgerwatch/erigon/eth/stagedsync" "github.com/ledgerwatch/erigon/eth/stagedsync/stages" "github.com/ledgerwatch/erigon/p2p" + "github.com/ledgerwatch/erigon/p2p/sentry/sentry_multi_client" "github.com/ledgerwatch/erigon/turbo/engineapi/engine_helpers" "github.com/ledgerwatch/erigon/turbo/services" "github.com/ledgerwatch/erigon/turbo/shards" @@ -443,11 +443,18 @@ func StateStep(ctx context.Context, chainReader consensus.ChainReader, engine co return nil } +func silkwormForExecutionStage(silkworm *silkworm.Silkworm, cfg *ethconfig.Config) *silkworm.Silkworm { + if cfg.SilkwormExecution { + return silkworm + } + return nil +} + func NewDefaultStages(ctx context.Context, db kv.RwDB, p2pCfg p2p.Config, cfg *ethconfig.Config, - controlServer *sentry.MultiClient, + controlServer *sentry_multi_client.MultiClient, notifications *shards.Notifications, snapDownloader proto_downloader.DownloaderClient, blockReader services.FullBlockReader, @@ -496,7 +503,7 @@ func NewDefaultStages(ctx context.Context, cfg.Genesis, cfg.Sync, agg, - silkworm, + silkwormForExecutionStage(silkworm, cfg), ), stagedsync.StageHashStateCfg(db, dirs, cfg.HistoryV3), stagedsync.StageTrieCfg(db, true, true, false, dirs.Tmp, blockReader, controlServer.Hd, cfg.HistoryV3, agg), @@ -511,7 +518,7 @@ func NewDefaultStages(ctx context.Context, func NewPipelineStages(ctx context.Context, db kv.RwDB, cfg *ethconfig.Config, - controlServer *sentry.MultiClient, + controlServer *sentry_multi_client.MultiClient, notifications *shards.Notifications, snapDownloader proto_downloader.DownloaderClient, blockReader services.FullBlockReader, @@ -551,7 +558,7 @@ func NewPipelineStages(ctx context.Context, cfg.Genesis, cfg.Sync, agg, - silkworm, + silkwormForExecutionStage(silkworm, cfg), ), stagedsync.StageHashStateCfg(db, dirs, cfg.HistoryV3), stagedsync.StageTrieCfg(db, checkStateRoot, true, false, dirs.Tmp, blockReader, controlServer.Hd, cfg.HistoryV3, agg), @@ -563,7 +570,7 @@ func NewPipelineStages(ctx context.Context, runInTestMode) } -func NewInMemoryExecution(ctx context.Context, db kv.RwDB, cfg *ethconfig.Config, controlServer *sentry.MultiClient, +func NewInMemoryExecution(ctx context.Context, db kv.RwDB, cfg *ethconfig.Config, controlServer *sentry_multi_client.MultiClient, dirs datadir.Dirs, notifications *shards.Notifications, blockReader services.FullBlockReader, blockWriter *blockio.BlockWriter, agg *state.AggregatorV3, silkworm *silkworm.Silkworm, logger log.Logger) *stagedsync.Sync { return stagedsync.New( @@ -590,7 +597,7 @@ func NewInMemoryExecution(ctx context.Context, db kv.RwDB, cfg *ethconfig.Config cfg.Genesis, cfg.Sync, agg, - silkworm, + silkwormForExecutionStage(silkworm, cfg), ), stagedsync.StageHashStateCfg(db, dirs, cfg.HistoryV3), stagedsync.StageTrieCfg(db, true, true, true, dirs.Tmp, blockReader, controlServer.Hd, cfg.HistoryV3, agg)), From 714fa0fdc767a34b57a76b67b90ec0a186b46fc2 Mon Sep 17 00:00:00 2001 From: Alex Sharov Date: Thu, 2 Nov 2023 14:14:39 +0700 Subject: [PATCH 42/44] mainnet 18.3M snaps (#8639) --- erigon-lib/go.mod | 2 +- erigon-lib/go.sum | 4 ++-- go.mod | 2 +- go.sum | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/erigon-lib/go.mod b/erigon-lib/go.mod index 0b664a64784..21986c37eee 100644 --- a/erigon-lib/go.mod +++ b/erigon-lib/go.mod @@ -4,7 +4,7 @@ go 1.20 require ( github.com/erigontech/mdbx-go v0.35.2-0.20231101074031-9f999220e9ed - github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66 + github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231102060711-19219b948f46 github.com/ledgerwatch/interfaces v0.0.0-20231031050643-c86352e41520 github.com/ledgerwatch/log/v3 v3.9.0 github.com/ledgerwatch/secp256k1 v1.0.0 diff --git a/erigon-lib/go.sum b/erigon-lib/go.sum index b979ec8ea6e..03c789a7c1c 100644 --- a/erigon-lib/go.sum +++ b/erigon-lib/go.sum @@ -291,8 +291,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66 h1:0GY0mXeC6ThOw1x50tF1dDWso0kL6a5SS7k/zrsIF60= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231102060711-19219b948f46 h1:yt3/AcefMQOzY/P05jyeaKpqMQvrCbL6OJWALsjKp5U= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231102060711-19219b948f46/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= github.com/ledgerwatch/interfaces v0.0.0-20231031050643-c86352e41520 h1:j/PRJWbPrbk8wpVjU77SWS8xJ/N+dcxPs1relNSolUs= github.com/ledgerwatch/interfaces v0.0.0-20231031050643-c86352e41520/go.mod h1:ugQv1QllJzBny3cKZKxUrSnykkjkBgm27eQM6dnGAcc= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= diff --git a/go.mod b/go.mod index da91f15babf..c004d8dd12c 100644 --- a/go.mod +++ b/go.mod @@ -186,7 +186,7 @@ require ( github.com/koron/go-ssdp v0.0.4 // indirect github.com/kr/pretty v0.3.1 // indirect github.com/kr/text v0.2.0 // indirect - github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66 // indirect + github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231102060711-19219b948f46 // indirect github.com/libp2p/go-buffer-pool v0.1.0 // indirect github.com/libp2p/go-cidranger v1.1.0 // indirect github.com/libp2p/go-flow-metrics v0.1.0 // indirect diff --git a/go.sum b/go.sum index 749effc2a21..e64dfc0bff6 100644 --- a/go.sum +++ b/go.sum @@ -539,8 +539,8 @@ github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170224010052-a616ab194758 h1:0D5M2HQSGD3PYPwICLl+/9oulQauOuETfgFvhBDffs0= github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c= github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66 h1:0GY0mXeC6ThOw1x50tF1dDWso0kL6a5SS7k/zrsIF60= -github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231101135659-d85154191b66/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231102060711-19219b948f46 h1:yt3/AcefMQOzY/P05jyeaKpqMQvrCbL6OJWALsjKp5U= +github.com/ledgerwatch/erigon-snapshot v1.3.1-0.20231102060711-19219b948f46/go.mod h1:3AuPxZc85jkehh/HA9h8gabv5MSi3kb/ddtzBsTVJFo= github.com/ledgerwatch/log/v3 v3.9.0 h1:iDwrXe0PVwBC68Dd94YSsHbMgQ3ufsgjzXtFNFVZFRk= github.com/ledgerwatch/log/v3 v3.9.0/go.mod h1:EiAY6upmI/6LkNhOVxb4eVsmsP11HZCnZ3PlJMjYiqE= github.com/ledgerwatch/secp256k1 v1.0.0 h1:Usvz87YoTG0uePIV8woOof5cQnLXGYa162rFf3YnwaQ= From de9f8881dff1688015f0a87f2712d33010a8f6dc Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Thu, 2 Nov 2023 10:20:47 -0400 Subject: [PATCH 43/44] Update external test replace directives --- tests/erigon-ext-test/go.mod.template | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/erigon-ext-test/go.mod.template b/tests/erigon-ext-test/go.mod.template index 515b3b14281..5e56bf3d761 100644 --- a/tests/erigon-ext-test/go.mod.template +++ b/tests/erigon-ext-test/go.mod.template @@ -2,8 +2,10 @@ module example.com/erigon-ext-test go 1.20 -require github.com/ledgerwatch/erigon $COMMIT_SHA +require github.com/ledgerwatch/erigon devel -replace github.com/ledgerwatch/erigon-lib => github.com/ledgerwatch/erigon/erigon-lib $COMMIT_SHA +replace github.com/ledgerwatch/erigon => github.com/bobanetwork/v3-erigon $COMMIT_SHA + +replace github.com/ledgerwatch/erigon-lib => github.com/bobanetwork/v3-erigon/erigon-lib $COMMIT_SHA require github.com/ethereum/go-ethereum v1.13.3 From 76835722716c31dfbeebfbe713103d1f25054c2f Mon Sep 17 00:00:00 2001 From: Jason Yellick Date: Thu, 2 Nov 2023 10:51:04 -0400 Subject: [PATCH 44/44] Slightly enlarge the 'heavy' struct size We are getting linter errors, because the addition of the historical RPC endpoints is making the http config struct slightly larger. I suspect upstream will run into the problem soon, so as a simple workaround, this change slightly enlarges the heavy struct max size. --- .golangci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.golangci.yml b/.golangci.yml index 774ddc7e451..efe83b4f9aa 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -81,7 +81,7 @@ linters-settings: rules: "rules.go" hugeParam: # size in bytes that makes the warning trigger (default 80) - sizeThreshold: 1000 + sizeThreshold: 1100 rangeExprCopy: # size in bytes that makes the warning trigger (default 512) sizeThreshold: 512