github.com/ethereum/go-ethereum@v1.16.1/internal/era/eradl/eradl.go (about) 1 // Copyright 2025 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 // Package eradl implements downloading of era1 files. 18 package eradl 19 20 import ( 21 _ "embed" 22 "fmt" 23 "net/url" 24 "path/filepath" 25 "regexp" 26 "strconv" 27 28 "github.com/ethereum/go-ethereum/internal/download" 29 "github.com/ethereum/go-ethereum/internal/era" 30 ) 31 32 //go:embed checksums_mainnet.txt 33 var mainnetDB []byte 34 35 //go:embed checksums_sepolia.txt 36 var sepoliaDB []byte 37 38 type Loader struct { 39 csdb *download.ChecksumDB 40 network string 41 baseURL *url.URL 42 } 43 44 // New creates an era1 loader for the given server URL and network name. 45 func New(baseURL string, network string) (*Loader, error) { 46 var checksums []byte 47 switch network { 48 case "mainnet": 49 checksums = mainnetDB 50 case "sepolia": 51 checksums = sepoliaDB 52 default: 53 return nil, fmt.Errorf("missing era1 checksum definitions for network %q", network) 54 } 55 56 csdb, err := download.ParseChecksums(checksums) 57 if err != nil { 58 return nil, fmt.Errorf("invalid checksums: %v", err) 59 } 60 61 base, err := url.Parse(baseURL) 62 if err != nil { 63 return nil, fmt.Errorf("invalid base URL %q: %v", baseURL, err) 64 } 65 if base.Scheme != "http" && base.Scheme != "https" { 66 return nil, fmt.Errorf("invalid base URL scheme, expected http(s): %q", baseURL) 67 } 68 69 l := &Loader{ 70 network: network, 71 csdb: csdb, 72 baseURL: base, 73 } 74 return l, nil 75 } 76 77 // DownloadAll downloads all known era1 files to the given directory. 78 func (l *Loader) DownloadAll(destDir string) error { 79 for file := range l.csdb.Files() { 80 if err := l.download(file, destDir); err != nil { 81 return err 82 } 83 } 84 return nil 85 } 86 87 // DownloadBlockRange fetches the era1 files for the given block range. 88 func (l *Loader) DownloadBlockRange(start, end uint64, destDir string) error { 89 startEpoch := start / uint64(era.MaxEra1Size) 90 endEpoch := end / uint64(era.MaxEra1Size) 91 return l.DownloadEpochRange(startEpoch, endEpoch, destDir) 92 } 93 94 // DownloadEpochRange fetches the era1 files in the given epoch range. 95 func (l *Loader) DownloadEpochRange(start, end uint64, destDir string) error { 96 pat := regexp.MustCompile(regexp.QuoteMeta(l.network) + "-([0-9]+)-[0-9a-f]+\\.era1") 97 for file := range l.csdb.Files() { 98 m := pat.FindStringSubmatch(file) 99 if len(m) == 2 { 100 fileEpoch, _ := strconv.Atoi(m[1]) 101 if uint64(fileEpoch) >= start && uint64(fileEpoch) <= end { 102 if err := l.download(file, destDir); err != nil { 103 return err 104 } 105 } 106 } 107 } 108 return nil 109 } 110 111 func (l *Loader) download(file, destDir string) error { 112 url := l.baseURL.JoinPath(file).String() 113 dest := filepath.Join(destDir, file) 114 return l.csdb.DownloadFile(url, dest) 115 }