Delete internal directory

Signed-off-by: Isabel Schöps Thiel @IsabelSchoepd <155141998+IST-Github@users.noreply.github.com>
This commit is contained in:
Isabel Schöps Thiel @IsabelSchoepd 2024-01-04 04:29:40 +01:00 committed by GitHub
parent f974fde3fe
commit 35587a352c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
91 changed files with 0 additions and 25380 deletions

View file

@ -1,59 +0,0 @@
// Copyright 2023 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package utesting provides a standalone replacement for package testing.
//
// This package exists because package testing cannot easily be embedded into a
// standalone go program. It provides an API that mirrors the standard library
// testing API.
package blocktest
import (
"hash"
"github.com/ethereum/go-ethereum/common"
"golang.org/x/crypto/sha3"
)
// testHasher is the helper tool for transaction/receipt list hashing.
// The original hasher is trie, in order to get rid of import cycle,
// use the testing hasher instead.
type testHasher struct {
hasher hash.Hash
}
// NewHasher returns a new testHasher instance.
func NewHasher() *testHasher {
return &testHasher{hasher: sha3.NewLegacyKeccak256()}
}
// Reset resets the hash state.
func (h *testHasher) Reset() {
h.hasher.Reset()
}
// Update updates the hash state with the given key and value.
func (h *testHasher) Update(key, val []byte) error {
h.hasher.Write(key)
h.hasher.Write(val)
return nil
}
// Hash returns the hash value.
func (h *testHasher) Hash() common.Hash {
return common.BytesToHash(h.hasher.Sum(nil))
}

View file

@ -1,291 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package build
import (
"archive/tar"
"archive/zip"
"compress/gzip"
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"time"
)
type Archive interface {
// Directory adds a new directory entry to the archive and sets the
// directory for subsequent calls to Header.
Directory(name string) error
// Header adds a new file to the archive. The file is added to the directory
// set by Directory. The content of the file must be written to the returned
// writer.
Header(os.FileInfo) (io.Writer, error)
// Close flushes the archive and closes the underlying file.
Close() error
}
func NewArchive(file *os.File) (Archive, string) {
switch {
case strings.HasSuffix(file.Name(), ".zip"):
return NewZipArchive(file), strings.TrimSuffix(file.Name(), ".zip")
case strings.HasSuffix(file.Name(), ".tar.gz"):
return NewTarballArchive(file), strings.TrimSuffix(file.Name(), ".tar.gz")
default:
return nil, ""
}
}
// AddFile appends an existing file to an archive.
func AddFile(a Archive, file string) error {
fd, err := os.Open(file)
if err != nil {
return err
}
defer fd.Close()
fi, err := fd.Stat()
if err != nil {
return err
}
w, err := a.Header(fi)
if err != nil {
return err
}
if _, err := io.Copy(w, fd); err != nil {
return err
}
return nil
}
// WriteArchive creates an archive containing the given files.
func WriteArchive(name string, files []string) (err error) {
archfd, err := os.Create(name)
if err != nil {
return err
}
defer func() {
archfd.Close()
// Remove the half-written archive on failure.
if err != nil {
os.Remove(name)
}
}()
archive, basename := NewArchive(archfd)
if archive == nil {
return errors.New("unknown archive extension")
}
fmt.Println(name)
if err := archive.Directory(basename); err != nil {
return err
}
for _, file := range files {
fmt.Println(" +", filepath.Base(file))
if err := AddFile(archive, file); err != nil {
return err
}
}
return archive.Close()
}
type ZipArchive struct {
dir string
zipw *zip.Writer
file io.Closer
}
func NewZipArchive(w io.WriteCloser) Archive {
return &ZipArchive{"", zip.NewWriter(w), w}
}
func (a *ZipArchive) Directory(name string) error {
a.dir = name + "/"
return nil
}
func (a *ZipArchive) Header(fi os.FileInfo) (io.Writer, error) {
head, err := zip.FileInfoHeader(fi)
if err != nil {
return nil, fmt.Errorf("can't make zip header: %v", err)
}
head.Name = a.dir + head.Name
head.Method = zip.Deflate
w, err := a.zipw.CreateHeader(head)
if err != nil {
return nil, fmt.Errorf("can't add zip header: %v", err)
}
return w, nil
}
func (a *ZipArchive) Close() error {
if err := a.zipw.Close(); err != nil {
return err
}
return a.file.Close()
}
type TarballArchive struct {
dir string
tarw *tar.Writer
gzw *gzip.Writer
file io.Closer
}
func NewTarballArchive(w io.WriteCloser) Archive {
gzw := gzip.NewWriter(w)
tarw := tar.NewWriter(gzw)
return &TarballArchive{"", tarw, gzw, w}
}
func (a *TarballArchive) Directory(name string) error {
a.dir = name + "/"
return a.tarw.WriteHeader(&tar.Header{
Name: a.dir,
Mode: 0755,
Typeflag: tar.TypeDir,
ModTime: time.Now(),
})
}
func (a *TarballArchive) Header(fi os.FileInfo) (io.Writer, error) {
head, err := tar.FileInfoHeader(fi, "")
if err != nil {
return nil, fmt.Errorf("can't make tar header: %v", err)
}
head.Name = a.dir + head.Name
if err := a.tarw.WriteHeader(head); err != nil {
return nil, fmt.Errorf("can't add tar header: %v", err)
}
return a.tarw, nil
}
func (a *TarballArchive) Close() error {
if err := a.tarw.Close(); err != nil {
return err
}
if err := a.gzw.Close(); err != nil {
return err
}
return a.file.Close()
}
// ExtractArchive unpacks a .zip or .tar.gz archive to the destination directory.
func ExtractArchive(archive string, dest string) error {
ar, err := os.Open(archive)
if err != nil {
return err
}
defer ar.Close()
switch {
case strings.HasSuffix(archive, ".tar.gz"):
return extractTarball(ar, dest)
case strings.HasSuffix(archive, ".zip"):
return extractZip(ar, dest)
default:
return fmt.Errorf("unhandled archive type %s", archive)
}
}
// extractTarball unpacks a .tar.gz file.
func extractTarball(ar io.Reader, dest string) error {
gzr, err := gzip.NewReader(ar)
if err != nil {
return err
}
defer gzr.Close()
tr := tar.NewReader(gzr)
for {
// Move to the next file header.
header, err := tr.Next()
if err != nil {
if err == io.EOF {
return nil
}
return err
}
// We only care about regular files, directory modes
// and special file types are not supported.
if header.Typeflag == tar.TypeReg {
armode := header.FileInfo().Mode()
err := extractFile(header.Name, armode, tr, dest)
if err != nil {
return fmt.Errorf("extract %s: %v", header.Name, err)
}
}
}
}
// extractZip unpacks the given .zip file.
func extractZip(ar *os.File, dest string) error {
info, err := ar.Stat()
if err != nil {
return err
}
zr, err := zip.NewReader(ar, info.Size())
if err != nil {
return err
}
for _, zf := range zr.File {
if !zf.Mode().IsRegular() {
continue
}
data, err := zf.Open()
if err != nil {
return err
}
err = extractFile(zf.Name, zf.Mode(), data, dest)
data.Close()
if err != nil {
return fmt.Errorf("extract %s: %v", zf.Name, err)
}
}
return nil
}
// extractFile extracts a single file from an archive.
func extractFile(arpath string, armode os.FileMode, data io.Reader, dest string) error {
// Check that path is inside destination directory.
target := filepath.Join(dest, filepath.FromSlash(arpath))
if !strings.HasPrefix(target, filepath.Clean(dest)+string(os.PathSeparator)) {
return fmt.Errorf("path %q escapes archive destination", target)
}
// Ensure the destination directory exists.
if err := os.MkdirAll(filepath.Dir(target), 0755); err != nil {
return err
}
// Copy file data.
file, err := os.OpenFile(target, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, armode)
if err != nil {
return err
}
if _, err := io.Copy(file, data); err != nil {
file.Close()
os.Remove(target)
return err
}
return file.Close()
}

View file

@ -1,120 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package build
import (
"context"
"fmt"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azblob/container"
)
// AzureBlobstoreConfig is an authentication and configuration struct containing
// the data needed by the Azure SDK to interact with a specific container in the
// blobstore.
type AzureBlobstoreConfig struct {
Account string // Account name to authorize API requests with
Token string // Access token for the above account
Container string // Blob container to upload files into
}
// AzureBlobstoreUpload uploads a local file to the Azure Blob Storage. Note, this
// method assumes a max file size of 64MB (Azure limitation). Larger files will
// need a multi API call approach implemented.
//
// See: https://msdn.microsoft.com/en-us/library/azure/dd179451.aspx#Anchor_3
func AzureBlobstoreUpload(path string, name string, config AzureBlobstoreConfig) error {
if *DryRunFlag {
fmt.Printf("would upload %q to %s/%s/%s\n", path, config.Account, config.Container, name)
return nil
}
// Create an authenticated client against the Azure cloud
credential, err := azblob.NewSharedKeyCredential(config.Account, config.Token)
if err != nil {
return err
}
a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account)
client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil)
if err != nil {
return err
}
// Stream the file to upload into the designated blobstore container
in, err := os.Open(path)
if err != nil {
return err
}
defer in.Close()
_, err = client.UploadFile(context.Background(), config.Container, name, in, nil)
return err
}
// AzureBlobstoreList lists all the files contained within an azure blobstore.
func AzureBlobstoreList(config AzureBlobstoreConfig) ([]*container.BlobItem, error) {
// Create an authenticated client against the Azure cloud
credential, err := azblob.NewSharedKeyCredential(config.Account, config.Token)
if err != nil {
return nil, err
}
a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account)
client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil)
if err != nil {
return nil, err
}
pager := client.NewListBlobsFlatPager(config.Container, nil)
var blobs []*container.BlobItem
for pager.More() {
page, err := pager.NextPage(context.TODO())
if err != nil {
return nil, err
}
blobs = append(blobs, page.Segment.BlobItems...)
}
return blobs, nil
}
// AzureBlobstoreDelete iterates over a list of files to delete and removes them
// from the blobstore.
func AzureBlobstoreDelete(config AzureBlobstoreConfig, blobs []*container.BlobItem) error {
if *DryRunFlag {
for _, blob := range blobs {
fmt.Printf("would delete %s (%s) from %s/%s\n", *blob.Name, blob.Properties.LastModified, config.Account, config.Container)
}
return nil
}
// Create an authenticated client against the Azure cloud
credential, err := azblob.NewSharedKeyCredential(config.Account, config.Token)
if err != nil {
return err
}
a := fmt.Sprintf("https://%s.blob.core.windows.net/", config.Account)
client, err := azblob.NewClientWithSharedKeyCredential(a, credential, nil)
if err != nil {
return err
}
// Iterate over the blobs and delete them
for _, blob := range blobs {
if _, err := client.DeleteBlob(context.Background(), config.Container, *blob.Name, nil); err != nil {
return err
}
fmt.Printf("deleted %s (%s)\n", *blob.Name, blob.Properties.LastModified)
}
return nil
}

View file

@ -1,150 +0,0 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package build
import (
"bufio"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"log"
"net/http"
"os"
"path/filepath"
"strings"
)
// ChecksumDB keeps file checksums.
type ChecksumDB struct {
allChecksums []string
}
// MustLoadChecksums loads a file containing checksums.
func MustLoadChecksums(file string) *ChecksumDB {
content, err := os.ReadFile(file)
if err != nil {
log.Fatal("can't load checksum file: " + err.Error())
}
return &ChecksumDB{strings.Split(string(content), "\n")}
}
// Verify checks whether the given file is valid according to the checksum database.
func (db *ChecksumDB) Verify(path string) error {
fd, err := os.Open(path)
if err != nil {
return err
}
defer fd.Close()
h := sha256.New()
if _, err := io.Copy(h, bufio.NewReader(fd)); err != nil {
return err
}
fileHash := hex.EncodeToString(h.Sum(nil))
if !db.findHash(filepath.Base(path), fileHash) {
return fmt.Errorf("invalid file hash %s for %s", fileHash, filepath.Base(path))
}
return nil
}
func (db *ChecksumDB) findHash(basename, hash string) bool {
want := hash + " " + basename
for _, line := range db.allChecksums {
if strings.TrimSpace(line) == want {
return true
}
}
return false
}
// DownloadFile downloads a file and verifies its checksum.
func (db *ChecksumDB) DownloadFile(url, dstPath string) error {
if err := db.Verify(dstPath); err == nil {
fmt.Printf("%s is up-to-date\n", dstPath)
return nil
}
fmt.Printf("%s is stale\n", dstPath)
fmt.Printf("downloading from %s\n", url)
resp, err := http.Get(url)
if err != nil {
return fmt.Errorf("download error: %v", err)
} else if resp.StatusCode != http.StatusOK {
return fmt.Errorf("download error: status %d", resp.StatusCode)
}
defer resp.Body.Close()
if err := os.MkdirAll(filepath.Dir(dstPath), 0755); err != nil {
return err
}
fd, err := os.OpenFile(dstPath, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
if err != nil {
return err
}
dst := newDownloadWriter(fd, resp.ContentLength)
_, err = io.Copy(dst, resp.Body)
dst.Close()
if err != nil {
return err
}
return db.Verify(dstPath)
}
type downloadWriter struct {
file *os.File
dstBuf *bufio.Writer
size int64
written int64
lastpct int64
}
func newDownloadWriter(dst *os.File, size int64) *downloadWriter {
return &downloadWriter{
file: dst,
dstBuf: bufio.NewWriter(dst),
size: size,
}
}
func (w *downloadWriter) Write(buf []byte) (int, error) {
n, err := w.dstBuf.Write(buf)
// Report progress.
w.written += int64(n)
pct := w.written * 10 / w.size * 10
if pct != w.lastpct {
if w.lastpct != 0 {
fmt.Print("...")
}
fmt.Print(pct, "%")
w.lastpct = pct
}
return n, err
}
func (w *downloadWriter) Close() error {
if w.lastpct > 0 {
fmt.Println() // Finish the progress line.
}
flushErr := w.dstBuf.Flush()
closeErr := w.file.Close()
if flushErr != nil {
return flushErr
}
return closeErr
}

View file

@ -1,177 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package build
import (
"flag"
"fmt"
"os"
"regexp"
"strconv"
"strings"
"time"
)
var (
// These flags override values in build env.
GitCommitFlag = flag.String("git-commit", "", `Overrides git commit hash embedded into executables`)
GitBranchFlag = flag.String("git-branch", "", `Overrides git branch being built`)
GitTagFlag = flag.String("git-tag", "", `Overrides git tag being built`)
BuildnumFlag = flag.String("buildnum", "", `Overrides CI build number`)
PullRequestFlag = flag.Bool("pull-request", false, `Overrides pull request status of the build`)
CronJobFlag = flag.Bool("cron-job", false, `Overrides cron job status of the build`)
UbuntuVersionFlag = flag.String("ubuntu", "", `Sets the ubuntu version being built for`)
)
// Environment contains metadata provided by the build environment.
type Environment struct {
CI bool
Name string // name of the environment
Repo string // name of GitHub repo
Commit, Date, Branch, Tag string // Git info
Buildnum string
UbuntuVersion string // Ubuntu version being built for
IsPullRequest bool
IsCronJob bool
}
func (env Environment) String() string {
return fmt.Sprintf("%s env (commit:%s date:%s branch:%s tag:%s buildnum:%s pr:%t)",
env.Name, env.Commit, env.Date, env.Branch, env.Tag, env.Buildnum, env.IsPullRequest)
}
// Env returns metadata about the current CI environment, falling back to LocalEnv
// if not running on CI.
func Env() Environment {
switch {
case os.Getenv("CI") == "true" && os.Getenv("TRAVIS") == "true":
commit := os.Getenv("TRAVIS_PULL_REQUEST_SHA")
if commit == "" {
commit = os.Getenv("TRAVIS_COMMIT")
}
return Environment{
CI: true,
Name: "travis",
Repo: os.Getenv("TRAVIS_REPO_SLUG"),
Commit: commit,
Date: getDate(commit),
Branch: os.Getenv("TRAVIS_BRANCH"),
Tag: os.Getenv("TRAVIS_TAG"),
Buildnum: os.Getenv("TRAVIS_BUILD_NUMBER"),
IsPullRequest: os.Getenv("TRAVIS_PULL_REQUEST") != "false",
IsCronJob: os.Getenv("TRAVIS_EVENT_TYPE") == "cron",
}
case os.Getenv("CI") == "True" && os.Getenv("APPVEYOR") == "True":
commit := os.Getenv("APPVEYOR_PULL_REQUEST_HEAD_COMMIT")
if commit == "" {
commit = os.Getenv("APPVEYOR_REPO_COMMIT")
}
return Environment{
CI: true,
Name: "appveyor",
Repo: os.Getenv("APPVEYOR_REPO_NAME"),
Commit: commit,
Date: getDate(commit),
Branch: os.Getenv("APPVEYOR_REPO_BRANCH"),
Tag: os.Getenv("APPVEYOR_REPO_TAG_NAME"),
Buildnum: os.Getenv("APPVEYOR_BUILD_NUMBER"),
IsPullRequest: os.Getenv("APPVEYOR_PULL_REQUEST_NUMBER") != "",
IsCronJob: os.Getenv("APPVEYOR_SCHEDULED_BUILD") == "True",
}
default:
return LocalEnv()
}
}
// LocalEnv returns build environment metadata gathered from git.
func LocalEnv() Environment {
env := applyEnvFlags(Environment{Name: "local", Repo: "ethereum/go-ethereum"})
head := readGitFile("HEAD")
if fields := strings.Fields(head); len(fields) == 2 {
head = fields[1]
} else {
// In this case we are in "detached head" state
// see: https://git-scm.com/docs/git-checkout#_detached_head
// Additional check required to verify, that file contains commit hash
commitRe, _ := regexp.Compile("^([0-9a-f]{40})$")
if commit := commitRe.FindString(head); commit != "" && env.Commit == "" {
env.Commit = commit
}
return env
}
if env.Commit == "" {
env.Commit = readGitFile(head)
}
env.Date = getDate(env.Commit)
if env.Branch == "" {
if head != "HEAD" {
env.Branch = strings.TrimPrefix(head, "refs/heads/")
}
}
if info, err := os.Stat(".git/objects"); err == nil && info.IsDir() && env.Tag == "" {
env.Tag = firstLine(RunGit("tag", "-l", "--points-at", "HEAD"))
}
return env
}
func firstLine(s string) string {
return strings.Split(s, "\n")[0]
}
func getDate(commit string) string {
if commit == "" {
return ""
}
out := RunGit("show", "-s", "--format=%ct", commit)
if out == "" {
return ""
}
date, err := strconv.ParseInt(strings.TrimSpace(out), 10, 64)
if err != nil {
panic(fmt.Sprintf("failed to parse git commit date: %v", err))
}
return time.Unix(date, 0).Format("20060102")
}
func applyEnvFlags(env Environment) Environment {
if !flag.Parsed() {
panic("you need to call flag.Parse before Env or LocalEnv")
}
if *GitCommitFlag != "" {
env.Commit = *GitCommitFlag
}
if *GitBranchFlag != "" {
env.Branch = *GitBranchFlag
}
if *GitTagFlag != "" {
env.Tag = *GitTagFlag
}
if *BuildnumFlag != "" {
env.Buildnum = *BuildnumFlag
}
if *PullRequestFlag {
env.IsPullRequest = true
}
if *CronJobFlag {
env.IsCronJob = true
}
if *UbuntuVersionFlag != "" {
env.UbuntuVersion = *UbuntuVersionFlag
}
return env
}

View file

@ -1,180 +0,0 @@
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package build
import (
"fmt"
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
)
type GoToolchain struct {
Root string // GOROOT
// Cross-compilation variables. These are set when running the go tool.
GOARCH string
GOOS string
CC string
}
// Go creates an invocation of the go command.
func (g *GoToolchain) Go(command string, args ...string) *exec.Cmd {
tool := g.goTool(command, args...)
// Configure environment for cross build.
if g.GOARCH != "" && g.GOARCH != runtime.GOARCH {
tool.Env = append(tool.Env, "CGO_ENABLED=1")
tool.Env = append(tool.Env, "GOARCH="+g.GOARCH)
}
if g.GOOS != "" && g.GOOS != runtime.GOOS {
tool.Env = append(tool.Env, "GOOS="+g.GOOS)
}
// Configure C compiler.
if g.CC != "" {
tool.Env = append(tool.Env, "CC="+g.CC)
} else if os.Getenv("CC") != "" {
tool.Env = append(tool.Env, "CC="+os.Getenv("CC"))
}
// CKZG by default is not portable, append the necessary build flags to make
// it not rely on modern CPU instructions and enable linking against.
tool.Env = append(tool.Env, "CGO_CFLAGS=-O2 -g -D__BLST_PORTABLE__")
return tool
}
func (g *GoToolchain) goTool(command string, args ...string) *exec.Cmd {
if g.Root == "" {
g.Root = runtime.GOROOT()
}
tool := exec.Command(filepath.Join(g.Root, "bin", "go"), command) // nolint: gosec
tool.Args = append(tool.Args, args...)
tool.Env = append(tool.Env, "GOROOT="+g.Root)
// Forward environment variables to the tool, but skip compiler target settings.
// TODO: what about GOARM?
skip := map[string]struct{}{"GOROOT": {}, "GOARCH": {}, "GOOS": {}, "GOBIN": {}, "CC": {}}
for _, e := range os.Environ() {
if i := strings.IndexByte(e, '='); i >= 0 {
if _, ok := skip[e[:i]]; ok {
continue
}
}
tool.Env = append(tool.Env, e)
}
return tool
}
// DownloadGo downloads the Go binary distribution and unpacks it into a temporary
// directory. It returns the GOROOT of the unpacked toolchain.
func DownloadGo(csdb *ChecksumDB) string {
version, err := Version(csdb, "golang")
if err != nil {
log.Fatal(err)
}
// Shortcut: if the Go version that runs this script matches the
// requested version exactly, there is no need to download anything.
activeGo := strings.TrimPrefix(runtime.Version(), "go")
if activeGo == version {
log.Printf("-dlgo version matches active Go version %s, skipping download.", activeGo)
return runtime.GOROOT()
}
ucache, err := os.UserCacheDir()
if err != nil {
log.Fatal(err)
}
// For Arm architecture, GOARCH includes ISA version.
os := runtime.GOOS
arch := runtime.GOARCH
if arch == "arm" {
arch = "armv6l"
}
file := fmt.Sprintf("go%s.%s-%s", version, os, arch)
if os == "windows" {
file += ".zip"
} else {
file += ".tar.gz"
}
url := "https://golang.org/dl/" + file
dst := filepath.Join(ucache, file)
if err := csdb.DownloadFile(url, dst); err != nil {
log.Fatal(err)
}
godir := filepath.Join(ucache, fmt.Sprintf("geth-go-%s-%s-%s", version, os, arch))
if err := ExtractArchive(dst, godir); err != nil {
log.Fatal(err)
}
goroot, err := filepath.Abs(filepath.Join(godir, "go"))
if err != nil {
log.Fatal(err)
}
return goroot
}
// Version returns the versions defined in the checksumdb.
func Version(csdb *ChecksumDB, version string) (string, error) {
for _, l := range csdb.allChecksums {
if !strings.HasPrefix(l, "# version:") {
continue
}
v := strings.Split(l, ":")[1]
parts := strings.Split(v, " ")
if len(parts) != 2 {
log.Print("Erroneous version-string", "v", l)
continue
}
if parts[0] == version {
return parts[1], nil
}
}
return "", fmt.Errorf("no version found for '%v'", version)
}
// DownloadAndVerifyChecksums downloads all files and checks that they match
// the checksum given in checksums.txt.
// This task can be used to sanity-check new checksums.
func DownloadAndVerifyChecksums(csdb *ChecksumDB) {
var (
base = ""
ucache = os.TempDir()
)
for _, l := range csdb.allChecksums {
if strings.HasPrefix(l, "# https://") {
base = l[2:]
continue
}
if strings.HasPrefix(l, "#") {
continue
}
hashFile := strings.Split(l, " ")
if len(hashFile) != 2 {
continue
}
file := hashFile[1]
url := base + file
dst := filepath.Join(ucache, file)
if err := csdb.DownloadFile(url, dst); err != nil {
log.Print(err)
}
}
}

View file

@ -1,71 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// signFile reads the contents of an input file and signs it (in armored format)
// with the key provided, placing the signature into the output file.
package build
import (
"bytes"
"fmt"
"os"
"golang.org/x/crypto/openpgp"
)
// PGPSignFile parses a PGP private key from the specified string and creates a
// signature file into the output parameter of the input file.
//
// Note, this method assumes a single key will be container in the pgpkey arg,
// furthermore that it is in armored format.
func PGPSignFile(input string, output string, pgpkey string) error {
// Parse the keyring and make sure we only have a single private key in it
keys, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(pgpkey))
if err != nil {
return err
}
if len(keys) != 1 {
return fmt.Errorf("key count mismatch: have %d, want %d", len(keys), 1)
}
// Create the input and output streams for signing
in, err := os.Open(input)
if err != nil {
return err
}
defer in.Close()
out, err := os.Create(output)
if err != nil {
return err
}
defer out.Close()
// Generate the signature and return
return openpgp.ArmoredDetachSign(out, keys[0], in, nil)
}
// PGPKeyID parses an armored key and returns the key ID.
func PGPKeyID(pgpkey string) (string, error) {
keys, err := openpgp.ReadArmoredKeyRing(bytes.NewBufferString(pgpkey))
if err != nil {
return "", err
}
if len(keys) != 1 {
return "", fmt.Errorf("key count mismatch: have %d, want %d", len(keys), 1)
}
return keys[0].PrimaryKey.KeyIdString(), nil
}

View file

@ -1,237 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package build
import (
"bufio"
"bytes"
"flag"
"fmt"
"go/parser"
"go/token"
"io"
"log"
"os"
"os/exec"
"path"
"path/filepath"
"strconv"
"strings"
"text/template"
"time"
)
var DryRunFlag = flag.Bool("n", false, "dry run, don't execute commands")
// MustRun executes the given command and exits the host process for
// any error.
func MustRun(cmd *exec.Cmd) {
fmt.Println(">>>", printArgs(cmd.Args))
if !*DryRunFlag {
cmd.Stderr = os.Stderr
cmd.Stdout = os.Stdout
if err := cmd.Run(); err != nil {
log.Fatal(err)
}
}
}
func printArgs(args []string) string {
var s strings.Builder
for i, arg := range args {
if i > 0 {
s.WriteByte(' ')
}
if strings.IndexByte(arg, ' ') >= 0 {
arg = strconv.QuoteToASCII(arg)
}
s.WriteString(arg)
}
return s.String()
}
func MustRunCommand(cmd string, args ...string) {
MustRun(exec.Command(cmd, args...))
}
// MustRunCommandWithOutput runs the given command, and ensures that some output will be
// printed while it runs. This is useful for CI builds where the process will be stopped
// when there is no output.
func MustRunCommandWithOutput(cmd string, args ...string) {
interval := time.NewTicker(time.Minute)
done := make(chan struct{})
defer interval.Stop()
defer close(done)
go func() {
for {
select {
case <-interval.C:
fmt.Printf("Waiting for command %q\n", cmd)
case <-done:
return
}
}
}()
MustRun(exec.Command(cmd, args...))
}
var warnedAboutGit bool
// RunGit runs a git subcommand and returns its output.
// The command must complete successfully.
func RunGit(args ...string) string {
cmd := exec.Command("git", args...)
var stdout, stderr bytes.Buffer
cmd.Stdout, cmd.Stderr = &stdout, &stderr
if err := cmd.Run(); err != nil {
if e, ok := err.(*exec.Error); ok && e.Err == exec.ErrNotFound {
if !warnedAboutGit {
log.Println("Warning: can't find 'git' in PATH")
warnedAboutGit = true
}
return ""
}
log.Fatal(strings.Join(cmd.Args, " "), ": ", err, "\n", stderr.String())
}
return strings.TrimSpace(stdout.String())
}
// readGitFile returns content of file in .git directory.
func readGitFile(file string) string {
content, err := os.ReadFile(path.Join(".git", file))
if err != nil {
return ""
}
return strings.TrimSpace(string(content))
}
// Render renders the given template file into outputFile.
func Render(templateFile, outputFile string, outputPerm os.FileMode, x interface{}) {
tpl := template.Must(template.ParseFiles(templateFile))
render(tpl, outputFile, outputPerm, x)
}
// RenderString renders the given template string into outputFile.
func RenderString(templateContent, outputFile string, outputPerm os.FileMode, x interface{}) {
tpl := template.Must(template.New("").Parse(templateContent))
render(tpl, outputFile, outputPerm, x)
}
func render(tpl *template.Template, outputFile string, outputPerm os.FileMode, x interface{}) {
if err := os.MkdirAll(filepath.Dir(outputFile), 0755); err != nil {
log.Fatal(err)
}
out, err := os.OpenFile(outputFile, os.O_CREATE|os.O_WRONLY|os.O_EXCL, outputPerm)
if err != nil {
log.Fatal(err)
}
if err := tpl.Execute(out, x); err != nil {
log.Fatal(err)
}
if err := out.Close(); err != nil {
log.Fatal(err)
}
}
// UploadSFTP uploads files to a remote host using the sftp command line tool.
// The destination host may be specified either as [user@]host: or as a URI in
// the form sftp://[user@]host[:port].
func UploadSFTP(identityFile, host, dir string, files []string) error {
sftp := exec.Command("sftp")
sftp.Stderr = os.Stderr
if identityFile != "" {
sftp.Args = append(sftp.Args, "-i", identityFile)
}
sftp.Args = append(sftp.Args, host)
fmt.Println(">>>", printArgs(sftp.Args))
if *DryRunFlag {
return nil
}
stdin, err := sftp.StdinPipe()
if err != nil {
return fmt.Errorf("can't create stdin pipe for sftp: %v", err)
}
stdout, err := sftp.StdoutPipe()
if err != nil {
return fmt.Errorf("can't create stdout pipe for sftp: %v", err)
}
if err := sftp.Start(); err != nil {
return err
}
in := io.MultiWriter(stdin, os.Stdout)
for _, f := range files {
fmt.Fprintln(in, "put", f, path.Join(dir, filepath.Base(f)))
}
fmt.Fprintln(in, "exit")
// Some issue with the PPA sftp server makes it so the server does not
// respond properly to a 'bye', 'exit' or 'quit' from the client.
// To work around that, we check the output, and when we see the client
// exit command, we do a hard exit.
// See
// https://github.com/kolban-google/sftp-gcs/issues/23
// https://github.com/mscdex/ssh2/pull/1111
aborted := false
go func() {
scanner := bufio.NewScanner(stdout)
for scanner.Scan() {
txt := scanner.Text()
fmt.Println(txt)
if txt == "sftp> exit" {
// Give it .5 seconds to exit (server might be fixed), then
// hard kill it from the outside
time.Sleep(500 * time.Millisecond)
aborted = true
sftp.Process.Kill()
}
}
}()
stdin.Close()
err = sftp.Wait()
if aborted {
return nil
}
return err
}
// FindMainPackages finds all 'main' packages in the given directory and returns their
// package paths.
func FindMainPackages(dir string) []string {
var commands []string
cmds, err := os.ReadDir(dir)
if err != nil {
log.Fatal(err)
}
for _, cmd := range cmds {
pkgdir := filepath.Join(dir, cmd.Name())
if !cmd.IsDir() {
continue
}
pkgs, err := parser.ParseDir(token.NewFileSet(), pkgdir, nil, parser.PackageClauseOnly)
if err != nil {
log.Fatal(err)
}
for name := range pkgs {
if name == "main" {
path := "./" + filepath.ToSlash(pkgdir)
commands = append(commands, path)
break
}
}
}
return commands
}

View file

@ -1,300 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package cmdtest
import (
"bufio"
"bytes"
"fmt"
"io"
"os"
"os/exec"
"regexp"
"strings"
"sync"
"sync/atomic"
"syscall"
"testing"
"text/template"
"time"
"github.com/ethereum/go-ethereum/internal/reexec"
)
func NewTestCmd(t *testing.T, data interface{}) *TestCmd {
return &TestCmd{T: t, Data: data}
}
type TestCmd struct {
// For total convenience, all testing methods are available.
*testing.T
Func template.FuncMap
Data interface{}
Cleanup func()
cmd *exec.Cmd
stdout *bufio.Reader
stdin io.WriteCloser
stderr *testlogger
// Err will contain the process exit error or interrupt signal error
Err error
}
var id atomic.Int32
// Run exec's the current binary using name as argv[0] which will trigger the
// reexec init function for that name (e.g. "geth-test" in cmd/geth/run_test.go)
func (tt *TestCmd) Run(name string, args ...string) {
id.Add(1)
tt.stderr = &testlogger{t: tt.T, name: fmt.Sprintf("%d", id.Load())}
tt.cmd = &exec.Cmd{
Path: reexec.Self(),
Args: append([]string{name}, args...),
Stderr: tt.stderr,
}
stdout, err := tt.cmd.StdoutPipe()
if err != nil {
tt.Fatal(err)
}
tt.stdout = bufio.NewReader(stdout)
if tt.stdin, err = tt.cmd.StdinPipe(); err != nil {
tt.Fatal(err)
}
if err := tt.cmd.Start(); err != nil {
tt.Fatal(err)
}
}
// InputLine writes the given text to the child's stdin.
// This method can also be called from an expect template, e.g.:
//
// geth.expect(`Passphrase: {{.InputLine "password"}}`)
func (tt *TestCmd) InputLine(s string) string {
io.WriteString(tt.stdin, s+"\n")
return ""
}
func (tt *TestCmd) SetTemplateFunc(name string, fn interface{}) {
if tt.Func == nil {
tt.Func = make(map[string]interface{})
}
tt.Func[name] = fn
}
// Expect runs its argument as a template, then expects the
// child process to output the result of the template within 5s.
//
// If the template starts with a newline, the newline is removed
// before matching.
func (tt *TestCmd) Expect(tplsource string) {
// Generate the expected output by running the template.
tpl := template.Must(template.New("").Funcs(tt.Func).Parse(tplsource))
wantbuf := new(bytes.Buffer)
if err := tpl.Execute(wantbuf, tt.Data); err != nil {
panic(err)
}
// Trim exactly one newline at the beginning. This makes tests look
// much nicer because all expect strings are at column 0.
want := bytes.TrimPrefix(wantbuf.Bytes(), []byte("\n"))
if err := tt.matchExactOutput(want); err != nil {
tt.Fatal(err)
}
tt.Logf("Matched stdout text:\n%s", want)
}
// Output reads all output from stdout, and returns the data.
func (tt *TestCmd) Output() []byte {
var buf []byte
tt.withKillTimeout(func() { buf, _ = io.ReadAll(tt.stdout) })
return buf
}
func (tt *TestCmd) matchExactOutput(want []byte) error {
buf := make([]byte, len(want))
n := 0
tt.withKillTimeout(func() { n, _ = io.ReadFull(tt.stdout, buf) })
buf = buf[:n]
if n < len(want) || !bytes.Equal(buf, want) {
// Grab any additional buffered output in case of mismatch
// because it might help with debugging.
buf = append(buf, make([]byte, tt.stdout.Buffered())...)
tt.stdout.Read(buf[n:])
// Find the mismatch position.
for i := 0; i < n; i++ {
if want[i] != buf[i] {
return fmt.Errorf("output mismatch at ◊:\n---------------- (stdout text)\n%s◊%s\n---------------- (expected text)\n%s",
buf[:i], buf[i:n], want)
}
}
if n < len(want) {
return fmt.Errorf("not enough output, got until ◊:\n---------------- (stdout text)\n%s\n---------------- (expected text)\n%s◊%s",
buf, want[:n], want[n:])
}
}
return nil
}
// ExpectRegexp expects the child process to output text matching the
// given regular expression within 5s.
//
// Note that an arbitrary amount of output may be consumed by the
// regular expression. This usually means that expect cannot be used
// after ExpectRegexp.
func (tt *TestCmd) ExpectRegexp(regex string) (*regexp.Regexp, []string) {
regex = strings.TrimPrefix(regex, "\n")
var (
re = regexp.MustCompile(regex)
rtee = &runeTee{in: tt.stdout}
matches []int
)
tt.withKillTimeout(func() { matches = re.FindReaderSubmatchIndex(rtee) })
output := rtee.buf.Bytes()
if matches == nil {
tt.Fatalf("Output did not match:\n---------------- (stdout text)\n%s\n---------------- (regular expression)\n%s",
output, regex)
return re, nil
}
tt.Logf("Matched stdout text:\n%s", output)
var submatches []string
for i := 0; i < len(matches); i += 2 {
submatch := string(output[matches[i]:matches[i+1]])
submatches = append(submatches, submatch)
}
return re, submatches
}
// ExpectExit expects the child process to exit within 5s without
// printing any additional text on stdout.
func (tt *TestCmd) ExpectExit() {
var output []byte
tt.withKillTimeout(func() {
output, _ = io.ReadAll(tt.stdout)
})
tt.WaitExit()
if tt.Cleanup != nil {
tt.Cleanup()
}
if len(output) > 0 {
tt.Errorf("Unmatched stdout text:\n%s", output)
}
}
func (tt *TestCmd) WaitExit() {
tt.Err = tt.cmd.Wait()
}
func (tt *TestCmd) Interrupt() {
tt.Err = tt.cmd.Process.Signal(os.Interrupt)
}
// ExitStatus exposes the process' OS exit code
// It will only return a valid value after the process has finished.
func (tt *TestCmd) ExitStatus() int {
if tt.Err != nil {
exitErr := tt.Err.(*exec.ExitError)
if exitErr != nil {
if status, ok := exitErr.Sys().(syscall.WaitStatus); ok {
return status.ExitStatus()
}
}
}
return 0
}
// StderrText returns any stderr output written so far.
// The returned text holds all log lines after ExpectExit has
// returned.
func (tt *TestCmd) StderrText() string {
tt.stderr.mu.Lock()
defer tt.stderr.mu.Unlock()
return tt.stderr.buf.String()
}
func (tt *TestCmd) CloseStdin() {
tt.stdin.Close()
}
func (tt *TestCmd) Kill() {
tt.cmd.Process.Kill()
if tt.Cleanup != nil {
tt.Cleanup()
}
}
func (tt *TestCmd) withKillTimeout(fn func()) {
timeout := time.AfterFunc(30*time.Second, func() {
tt.Log("killing the child process (timeout)")
tt.Kill()
})
defer timeout.Stop()
fn()
}
// testlogger logs all written lines via t.Log and also
// collects them for later inspection.
type testlogger struct {
t *testing.T
mu sync.Mutex
buf bytes.Buffer
name string
}
func (tl *testlogger) Write(b []byte) (n int, err error) {
lines := bytes.Split(b, []byte("\n"))
for _, line := range lines {
if len(line) > 0 {
tl.t.Logf("(stderr:%v) %s", tl.name, line)
}
}
tl.mu.Lock()
tl.buf.Write(b)
tl.mu.Unlock()
return len(b), err
}
// runeTee collects text read through it into buf.
type runeTee struct {
in interface {
io.Reader
io.ByteReader
io.RuneReader
}
buf bytes.Buffer
}
func (rtee *runeTee) Read(b []byte) (n int, err error) {
n, err = rtee.in.Read(b)
rtee.buf.Write(b[:n])
return n, err
}
func (rtee *runeTee) ReadRune() (r rune, size int, err error) {
r, size, err = rtee.in.ReadRune()
if err == nil {
rtee.buf.WriteRune(r)
}
return r, size, err
}
func (rtee *runeTee) ReadByte() (b byte, err error) {
b, err = rtee.in.ReadByte()
if err == nil {
rtee.buf.WriteByte(b)
}
return b, err
}

View file

@ -1,267 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package debug interfaces Go runtime debugging facilities.
// This package is mostly glue code making these facilities available
// through the CLI and RPC subsystem. If you want to use them from Go code,
// use package runtime instead.
package debug
import (
"bytes"
"errors"
"io"
"os"
"os/user"
"path/filepath"
"regexp"
"runtime"
"runtime/debug"
"runtime/pprof"
"strings"
"sync"
"time"
"github.com/ethereum/go-ethereum/log"
"github.com/hashicorp/go-bexpr"
"golang.org/x/exp/slog"
)
// Handler is the global debugging handler.
var Handler = new(HandlerT)
// HandlerT implements the debugging API.
// Do not create values of this type, use the one
// in the Handler variable instead.
type HandlerT struct {
mu sync.Mutex
cpuW io.WriteCloser
cpuFile string
traceW io.WriteCloser
traceFile string
}
// Verbosity sets the log verbosity ceiling. The verbosity of individual packages
// and source files can be raised using Vmodule.
func (*HandlerT) Verbosity(level int) {
glogger.Verbosity(slog.Level(level))
}
// Vmodule sets the log verbosity pattern. See package log for details on the
// pattern syntax.
func (*HandlerT) Vmodule(pattern string) error {
return glogger.Vmodule(pattern)
}
// MemStats returns detailed runtime memory statistics.
func (*HandlerT) MemStats() *runtime.MemStats {
s := new(runtime.MemStats)
runtime.ReadMemStats(s)
return s
}
// GcStats returns GC statistics.
func (*HandlerT) GcStats() *debug.GCStats {
s := new(debug.GCStats)
debug.ReadGCStats(s)
return s
}
// CpuProfile turns on CPU profiling for nsec seconds and writes
// profile data to file.
func (h *HandlerT) CpuProfile(file string, nsec uint) error {
if err := h.StartCPUProfile(file); err != nil {
return err
}
time.Sleep(time.Duration(nsec) * time.Second)
h.StopCPUProfile()
return nil
}
// StartCPUProfile turns on CPU profiling, writing to the given file.
func (h *HandlerT) StartCPUProfile(file string) error {
h.mu.Lock()
defer h.mu.Unlock()
if h.cpuW != nil {
return errors.New("CPU profiling already in progress")
}
f, err := os.Create(expandHome(file))
if err != nil {
return err
}
if err := pprof.StartCPUProfile(f); err != nil {
f.Close()
return err
}
h.cpuW = f
h.cpuFile = file
log.Info("CPU profiling started", "dump", h.cpuFile)
return nil
}
// StopCPUProfile stops an ongoing CPU profile.
func (h *HandlerT) StopCPUProfile() error {
h.mu.Lock()
defer h.mu.Unlock()
pprof.StopCPUProfile()
if h.cpuW == nil {
return errors.New("CPU profiling not in progress")
}
log.Info("Done writing CPU profile", "dump", h.cpuFile)
h.cpuW.Close()
h.cpuW = nil
h.cpuFile = ""
return nil
}
// GoTrace turns on tracing for nsec seconds and writes
// trace data to file.
func (h *HandlerT) GoTrace(file string, nsec uint) error {
if err := h.StartGoTrace(file); err != nil {
return err
}
time.Sleep(time.Duration(nsec) * time.Second)
h.StopGoTrace()
return nil
}
// BlockProfile turns on goroutine profiling for nsec seconds and writes profile data to
// file. It uses a profile rate of 1 for most accurate information. If a different rate is
// desired, set the rate and write the profile manually.
func (*HandlerT) BlockProfile(file string, nsec uint) error {
runtime.SetBlockProfileRate(1)
time.Sleep(time.Duration(nsec) * time.Second)
defer runtime.SetBlockProfileRate(0)
return writeProfile("block", file)
}
// SetBlockProfileRate sets the rate of goroutine block profile data collection.
// rate 0 disables block profiling.
func (*HandlerT) SetBlockProfileRate(rate int) {
runtime.SetBlockProfileRate(rate)
}
// WriteBlockProfile writes a goroutine blocking profile to the given file.
func (*HandlerT) WriteBlockProfile(file string) error {
return writeProfile("block", file)
}
// MutexProfile turns on mutex profiling for nsec seconds and writes profile data to file.
// It uses a profile rate of 1 for most accurate information. If a different rate is
// desired, set the rate and write the profile manually.
func (*HandlerT) MutexProfile(file string, nsec uint) error {
runtime.SetMutexProfileFraction(1)
time.Sleep(time.Duration(nsec) * time.Second)
defer runtime.SetMutexProfileFraction(0)
return writeProfile("mutex", file)
}
// SetMutexProfileFraction sets the rate of mutex profiling.
func (*HandlerT) SetMutexProfileFraction(rate int) {
runtime.SetMutexProfileFraction(rate)
}
// WriteMutexProfile writes a goroutine blocking profile to the given file.
func (*HandlerT) WriteMutexProfile(file string) error {
return writeProfile("mutex", file)
}
// WriteMemProfile writes an allocation profile to the given file.
// Note that the profiling rate cannot be set through the API,
// it must be set on the command line.
func (*HandlerT) WriteMemProfile(file string) error {
return writeProfile("heap", file)
}
// Stacks returns a printed representation of the stacks of all goroutines. It
// also permits the following optional filters to be used:
// - filter: boolean expression of packages to filter for
func (*HandlerT) Stacks(filter *string) string {
buf := new(bytes.Buffer)
pprof.Lookup("goroutine").WriteTo(buf, 2)
// If any filtering was requested, execute them now
if filter != nil && len(*filter) > 0 {
expanded := *filter
// The input filter is a logical expression of package names. Transform
// it into a proper boolean expression that can be fed into a parser and
// interpreter:
//
// E.g. (eth || snap) && !p2p -> (eth in Value || snap in Value) && p2p not in Value
expanded = regexp.MustCompile(`[:/\.A-Za-z0-9_-]+`).ReplaceAllString(expanded, "`$0` in Value")
expanded = regexp.MustCompile("!(`[:/\\.A-Za-z0-9_-]+`)").ReplaceAllString(expanded, "$1 not")
expanded = strings.ReplaceAll(expanded, "||", "or")
expanded = strings.ReplaceAll(expanded, "&&", "and")
log.Info("Expanded filter expression", "filter", *filter, "expanded", expanded)
expr, err := bexpr.CreateEvaluator(expanded)
if err != nil {
log.Error("Failed to parse filter expression", "expanded", expanded, "err", err)
return ""
}
// Split the goroutine dump into segments and filter each
dump := buf.String()
buf.Reset()
for _, trace := range strings.Split(dump, "\n\n") {
if ok, _ := expr.Evaluate(map[string]string{"Value": trace}); ok {
buf.WriteString(trace)
buf.WriteString("\n\n")
}
}
}
return buf.String()
}
// FreeOSMemory forces a garbage collection.
func (*HandlerT) FreeOSMemory() {
debug.FreeOSMemory()
}
// SetGCPercent sets the garbage collection target percentage. It returns the previous
// setting. A negative value disables GC.
func (*HandlerT) SetGCPercent(v int) int {
return debug.SetGCPercent(v)
}
func writeProfile(name, file string) error {
p := pprof.Lookup(name)
log.Info("Writing profile records", "count", p.Count(), "type", name, "dump", file)
f, err := os.Create(expandHome(file))
if err != nil {
return err
}
defer f.Close()
return p.WriteTo(f, 0)
}
// expands home directory in file paths.
// ~someuser/tmp will not be expanded.
func expandHome(p string) string {
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
home := os.Getenv("HOME")
if home == "" {
if usr, err := user.Current(); err == nil {
home = usr.HomeDir
}
}
if home != "" {
p = home + p[1:]
}
}
return filepath.Clean(p)
}

View file

@ -1,357 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package debug
import (
"fmt"
"io"
"net"
"net/http"
_ "net/http/pprof"
"os"
"path/filepath"
"runtime"
"github.com/ethereum/go-ethereum/internal/flags"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/metrics/exp"
"github.com/fjl/memsize/memsizeui"
"github.com/mattn/go-colorable"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
"golang.org/x/exp/slog"
"gopkg.in/natefinch/lumberjack.v2"
)
var Memsize memsizeui.Handler
var (
verbosityFlag = &cli.IntFlag{
Name: "verbosity",
Usage: "Logging verbosity: 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail",
Value: 3,
Category: flags.LoggingCategory,
}
logVmoduleFlag = &cli.StringFlag{
Name: "log.vmodule",
Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)",
Value: "",
Category: flags.LoggingCategory,
}
vmoduleFlag = &cli.StringFlag{
Name: "vmodule",
Usage: "Per-module verbosity: comma-separated list of <pattern>=<level> (e.g. eth/*=5,p2p=4)",
Value: "",
Hidden: true,
Category: flags.LoggingCategory,
}
logjsonFlag = &cli.BoolFlag{
Name: "log.json",
Usage: "Format logs with JSON",
Hidden: true,
Category: flags.LoggingCategory,
}
logFormatFlag = &cli.StringFlag{
Name: "log.format",
Usage: "Log format to use (json|logfmt|terminal)",
Category: flags.LoggingCategory,
}
logFileFlag = &cli.StringFlag{
Name: "log.file",
Usage: "Write logs to a file",
Category: flags.LoggingCategory,
}
logRotateFlag = &cli.BoolFlag{
Name: "log.rotate",
Usage: "Enables log file rotation",
Category: flags.LoggingCategory,
}
logMaxSizeMBsFlag = &cli.IntFlag{
Name: "log.maxsize",
Usage: "Maximum size in MBs of a single log file",
Value: 100,
Category: flags.LoggingCategory,
}
logMaxBackupsFlag = &cli.IntFlag{
Name: "log.maxbackups",
Usage: "Maximum number of log files to retain",
Value: 10,
Category: flags.LoggingCategory,
}
logMaxAgeFlag = &cli.IntFlag{
Name: "log.maxage",
Usage: "Maximum number of days to retain a log file",
Value: 30,
Category: flags.LoggingCategory,
}
logCompressFlag = &cli.BoolFlag{
Name: "log.compress",
Usage: "Compress the log files",
Value: false,
Category: flags.LoggingCategory,
}
pprofFlag = &cli.BoolFlag{
Name: "pprof",
Usage: "Enable the pprof HTTP server",
Category: flags.LoggingCategory,
}
pprofPortFlag = &cli.IntFlag{
Name: "pprof.port",
Usage: "pprof HTTP server listening port",
Value: 6060,
Category: flags.LoggingCategory,
}
pprofAddrFlag = &cli.StringFlag{
Name: "pprof.addr",
Usage: "pprof HTTP server listening interface",
Value: "127.0.0.1",
Category: flags.LoggingCategory,
}
memprofilerateFlag = &cli.IntFlag{
Name: "pprof.memprofilerate",
Usage: "Turn on memory profiling with the given rate",
Value: runtime.MemProfileRate,
Category: flags.LoggingCategory,
}
blockprofilerateFlag = &cli.IntFlag{
Name: "pprof.blockprofilerate",
Usage: "Turn on block profiling with the given rate",
Category: flags.LoggingCategory,
}
cpuprofileFlag = &cli.StringFlag{
Name: "pprof.cpuprofile",
Usage: "Write CPU profile to the given file",
Category: flags.LoggingCategory,
}
traceFlag = &cli.StringFlag{
Name: "trace",
Usage: "Write execution trace to the given file",
Category: flags.LoggingCategory,
}
)
// Flags holds all command-line flags required for debugging.
var Flags = []cli.Flag{
verbosityFlag,
logVmoduleFlag,
vmoduleFlag,
logjsonFlag,
logFormatFlag,
logFileFlag,
logRotateFlag,
logMaxSizeMBsFlag,
logMaxBackupsFlag,
logMaxAgeFlag,
logCompressFlag,
pprofFlag,
pprofAddrFlag,
pprofPortFlag,
memprofilerateFlag,
blockprofilerateFlag,
cpuprofileFlag,
traceFlag,
}
var (
glogger *log.GlogHandler
logOutputFile io.WriteCloser
defaultTerminalHandler *log.TerminalHandler
)
func init() {
defaultTerminalHandler = log.NewTerminalHandler(os.Stderr, false)
glogger = log.NewGlogHandler(defaultTerminalHandler)
glogger.Verbosity(log.LvlInfo)
log.SetDefault(log.NewLogger(glogger))
}
func ResetLogging() {
if defaultTerminalHandler != nil {
defaultTerminalHandler.ResetFieldPadding()
}
}
// Setup initializes profiling and logging based on the CLI flags.
// It should be called as early as possible in the program.
func Setup(ctx *cli.Context) error {
var (
handler slog.Handler
terminalOutput = io.Writer(os.Stderr)
output io.Writer
logFmtFlag = ctx.String(logFormatFlag.Name)
)
var (
logFile = ctx.String(logFileFlag.Name)
rotation = ctx.Bool(logRotateFlag.Name)
)
if len(logFile) > 0 {
if err := validateLogLocation(filepath.Dir(logFile)); err != nil {
return fmt.Errorf("failed to initiatilize file logger: %v", err)
}
}
context := []interface{}{"rotate", rotation}
if len(logFmtFlag) > 0 {
context = append(context, "format", logFmtFlag)
} else {
context = append(context, "format", "terminal")
}
if rotation {
// Lumberjack uses <processname>-lumberjack.log in is.TempDir() if empty.
// so typically /tmp/geth-lumberjack.log on linux
if len(logFile) > 0 {
context = append(context, "location", logFile)
} else {
context = append(context, "location", filepath.Join(os.TempDir(), "geth-lumberjack.log"))
}
logOutputFile = &lumberjack.Logger{
Filename: logFile,
MaxSize: ctx.Int(logMaxSizeMBsFlag.Name),
MaxBackups: ctx.Int(logMaxBackupsFlag.Name),
MaxAge: ctx.Int(logMaxAgeFlag.Name),
Compress: ctx.Bool(logCompressFlag.Name),
}
output = io.MultiWriter(terminalOutput, logOutputFile)
} else if logFile != "" {
var err error
if logOutputFile, err = os.OpenFile(logFile, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644); err != nil {
return err
}
output = io.MultiWriter(logOutputFile, terminalOutput)
context = append(context, "location", logFile)
} else {
output = terminalOutput
}
switch {
case ctx.Bool(logjsonFlag.Name):
// Retain backwards compatibility with `--log.json` flag if `--log.format` not set
defer log.Warn("The flag '--log.json' is deprecated, please use '--log.format=json' instead")
handler = log.JSONHandler(output)
case logFmtFlag == "json":
handler = log.JSONHandler(output)
case logFmtFlag == "logfmt":
handler = log.LogfmtHandler(output)
case logFmtFlag == "", logFmtFlag == "terminal":
useColor := (isatty.IsTerminal(os.Stderr.Fd()) || isatty.IsCygwinTerminal(os.Stderr.Fd())) && os.Getenv("TERM") != "dumb"
if useColor {
terminalOutput = colorable.NewColorableStderr()
if logOutputFile != nil {
output = io.MultiWriter(logOutputFile, terminalOutput)
} else {
output = terminalOutput
}
}
handler = log.NewTerminalHandler(output, useColor)
default:
// Unknown log format specified
return fmt.Errorf("unknown log format: %v", ctx.String(logFormatFlag.Name))
}
glogger = log.NewGlogHandler(handler)
// logging
verbosity := log.FromLegacyLevel(ctx.Int(verbosityFlag.Name))
glogger.Verbosity(verbosity)
vmodule := ctx.String(logVmoduleFlag.Name)
if vmodule == "" {
// Retain backwards compatibility with `--vmodule` flag if `--log.vmodule` not set
vmodule = ctx.String(vmoduleFlag.Name)
if vmodule != "" {
defer log.Warn("The flag '--vmodule' is deprecated, please use '--log.vmodule' instead")
}
}
glogger.Vmodule(vmodule)
log.SetDefault(log.NewLogger(glogger))
// profiling, tracing
runtime.MemProfileRate = memprofilerateFlag.Value
if ctx.IsSet(memprofilerateFlag.Name) {
runtime.MemProfileRate = ctx.Int(memprofilerateFlag.Name)
}
blockProfileRate := ctx.Int(blockprofilerateFlag.Name)
Handler.SetBlockProfileRate(blockProfileRate)
if traceFile := ctx.String(traceFlag.Name); traceFile != "" {
if err := Handler.StartGoTrace(traceFile); err != nil {
return err
}
}
if cpuFile := ctx.String(cpuprofileFlag.Name); cpuFile != "" {
if err := Handler.StartCPUProfile(cpuFile); err != nil {
return err
}
}
// pprof server
if ctx.Bool(pprofFlag.Name) {
listenHost := ctx.String(pprofAddrFlag.Name)
port := ctx.Int(pprofPortFlag.Name)
address := net.JoinHostPort(listenHost, fmt.Sprintf("%d", port))
// This context value ("metrics.addr") represents the utils.MetricsHTTPFlag.Name.
// It cannot be imported because it will cause a cyclical dependency.
StartPProf(address, !ctx.IsSet("metrics.addr"))
}
if len(logFile) > 0 || rotation {
log.Info("Logging configured", context...)
}
return nil
}
func StartPProf(address string, withMetrics bool) {
// Hook go-metrics into expvar on any /debug/metrics request, load all vars
// from the registry into expvar, and execute regular expvar handler.
if withMetrics {
exp.Exp(metrics.DefaultRegistry)
}
http.Handle("/memsize/", http.StripPrefix("/memsize", &Memsize))
log.Info("Starting pprof server", "addr", fmt.Sprintf("http://%s/debug/pprof", address))
go func() {
if err := http.ListenAndServe(address, nil); err != nil {
log.Error("Failure in running pprof server", "err", err)
}
}()
}
// Exit stops all running profiles, flushing their output to the
// respective file.
func Exit() {
Handler.StopCPUProfile()
Handler.StopGoTrace()
if logOutputFile != nil {
logOutputFile.Close()
}
}
func validateLogLocation(path string) error {
if err := os.MkdirAll(path, os.ModePerm); err != nil {
return fmt.Errorf("error creating the directory: %w", err)
}
// Check if the path is writable by trying to create a temporary file
tmp := filepath.Join(path, "tmp")
if f, err := os.Create(tmp); err != nil {
return err
} else {
f.Close()
}
return os.Remove(tmp)
}

View file

@ -1,25 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package debug
import "runtime/debug"
// LoudPanic panics in a way that gets all goroutine stacks printed on stderr.
func LoudPanic(x interface{}) {
debug.SetTraceback("all")
panic(x)
}

View file

@ -1,61 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package debug
import (
"errors"
"os"
"runtime/trace"
"github.com/ethereum/go-ethereum/log"
)
// StartGoTrace turns on tracing, writing to the given file.
func (h *HandlerT) StartGoTrace(file string) error {
h.mu.Lock()
defer h.mu.Unlock()
if h.traceW != nil {
return errors.New("trace already in progress")
}
f, err := os.Create(expandHome(file))
if err != nil {
return err
}
if err := trace.Start(f); err != nil {
f.Close()
return err
}
h.traceW = f
h.traceFile = file
log.Info("Go tracing started", "dump", h.traceFile)
return nil
}
// StopGoTrace stops an ongoing trace.
func (h *HandlerT) StopGoTrace() error {
h.mu.Lock()
defer h.mu.Unlock()
trace.Stop()
if h.traceW == nil {
return errors.New("trace not in progress")
}
log.Info("Done writing Go trace", "dump", h.traceFile)
h.traceW.Close()
h.traceW = nil
h.traceFile = ""
return nil
}

View file

@ -1,53 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethapi
import (
"sync"
"github.com/ethereum/go-ethereum/common"
)
type AddrLocker struct {
mu sync.Mutex
locks map[common.Address]*sync.Mutex
}
// lock returns the lock of the given address.
func (l *AddrLocker) lock(address common.Address) *sync.Mutex {
l.mu.Lock()
defer l.mu.Unlock()
if l.locks == nil {
l.locks = make(map[common.Address]*sync.Mutex)
}
if _, ok := l.locks[address]; !ok {
l.locks[address] = new(sync.Mutex)
}
return l.locks[address]
}
// LockAddr locks an account's mutex. This is used to prevent another tx getting the
// same nonce until the lock is released. The mutex prevents the (an identical nonce) from
// being read again during the time that the first transaction is being signed.
func (l *AddrLocker) LockAddr(address common.Address) {
l.lock(address).Lock()
}
// UnlockAddr unlocks the mutex of the given account.
func (l *AddrLocker) UnlockAddr(address common.Address) {
l.lock(address).Unlock()
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,128 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package ethapi implements the general Ethereum API functions.
package ethapi
import (
"context"
"math/big"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
// Backend interface provides the common API services (that are provided by
// both full and light clients) with access to necessary functions.
type Backend interface {
// General Ethereum API
SyncProgress() ethereum.SyncProgress
SuggestGasTipCap(ctx context.Context) (*big.Int, error)
FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error)
ChainDb() ethdb.Database
AccountManager() *accounts.Manager
ExtRPCEnabled() bool
RPCGasCap() uint64 // global gas cap for eth_call over rpc: DoS protection
RPCEVMTimeout() time.Duration // global timeout for eth_call over rpc: DoS protection
RPCTxFeeCap() float64 // global tx fee cap for all transaction related APIs
UnprotectedAllowed() bool // allows only for EIP155 transactions.
// Blockchain API
SetHead(number uint64)
HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error)
HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error)
HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error)
CurrentHeader() *types.Header
CurrentBlock() *types.Header
BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error)
BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error)
BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error)
StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error)
StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error)
PendingBlockAndReceipts() (*types.Block, types.Receipts)
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
GetTd(ctx context.Context, hash common.Hash) *big.Int
GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription
// Transaction pool API
SendTx(ctx context.Context, signedTx *types.Transaction) error
GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
GetPoolTransactions() (types.Transactions, error)
GetPoolTransaction(txHash common.Hash) *types.Transaction
GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error)
Stats() (pending int, queued int)
TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction)
TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction)
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
ChainConfig() *params.ChainConfig
Engine() consensus.Engine
// This is copied from filters.Backend
// eth/filters needs to be initialized from this backend type, so methods needed by
// it must also be included here.
GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error)
GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error)
SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription
SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription
SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription
BloomStatus() (uint64, uint64)
ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)
}
func GetAPIs(apiBackend Backend) []rpc.API {
nonceLock := new(AddrLocker)
return []rpc.API{
{
Namespace: "eth",
Service: NewEthereumAPI(apiBackend),
}, {
Namespace: "eth",
Service: NewBlockChainAPI(apiBackend),
}, {
Namespace: "eth",
Service: NewTransactionAPI(apiBackend, nonceLock),
}, {
Namespace: "txpool",
Service: NewTxPoolAPI(apiBackend),
}, {
Namespace: "debug",
Service: NewDebugAPI(apiBackend),
}, {
Namespace: "eth",
Service: NewEthereumAccountAPI(apiBackend.AccountManager()),
}, {
Namespace: "personal",
Service: NewPersonalAccountAPI(apiBackend, nonceLock),
},
}
}

View file

@ -1,43 +0,0 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethapi
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
// DbGet returns the raw value of a key stored in the database.
func (api *DebugAPI) DbGet(key string) (hexutil.Bytes, error) {
blob, err := common.ParseHexOrString(key)
if err != nil {
return nil, err
}
return api.b.ChainDb().Get(blob)
}
// DbAncient retrieves an ancient binary blob from the append-only immutable files.
// It is a mapping to the `AncientReaderOp.Ancient` method
func (api *DebugAPI) DbAncient(kind string, number uint64) (hexutil.Bytes, error) {
return api.b.ChainDb().Ancient(kind, number)
}
// DbAncients returns the ancient item numbers in the ancient store.
// It is a mapping to the `AncientReaderOp.Ancients` method
func (api *DebugAPI) DbAncients() (uint64, error) {
return api.b.ChainDb().Ancients()
}

View file

@ -1,25 +0,0 @@
{
"baseFeePerGas": "0x342770c0",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x1",
"parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x26a",
"stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22",
"timestamp": "0xa",
"totalDifficulty": "0x1",
"transactions": [
"0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e"
],
"transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7",
"uncles": []
}

View file

@ -1,23 +0,0 @@
{
"baseFeePerGas": "0x3b9aca00",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x0",
"hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x200",
"stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
"timestamp": "0x0",
"totalDifficulty": "0x1",
"transactions": [],
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncles": []
}

View file

@ -1,41 +0,0 @@
{
"baseFeePerGas": "0x121a9cca",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x9",
"parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x26a",
"stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0",
"timestamp": "0x5a",
"totalDifficulty": "0x1",
"transactions": [
{
"blockHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"blockNumber": "0x9",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gas": "0x5208",
"gasPrice": "0x121a9cca",
"hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725",
"input": "0x",
"nonce": "0x8",
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
"transactionIndex": "0x0",
"value": "0x3e8",
"type": "0x0",
"v": "0x1b",
"r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd",
"s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d"
}
],
"transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5",
"uncles": []
}

View file

@ -1,25 +0,0 @@
{
"baseFeePerGas": "0xfdc7303",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0xa",
"parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x26a",
"stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91",
"timestamp": "0x64",
"totalDifficulty": "0x1",
"transactions": [
"0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644"
],
"transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445",
"uncles": []
}

View file

@ -1 +0,0 @@
null

View file

@ -1,23 +0,0 @@
{
"baseFeePerGas": "0x3b9aca00",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x0",
"hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x200",
"stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
"timestamp": "0x0",
"totalDifficulty": "0x1",
"transactions": [],
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"uncles": []
}

View file

@ -1,25 +0,0 @@
{
"baseFeePerGas": "0x342770c0",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x1",
"parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x26a",
"stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22",
"timestamp": "0xa",
"totalDifficulty": "0x1",
"transactions": [
"0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e"
],
"transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7",
"uncles": []
}

View file

@ -1,41 +0,0 @@
{
"baseFeePerGas": "0x121a9cca",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x9",
"parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x26a",
"stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0",
"timestamp": "0x5a",
"totalDifficulty": "0x1",
"transactions": [
{
"blockHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"blockNumber": "0x9",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gas": "0x5208",
"gasPrice": "0x121a9cca",
"hash": "0xecd155a61a5734b3efab75924e3ae34026c7c4133d8c2a46122bd03d7d199725",
"input": "0x",
"nonce": "0x8",
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
"transactionIndex": "0x0",
"value": "0x3e8",
"type": "0x0",
"v": "0x1b",
"r": "0xc6028b8e983d62fa8542f8a7633fb23cc941be2c897134352d95a7d9b19feafd",
"s": "0xeb6adcaaae3bed489c6cce4435f9db05d23a52820c78bd350e31eec65ed809d"
}
],
"transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5",
"uncles": []
}

View file

@ -1,25 +0,0 @@
{
"baseFeePerGas": "0xfdc7303",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0xa",
"parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x26a",
"stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91",
"timestamp": "0x64",
"totalDifficulty": "0x1",
"transactions": [
"0x3ee4094ca1e0b07a66dd616a057e081e53144ca7e9685a126fd4dda9ca042644"
],
"transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445",
"uncles": []
}

View file

@ -1,50 +0,0 @@
{
"difficulty": "0x0",
"extraData": "0x",
"gasLimit": "0x0",
"gasUsed": "0x0",
"hash": null,
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": null,
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": null,
"number": "0xb",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x256",
"stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x2a",
"totalDifficulty": null,
"transactions": [
{
"blockHash": "0x6cebd9f966ea686f44b981685e3f0eacea28591a7a86d7fbbe521a86e9f81165",
"blockNumber": "0xb",
"from": "0x0000000000000000000000000000000000000000",
"gas": "0x457",
"gasPrice": "0x2b67",
"hash": "0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298",
"input": "0x111111",
"nonce": "0xb",
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
"transactionIndex": "0x0",
"value": "0x6f",
"type": "0x0",
"chainId": "0x7fffffffffffffee",
"v": "0x0",
"r": "0x0",
"s": "0x0"
}
],
"transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
"uncles": [],
"withdrawals": [
{
"index": "0x0",
"validatorIndex": "0x1",
"address": "0x1234000000000000000000000000000000000000",
"amount": "0xa"
}
],
"withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84"
}

View file

@ -1,33 +0,0 @@
{
"difficulty": "0x0",
"extraData": "0x",
"gasLimit": "0x0",
"gasUsed": "0x0",
"hash": null,
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": null,
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": null,
"number": "0xb",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"size": "0x256",
"stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x2a",
"totalDifficulty": null,
"transactions": [
"0x4afee081df5dff7a025964032871f7d4ba4d21baf5f6376a2f4a9f79fc506298"
],
"transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
"uncles": [],
"withdrawals": [
{
"index": "0x0",
"validatorIndex": "0x1",
"address": "0x1234000000000000000000000000000000000000",
"amount": "0xa"
}
],
"withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84"
}

View file

@ -1,20 +0,0 @@
[
{
"blobGasPrice": "0x1",
"blobGasUsed": "0x20000",
"blockHash": "0xe724dfd4349861f4dceef2bc4df086d0a3d88858214f6bee9fcf1bebd1edc2a6",
"blockNumber": "0x6",
"contractAddress": null,
"cumulativeGasUsed": "0x5208",
"effectiveGasPrice": "0x1b09d63b",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x5208",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
"transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f",
"transactionIndex": "0x0",
"type": "0x3"
}
]

View file

@ -1,18 +0,0 @@
[
{
"blockHash": "0x1e7dcf3abe8bf05d32367a5dc387caa32578b15871bf8b3cbeedf2d8d530f844",
"blockNumber": "0x2",
"contractAddress": "0xae9bea628c4ce503dcfd7e305cab4e29e7476592",
"cumulativeGasUsed": "0xcf50",
"effectiveGasPrice": "0x2db16291",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0xcf50",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": null,
"transactionHash": "0x340e58cda5086495010b571fe25067fecc9954dc4ee3cedece00691fa3f5904a",
"transactionIndex": "0x0",
"type": "0x0"
}
]

View file

@ -1,18 +0,0 @@
[
{
"blockHash": "0xffa737e6ce9a9162ffd411dd06169114b3ed5ee9fc1474a2625c92548e4455e0",
"blockNumber": "0x4",
"contractAddress": null,
"cumulativeGasUsed": "0x538d",
"effectiveGasPrice": "0x2325c42f",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x538d",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x0",
"to": "0x0000000000000000000000000000000000031ec7",
"transactionHash": "0xdcde2574628c9d7dff22b9afa19f235959a924ceec65a9df903a517ae91f5c84",
"transactionIndex": "0x0",
"type": "0x2"
}
]

View file

@ -1,34 +0,0 @@
[
{
"blockHash": "0x173dcd9d22ce71929cd17e84ea88702a0f84d6244c6898d2a4f48722e494fe9c",
"blockNumber": "0x3",
"contractAddress": null,
"cumulativeGasUsed": "0x5e28",
"effectiveGasPrice": "0x281c2585",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x5e28",
"logs": [
{
"address": "0x0000000000000000000000000000000000031ec7",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7",
"0x0000000000000000000000000000000000000000000000000000000000000003"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000000d",
"blockNumber": "0x3",
"transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287",
"transactionIndex": "0x0",
"blockHash": "0x173dcd9d22ce71929cd17e84ea88702a0f84d6244c6898d2a4f48722e494fe9c",
"logIndex": "0x0",
"removed": false
}
],
"logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000",
"status": "0x1",
"to": "0x0000000000000000000000000000000000031ec7",
"transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287",
"transactionIndex": "0x0",
"type": "0x0"
}
]

View file

@ -1,18 +0,0 @@
[
{
"blockHash": "0xa8a067b3cb3b9ddc6cfb8317bfd08b266fcf9994fc870c1f7ed394acecfadf39",
"blockNumber": "0x1",
"contractAddress": null,
"cumulativeGasUsed": "0x5208",
"effectiveGasPrice": "0x342770c0",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x5208",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
"transactionHash": "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e",
"transactionIndex": "0x0",
"type": "0x0"
}
]

View file

@ -1 +0,0 @@
null

View file

@ -1 +0,0 @@
[]

View file

@ -1 +0,0 @@
[]

View file

@ -1,20 +0,0 @@
[
{
"blobGasPrice": "0x1",
"blobGasUsed": "0x20000",
"blockHash": "0xe724dfd4349861f4dceef2bc4df086d0a3d88858214f6bee9fcf1bebd1edc2a6",
"blockNumber": "0x6",
"contractAddress": null,
"cumulativeGasUsed": "0x5208",
"effectiveGasPrice": "0x1b09d63b",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x5208",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
"transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f",
"transactionIndex": "0x0",
"type": "0x3"
}
]

View file

@ -1,20 +0,0 @@
{
"baseFeePerGas": "0x3b9aca00",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x0",
"hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
"timestamp": "0x0",
"totalDifficulty": "0x1",
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}

View file

@ -1,20 +0,0 @@
{
"baseFeePerGas": "0x342770c0",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x1",
"parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22",
"timestamp": "0xa",
"totalDifficulty": "0x1",
"transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7"
}

View file

@ -1 +0,0 @@
null

View file

@ -1,20 +0,0 @@
{
"baseFeePerGas": "0x121a9cca",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x9",
"parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0",
"timestamp": "0x5a",
"totalDifficulty": "0x1",
"transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5"
}

View file

@ -1,20 +0,0 @@
{
"baseFeePerGas": "0xfdc7303",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0xa",
"parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91",
"timestamp": "0x64",
"totalDifficulty": "0x1",
"transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445"
}

View file

@ -1 +0,0 @@
null

View file

@ -1,20 +0,0 @@
{
"baseFeePerGas": "0x3b9aca00",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x0",
"hash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x0",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0xfe168c5e9584a85927212e5bea5304bb7d0d8a893453b4b2c52176a72f585ae2",
"timestamp": "0x0",
"totalDifficulty": "0x1",
"transactionsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"
}

View file

@ -1,20 +0,0 @@
{
"baseFeePerGas": "0x342770c0",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0x0da274b315de8e4d5bf8717218ec43540464ef36378cb896469bb731e1d3f3cb",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x1",
"parentHash": "0xbdc7d83b8f876938810462fe8d053263a482e44201e3883d4ae204ff4de7eff5",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0x92c5c55a698963f5b06e3aee415630f5c48b0760e537af94917ce9c4f42a2e22",
"timestamp": "0xa",
"totalDifficulty": "0x1",
"transactionsRoot": "0xca0ebcce920d2cdfbf9e1dbe90ed3441a1a576f344bd80e60508da814916f4e7"
}

View file

@ -1,20 +0,0 @@
{
"baseFeePerGas": "0x121a9cca",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0x9",
"parentHash": "0x5abd19c39d9f1c6e52998e135ea14e1fbc5db3fa2a108f4538e238ca5c2e68d7",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0xbd4aa2c2873df709151075250a8c01c9a14d2b0e2f715dbdd16e0ef8030c2cf0",
"timestamp": "0x5a",
"totalDifficulty": "0x1",
"transactionsRoot": "0x0767ed8359337dc6a8fdc77fe52db611bed1be87aac73c4556b1bf1dd3d190a5"
}

View file

@ -1,20 +0,0 @@
{
"baseFeePerGas": "0xfdc7303",
"difficulty": "0x20000",
"extraData": "0x",
"gasLimit": "0x47e7c4",
"gasUsed": "0x5208",
"hash": "0x97f540a3577c0f645c5dada5da86f38350e8f847e71f21124f917835003e2607",
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": "0x0000000000000000000000000000000000000000",
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": "0x0000000000000000",
"number": "0xa",
"parentHash": "0xda97ed946e0d502fb898b0ac881bd44da3c7fee5eaf184431e1ec3d361dad17e",
"receiptsRoot": "0x056b23fbba480696b65fe5a59b8f2148a1299103c4f57df839233af2cf4ca2d2",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0xbb62872e4023fa8a8b17b9cc37031f4817d9595779748d01cba408b495707a91",
"timestamp": "0x64",
"totalDifficulty": "0x1",
"transactionsRoot": "0xb0893d21a4a44dc26a962a6e91abae66df87fb61ac9c60e936aee89c76331445"
}

View file

@ -1,20 +0,0 @@
{
"difficulty": "0x0",
"extraData": "0x",
"gasLimit": "0x0",
"gasUsed": "0x0",
"hash": null,
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"miner": null,
"mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce": null,
"number": "0xb",
"parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000",
"receiptsRoot": "0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
"stateRoot": "0x0000000000000000000000000000000000000000000000000000000000000000",
"timestamp": "0x2a",
"totalDifficulty": null,
"transactionsRoot": "0x98d9f6dd0aa479c0fb448f2627e9f1964aca699fccab8f6e95861547a4699e37",
"withdrawalsRoot": "0x73d756269cdfc22e7e17a3548e36f42f750ca06d7e3cd98d1b6d0eb5add9dc84"
}

View file

@ -1,18 +0,0 @@
{
"blobGasPrice": "0x1",
"blobGasUsed": "0x20000",
"blockHash": "0xe724dfd4349861f4dceef2bc4df086d0a3d88858214f6bee9fcf1bebd1edc2a6",
"blockNumber": "0x6",
"contractAddress": null,
"cumulativeGasUsed": "0x5208",
"effectiveGasPrice": "0x1b09d63b",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x5208",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
"transactionHash": "0xb51ee3d2a89ba5d5623c73133c8d7a6ba9fb41194c17f4302c21b30994a1180f",
"transactionIndex": "0x0",
"type": "0x3"
}

View file

@ -1,16 +0,0 @@
{
"blockHash": "0x1e7dcf3abe8bf05d32367a5dc387caa32578b15871bf8b3cbeedf2d8d530f844",
"blockNumber": "0x2",
"contractAddress": "0xae9bea628c4ce503dcfd7e305cab4e29e7476592",
"cumulativeGasUsed": "0xcf50",
"effectiveGasPrice": "0x2db16291",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0xcf50",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": null,
"transactionHash": "0x340e58cda5086495010b571fe25067fecc9954dc4ee3cedece00691fa3f5904a",
"transactionIndex": "0x0",
"type": "0x0"
}

View file

@ -1,16 +0,0 @@
{
"blockHash": "0x3fadc5bc916018a326732be829a2565b3acb960a8406f0f151a5e1fa971ea7dd",
"blockNumber": "0x5",
"contractAddress": "0xfdaa97661a584d977b4d3abb5370766ff5b86a18",
"cumulativeGasUsed": "0xe01c",
"effectiveGasPrice": "0x1ecb3fb4",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0xe01c",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": null,
"transactionHash": "0xb5a1148819cfdfff9bfe70035524fec940eb735d89b76960b97751d01ae2a9f2",
"transactionIndex": "0x0",
"type": "0x1"
}

View file

@ -1,16 +0,0 @@
{
"blockHash": "0xffa737e6ce9a9162ffd411dd06169114b3ed5ee9fc1474a2625c92548e4455e0",
"blockNumber": "0x4",
"contractAddress": null,
"cumulativeGasUsed": "0x538d",
"effectiveGasPrice": "0x2325c42f",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x538d",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x0",
"to": "0x0000000000000000000000000000000000031ec7",
"transactionHash": "0xdcde2574628c9d7dff22b9afa19f235959a924ceec65a9df903a517ae91f5c84",
"transactionIndex": "0x0",
"type": "0x2"
}

View file

@ -1,16 +0,0 @@
{
"blockHash": "0xa8a067b3cb3b9ddc6cfb8317bfd08b266fcf9994fc870c1f7ed394acecfadf39",
"blockNumber": "0x1",
"contractAddress": null,
"cumulativeGasUsed": "0x5208",
"effectiveGasPrice": "0x342770c0",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x5208",
"logs": [],
"logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"status": "0x1",
"to": "0x0d3ab14bbad3d99f4203bd7a11acb94882050e7e",
"transactionHash": "0x644a31c354391520d00e95b9affbbb010fc79ac268144ab8e28207f4cf51097e",
"transactionIndex": "0x0",
"type": "0x0"
}

View file

@ -1,32 +0,0 @@
{
"blockHash": "0x173dcd9d22ce71929cd17e84ea88702a0f84d6244c6898d2a4f48722e494fe9c",
"blockNumber": "0x3",
"contractAddress": null,
"cumulativeGasUsed": "0x5e28",
"effectiveGasPrice": "0x281c2585",
"from": "0x703c4b2bd70c169f5717101caee543299fc946c7",
"gasUsed": "0x5e28",
"logs": [
{
"address": "0x0000000000000000000000000000000000031ec7",
"topics": [
"0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef",
"0x000000000000000000000000703c4b2bd70c169f5717101caee543299fc946c7",
"0x0000000000000000000000000000000000000000000000000000000000000003"
],
"data": "0x000000000000000000000000000000000000000000000000000000000000000d",
"blockNumber": "0x3",
"transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287",
"transactionIndex": "0x0",
"blockHash": "0x173dcd9d22ce71929cd17e84ea88702a0f84d6244c6898d2a4f48722e494fe9c",
"logIndex": "0x0",
"removed": false
}
],
"logsBloom": "0x00000000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000800000000000000008000000000000000000000000000000000020000000080000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000400000000002000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000",
"status": "0x1",
"to": "0x0000000000000000000000000000000000031ec7",
"transactionHash": "0xeaf3921cbf03ba45bad4e6ab807b196ce3b2a0b5bacc355b6272fa96b11b4287",
"transactionIndex": "0x0",
"type": "0x0"
}

View file

@ -1,346 +0,0 @@
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethapi
import (
"bytes"
"context"
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/rpc"
)
// TransactionArgs represents the arguments to construct a new transaction
// or a message call.
type TransactionArgs struct {
From *common.Address `json:"from"`
To *common.Address `json:"to"`
Gas *hexutil.Uint64 `json:"gas"`
GasPrice *hexutil.Big `json:"gasPrice"`
MaxFeePerGas *hexutil.Big `json:"maxFeePerGas"`
MaxPriorityFeePerGas *hexutil.Big `json:"maxPriorityFeePerGas"`
Value *hexutil.Big `json:"value"`
Nonce *hexutil.Uint64 `json:"nonce"`
// We accept "data" and "input" for backwards-compatibility reasons.
// "input" is the newer name and should be preferred by clients.
// Issue detail: https://github.com/ethereum/go-ethereum/issues/15628
Data *hexutil.Bytes `json:"data"`
Input *hexutil.Bytes `json:"input"`
// Introduced by AccessListTxType transaction.
AccessList *types.AccessList `json:"accessList,omitempty"`
ChainID *hexutil.Big `json:"chainId,omitempty"`
}
// from retrieves the transaction sender address.
func (args *TransactionArgs) from() common.Address {
if args.From == nil {
return common.Address{}
}
return *args.From
}
// data retrieves the transaction calldata. Input field is preferred.
func (args *TransactionArgs) data() []byte {
if args.Input != nil {
return *args.Input
}
if args.Data != nil {
return *args.Data
}
return nil
}
// setDefaults fills in default values for unspecified tx fields.
func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
if err := args.setFeeDefaults(ctx, b); err != nil {
return err
}
if args.Value == nil {
args.Value = new(hexutil.Big)
}
if args.Nonce == nil {
nonce, err := b.GetPoolNonce(ctx, args.from())
if err != nil {
return err
}
args.Nonce = (*hexutil.Uint64)(&nonce)
}
if args.Data != nil && args.Input != nil && !bytes.Equal(*args.Data, *args.Input) {
return errors.New(`both "data" and "input" are set and not equal. Please use "input" to pass transaction call data`)
}
if args.To == nil && len(args.data()) == 0 {
return errors.New(`contract creation without any data provided`)
}
// Estimate the gas usage if necessary.
if args.Gas == nil {
// These fields are immutable during the estimation, safe to
// pass the pointer directly.
data := args.data()
callArgs := TransactionArgs{
From: args.From,
To: args.To,
GasPrice: args.GasPrice,
MaxFeePerGas: args.MaxFeePerGas,
MaxPriorityFeePerGas: args.MaxPriorityFeePerGas,
Value: args.Value,
Data: (*hexutil.Bytes)(&data),
AccessList: args.AccessList,
}
pendingBlockNr := rpc.BlockNumberOrHashWithNumber(rpc.PendingBlockNumber)
estimated, err := DoEstimateGas(ctx, b, callArgs, pendingBlockNr, nil, b.RPCGasCap())
if err != nil {
return err
}
args.Gas = &estimated
log.Trace("Estimate gas usage automatically", "gas", args.Gas)
}
// If chain id is provided, ensure it matches the local chain id. Otherwise, set the local
// chain id as the default.
want := b.ChainConfig().ChainID
if args.ChainID != nil {
if have := (*big.Int)(args.ChainID); have.Cmp(want) != 0 {
return fmt.Errorf("chainId does not match node's (have=%v, want=%v)", have, want)
}
} else {
args.ChainID = (*hexutil.Big)(want)
}
return nil
}
// setFeeDefaults fills in default fee values for unspecified tx fields.
func (args *TransactionArgs) setFeeDefaults(ctx context.Context, b Backend) error {
// If both gasPrice and at least one of the EIP-1559 fee parameters are specified, error.
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
// If the tx has completely specified a fee mechanism, no default is needed.
// This allows users who are not yet synced past London to get defaults for
// other tx values. See https://github.com/ethereum/go-ethereum/pull/23274
// for more information.
eip1559ParamsSet := args.MaxFeePerGas != nil && args.MaxPriorityFeePerGas != nil
// Sanity check the EIP-1559 fee parameters if present.
if args.GasPrice == nil && eip1559ParamsSet {
if args.MaxFeePerGas.ToInt().Sign() == 0 {
return errors.New("maxFeePerGas must be non-zero")
}
if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
}
return nil // No need to set anything, user already set MaxFeePerGas and MaxPriorityFeePerGas
}
// Sanity check the non-EIP-1559 fee parameters.
head := b.CurrentHeader()
isLondon := b.ChainConfig().IsLondon(head.Number)
if args.GasPrice != nil && !eip1559ParamsSet {
// Zero gas-price is not allowed after London fork
if args.GasPrice.ToInt().Sign() == 0 && isLondon {
return errors.New("gasPrice must be non-zero after london fork")
}
return nil // No need to set anything, user already set GasPrice
}
// Now attempt to fill in default value depending on whether London is active or not.
if isLondon {
// London is active, set maxPriorityFeePerGas and maxFeePerGas.
if err := args.setLondonFeeDefaults(ctx, head, b); err != nil {
return err
}
} else {
if args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil {
return errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active")
}
// London not active, set gas price.
price, err := b.SuggestGasTipCap(ctx)
if err != nil {
return err
}
args.GasPrice = (*hexutil.Big)(price)
}
return nil
}
// setLondonFeeDefaults fills in reasonable default fee values for unspecified fields.
func (args *TransactionArgs) setLondonFeeDefaults(ctx context.Context, head *types.Header, b Backend) error {
// Set maxPriorityFeePerGas if it is missing.
if args.MaxPriorityFeePerGas == nil {
tip, err := b.SuggestGasTipCap(ctx)
if err != nil {
return err
}
args.MaxPriorityFeePerGas = (*hexutil.Big)(tip)
}
// Set maxFeePerGas if it is missing.
if args.MaxFeePerGas == nil {
// Set the max fee to be 2 times larger than the previous block's base fee.
// The additional slack allows the tx to not become invalidated if the base
// fee is rising.
val := new(big.Int).Add(
args.MaxPriorityFeePerGas.ToInt(),
new(big.Int).Mul(head.BaseFee, big.NewInt(2)),
)
args.MaxFeePerGas = (*hexutil.Big)(val)
}
// Both EIP-1559 fee parameters are now set; sanity check them.
if args.MaxFeePerGas.ToInt().Cmp(args.MaxPriorityFeePerGas.ToInt()) < 0 {
return fmt.Errorf("maxFeePerGas (%v) < maxPriorityFeePerGas (%v)", args.MaxFeePerGas, args.MaxPriorityFeePerGas)
}
return nil
}
// ToMessage converts the transaction arguments to the Message type used by the
// core evm. This method is used in calls and traces that do not require a real
// live transaction.
func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (*core.Message, error) {
// Reject invalid combinations of pre- and post-1559 fee styles
if args.GasPrice != nil && (args.MaxFeePerGas != nil || args.MaxPriorityFeePerGas != nil) {
return nil, errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified")
}
// Set sender address or use zero address if none specified.
addr := args.from()
// Set default gas & gas price if none were set
gas := globalGasCap
if gas == 0 {
gas = uint64(math.MaxUint64 / 2)
}
if args.Gas != nil {
gas = uint64(*args.Gas)
}
if globalGasCap != 0 && globalGasCap < gas {
log.Warn("Caller gas above allowance, capping", "requested", gas, "cap", globalGasCap)
gas = globalGasCap
}
var (
gasPrice *big.Int
gasFeeCap *big.Int
gasTipCap *big.Int
)
if baseFee == nil {
// If there's no basefee, then it must be a non-1559 execution
gasPrice = new(big.Int)
if args.GasPrice != nil {
gasPrice = args.GasPrice.ToInt()
}
gasFeeCap, gasTipCap = gasPrice, gasPrice
} else {
// A basefee is provided, necessitating 1559-type execution
if args.GasPrice != nil {
// User specified the legacy gas field, convert to 1559 gas typing
gasPrice = args.GasPrice.ToInt()
gasFeeCap, gasTipCap = gasPrice, gasPrice
} else {
// User specified 1559 gas fields (or none), use those
gasFeeCap = new(big.Int)
if args.MaxFeePerGas != nil {
gasFeeCap = args.MaxFeePerGas.ToInt()
}
gasTipCap = new(big.Int)
if args.MaxPriorityFeePerGas != nil {
gasTipCap = args.MaxPriorityFeePerGas.ToInt()
}
// Backfill the legacy gasPrice for EVM execution, unless we're all zeroes
gasPrice = new(big.Int)
if gasFeeCap.BitLen() > 0 || gasTipCap.BitLen() > 0 {
gasPrice = math.BigMin(new(big.Int).Add(gasTipCap, baseFee), gasFeeCap)
}
}
}
value := new(big.Int)
if args.Value != nil {
value = args.Value.ToInt()
}
data := args.data()
var accessList types.AccessList
if args.AccessList != nil {
accessList = *args.AccessList
}
msg := &core.Message{
From: addr,
To: args.To,
Value: value,
GasLimit: gas,
GasPrice: gasPrice,
GasFeeCap: gasFeeCap,
GasTipCap: gasTipCap,
Data: data,
AccessList: accessList,
SkipAccountChecks: true,
}
return msg, nil
}
// toTransaction converts the arguments to a transaction.
// This assumes that setDefaults has been called.
func (args *TransactionArgs) toTransaction() *types.Transaction {
var data types.TxData
switch {
case args.MaxFeePerGas != nil:
al := types.AccessList{}
if args.AccessList != nil {
al = *args.AccessList
}
data = &types.DynamicFeeTx{
To: args.To,
ChainID: (*big.Int)(args.ChainID),
Nonce: uint64(*args.Nonce),
Gas: uint64(*args.Gas),
GasFeeCap: (*big.Int)(args.MaxFeePerGas),
GasTipCap: (*big.Int)(args.MaxPriorityFeePerGas),
Value: (*big.Int)(args.Value),
Data: args.data(),
AccessList: al,
}
case args.AccessList != nil:
data = &types.AccessListTx{
To: args.To,
ChainID: (*big.Int)(args.ChainID),
Nonce: uint64(*args.Nonce),
Gas: uint64(*args.Gas),
GasPrice: (*big.Int)(args.GasPrice),
Value: (*big.Int)(args.Value),
Data: args.data(),
AccessList: *args.AccessList,
}
default:
data = &types.LegacyTx{
To: args.To,
Nonce: uint64(*args.Nonce),
Gas: uint64(*args.Gas),
GasPrice: (*big.Int)(args.GasPrice),
Value: (*big.Int)(args.Value),
Data: args.data(),
}
}
return types.NewTx(data)
}
// ToTransaction converts the arguments to a transaction.
// This assumes that setDefaults has been called.
func (args *TransactionArgs) ToTransaction() *types.Transaction {
return args.toTransaction()
}

View file

@ -1,367 +0,0 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package ethapi
import (
"context"
"errors"
"math/big"
"reflect"
"testing"
"time"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/bloombits"
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
// TestSetFeeDefaults tests the logic for filling in default fee values works as expected.
func TestSetFeeDefaults(t *testing.T) {
type test struct {
name string
isLondon bool
in *TransactionArgs
want *TransactionArgs
err error
}
var (
b = newBackendMock()
zero = (*hexutil.Big)(big.NewInt(0))
fortytwo = (*hexutil.Big)(big.NewInt(42))
maxFee = (*hexutil.Big)(new(big.Int).Add(new(big.Int).Mul(b.current.BaseFee, big.NewInt(2)), fortytwo.ToInt()))
al = &types.AccessList{types.AccessTuple{Address: common.Address{0xaa}, StorageKeys: []common.Hash{{0x01}}}}
)
tests := []test{
// Legacy txs
{
"legacy tx pre-London",
false,
&TransactionArgs{},
&TransactionArgs{GasPrice: fortytwo},
nil,
},
{
"legacy tx pre-London with zero price",
false,
&TransactionArgs{GasPrice: zero},
&TransactionArgs{GasPrice: zero},
nil,
},
{
"legacy tx post-London, explicit gas price",
true,
&TransactionArgs{GasPrice: fortytwo},
&TransactionArgs{GasPrice: fortytwo},
nil,
},
{
"legacy tx post-London with zero price",
true,
&TransactionArgs{GasPrice: zero},
nil,
errors.New("gasPrice must be non-zero after london fork"),
},
// Access list txs
{
"access list tx pre-London",
false,
&TransactionArgs{AccessList: al},
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
nil,
},
{
"access list tx post-London, explicit gas price",
false,
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
&TransactionArgs{AccessList: al, GasPrice: fortytwo},
nil,
},
{
"access list tx post-London",
true,
&TransactionArgs{AccessList: al},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"access list tx post-London, only max fee",
true,
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"access list tx post-London, only priority fee",
true,
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee},
&TransactionArgs{AccessList: al, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
// Dynamic fee txs
{
"dynamic tx post-London",
true,
&TransactionArgs{},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic tx post-London, only max fee",
true,
&TransactionArgs{MaxFeePerGas: maxFee},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic tx post-London, only priority fee",
true,
&TransactionArgs{MaxFeePerGas: maxFee},
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
},
{
"dynamic fee tx pre-London, maxFee set",
false,
&TransactionArgs{MaxFeePerGas: maxFee},
nil,
errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
},
{
"dynamic fee tx pre-London, priorityFee set",
false,
&TransactionArgs{MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("maxFeePerGas and maxPriorityFeePerGas are not valid before London is active"),
},
{
"dynamic fee tx, maxFee < priorityFee",
true,
&TransactionArgs{MaxFeePerGas: maxFee, MaxPriorityFeePerGas: (*hexutil.Big)(big.NewInt(1000))},
nil,
errors.New("maxFeePerGas (0x3e) < maxPriorityFeePerGas (0x3e8)"),
},
{
"dynamic fee tx, maxFee < priorityFee while setting default",
true,
&TransactionArgs{MaxFeePerGas: (*hexutil.Big)(big.NewInt(7))},
nil,
errors.New("maxFeePerGas (0x7) < maxPriorityFeePerGas (0x2a)"),
},
{
"dynamic fee tx post-London, explicit gas price",
true,
&TransactionArgs{MaxFeePerGas: zero, MaxPriorityFeePerGas: zero},
nil,
errors.New("maxFeePerGas must be non-zero"),
},
// Misc
{
"set all fee parameters",
false,
&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee, MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
{
"set gas price and maxPriorityFee",
false,
&TransactionArgs{GasPrice: fortytwo, MaxPriorityFeePerGas: fortytwo},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
{
"set gas price and maxFee",
true,
&TransactionArgs{GasPrice: fortytwo, MaxFeePerGas: maxFee},
nil,
errors.New("both gasPrice and (maxFeePerGas or maxPriorityFeePerGas) specified"),
},
}
ctx := context.Background()
for i, test := range tests {
if test.isLondon {
b.activateLondon()
} else {
b.deactivateLondon()
}
got := test.in
err := got.setFeeDefaults(ctx, b)
if err != nil && err.Error() == test.err.Error() {
// Test threw expected error.
continue
} else if err != nil {
t.Fatalf("test %d (%s): unexpected error: %s", i, test.name, err)
}
if !reflect.DeepEqual(got, test.want) {
t.Fatalf("test %d (%s): did not fill defaults as expected: (got: %v, want: %v)", i, test.name, got, test.want)
}
}
}
type backendMock struct {
current *types.Header
config *params.ChainConfig
}
func newBackendMock() *backendMock {
config := &params.ChainConfig{
ChainID: big.NewInt(42),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: true,
EIP150Block: big.NewInt(0),
EIP155Block: big.NewInt(0),
EIP158Block: big.NewInt(0),
ByzantiumBlock: big.NewInt(0),
ConstantinopleBlock: big.NewInt(0),
PetersburgBlock: big.NewInt(0),
IstanbulBlock: big.NewInt(0),
MuirGlacierBlock: big.NewInt(0),
BerlinBlock: big.NewInt(0),
LondonBlock: big.NewInt(1000),
}
return &backendMock{
current: &types.Header{
Difficulty: big.NewInt(10000000000),
Number: big.NewInt(1100),
GasLimit: 8_000_000,
GasUsed: 8_000_000,
Time: 555,
Extra: make([]byte, 32),
BaseFee: big.NewInt(10),
},
config: config,
}
}
func (b *backendMock) activateLondon() {
b.current.Number = big.NewInt(1100)
}
func (b *backendMock) deactivateLondon() {
b.current.Number = big.NewInt(900)
}
func (b *backendMock) SuggestGasTipCap(ctx context.Context) (*big.Int, error) {
return big.NewInt(42), nil
}
func (b *backendMock) CurrentHeader() *types.Header { return b.current }
func (b *backendMock) ChainConfig() *params.ChainConfig { return b.config }
// Other methods needed to implement Backend interface.
func (b *backendMock) SyncProgress() ethereum.SyncProgress { return ethereum.SyncProgress{} }
func (b *backendMock) FeeHistory(ctx context.Context, blockCount uint64, lastBlock rpc.BlockNumber, rewardPercentiles []float64) (*big.Int, [][]*big.Int, []*big.Int, []float64, error) {
return nil, nil, nil, nil, nil
}
func (b *backendMock) ChainDb() ethdb.Database { return nil }
func (b *backendMock) AccountManager() *accounts.Manager { return nil }
func (b *backendMock) ExtRPCEnabled() bool { return false }
func (b *backendMock) RPCGasCap() uint64 { return 0 }
func (b *backendMock) RPCEVMTimeout() time.Duration { return time.Second }
func (b *backendMock) RPCTxFeeCap() float64 { return 0 }
func (b *backendMock) UnprotectedAllowed() bool { return false }
func (b *backendMock) SetHead(number uint64) {}
func (b *backendMock) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
return nil, nil
}
func (b *backendMock) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
return nil, nil
}
func (b *backendMock) HeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Header, error) {
return nil, nil
}
func (b *backendMock) CurrentBlock() *types.Header { return nil }
func (b *backendMock) BlockByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Block, error) {
return nil, nil
}
func (b *backendMock) BlockByHash(ctx context.Context, hash common.Hash) (*types.Block, error) {
return nil, nil
}
func (b *backendMock) BlockByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*types.Block, error) {
return nil, nil
}
func (b *backendMock) GetBody(ctx context.Context, hash common.Hash, number rpc.BlockNumber) (*types.Body, error) {
return nil, nil
}
func (b *backendMock) StateAndHeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*state.StateDB, *types.Header, error) {
return nil, nil, nil
}
func (b *backendMock) StateAndHeaderByNumberOrHash(ctx context.Context, blockNrOrHash rpc.BlockNumberOrHash) (*state.StateDB, *types.Header, error) {
return nil, nil, nil
}
func (b *backendMock) PendingBlockAndReceipts() (*types.Block, types.Receipts) { return nil, nil }
func (b *backendMock) GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error) {
return nil, nil
}
func (b *backendMock) GetLogs(ctx context.Context, blockHash common.Hash, number uint64) ([][]*types.Log, error) {
return nil, nil
}
func (b *backendMock) GetTd(ctx context.Context, hash common.Hash) *big.Int { return nil }
func (b *backendMock) GetEVM(ctx context.Context, msg *core.Message, state *state.StateDB, header *types.Header, vmConfig *vm.Config, blockCtx *vm.BlockContext) *vm.EVM {
return nil
}
func (b *backendMock) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription { return nil }
func (b *backendMock) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
return nil
}
func (b *backendMock) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
return nil
}
func (b *backendMock) SendTx(ctx context.Context, signedTx *types.Transaction) error { return nil }
func (b *backendMock) GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error) {
return nil, [32]byte{}, 0, 0, nil
}
func (b *backendMock) GetPoolTransactions() (types.Transactions, error) { return nil, nil }
func (b *backendMock) GetPoolTransaction(txHash common.Hash) *types.Transaction { return nil }
func (b *backendMock) GetPoolNonce(ctx context.Context, addr common.Address) (uint64, error) {
return 0, nil
}
func (b *backendMock) Stats() (pending int, queued int) { return 0, 0 }
func (b *backendMock) TxPoolContent() (map[common.Address][]*types.Transaction, map[common.Address][]*types.Transaction) {
return nil, nil
}
func (b *backendMock) TxPoolContentFrom(addr common.Address) ([]*types.Transaction, []*types.Transaction) {
return nil, nil
}
func (b *backendMock) SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription { return nil }
func (b *backendMock) BloomStatus() (uint64, uint64) { return 0, 0 }
func (b *backendMock) ServiceFilter(ctx context.Context, session *bloombits.MatcherSession) {}
func (b *backendMock) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription { return nil }
func (b *backendMock) SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription {
return nil
}
func (b *backendMock) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
return nil
}
func (b *backendMock) Engine() consensus.Engine { return nil }

View file

@ -1,45 +0,0 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package flags
import "github.com/urfave/cli/v2"
const (
EthCategory = "ETHEREUM"
LightCategory = "LIGHT CLIENT"
DevCategory = "DEVELOPER CHAIN"
StateCategory = "STATE HISTORY MANAGEMENT"
TxPoolCategory = "TRANSACTION POOL (EVM)"
BlobPoolCategory = "TRANSACTION POOL (BLOB)"
PerfCategory = "PERFORMANCE TUNING"
AccountCategory = "ACCOUNT"
APICategory = "API AND CONSOLE"
NetworkingCategory = "NETWORKING"
MinerCategory = "MINER"
GasPriceCategory = "GAS PRICE ORACLE"
VMCategory = "VIRTUAL MACHINE"
LoggingCategory = "LOGGING AND DEBUGGING"
MetricsCategory = "METRICS AND STATS"
MiscCategory = "MISC"
TestingCategory = "TESTING"
DeprecatedCategory = "ALIASED (deprecated)"
)
func init() {
cli.HelpFlag.(*cli.BoolFlag).Category = MiscCategory
cli.VersionFlag.(*cli.BoolFlag).Category = MiscCategory
}

View file

@ -1,377 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package flags
import (
"encoding"
"errors"
"flag"
"fmt"
"math/big"
"os"
"os/user"
"path/filepath"
"strings"
"syscall"
"github.com/ethereum/go-ethereum/common/math"
"github.com/urfave/cli/v2"
)
// DirectoryString is custom type which is registered in the flags library which cli uses for
// argument parsing. This allows us to expand Value to an absolute path when
// the argument is parsed
type DirectoryString string
func (s *DirectoryString) String() string {
return string(*s)
}
func (s *DirectoryString) Set(value string) error {
*s = DirectoryString(expandPath(value))
return nil
}
var (
_ cli.Flag = (*DirectoryFlag)(nil)
_ cli.RequiredFlag = (*DirectoryFlag)(nil)
_ cli.VisibleFlag = (*DirectoryFlag)(nil)
_ cli.DocGenerationFlag = (*DirectoryFlag)(nil)
_ cli.CategorizableFlag = (*DirectoryFlag)(nil)
)
// DirectoryFlag is custom cli.Flag type which expand the received string to an absolute path.
// e.g. ~/.ethereum -> /home/username/.ethereum
type DirectoryFlag struct {
Name string
Category string
DefaultText string
Usage string
Required bool
Hidden bool
HasBeenSet bool
Value DirectoryString
Aliases []string
EnvVars []string
}
// For cli.Flag:
func (f *DirectoryFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) }
func (f *DirectoryFlag) IsSet() bool { return f.HasBeenSet }
func (f *DirectoryFlag) String() string { return cli.FlagStringer(f) }
// Apply called by cli library, grabs variable from environment (if in env)
// and adds variable to flag set for parsing.
func (f *DirectoryFlag) Apply(set *flag.FlagSet) error {
for _, envVar := range f.EnvVars {
envVar = strings.TrimSpace(envVar)
if value, found := syscall.Getenv(envVar); found {
f.Value.Set(value)
f.HasBeenSet = true
break
}
}
eachName(f, func(name string) {
set.Var(&f.Value, f.Name, f.Usage)
})
return nil
}
// For cli.RequiredFlag:
func (f *DirectoryFlag) IsRequired() bool { return f.Required }
// For cli.VisibleFlag:
func (f *DirectoryFlag) IsVisible() bool { return !f.Hidden }
// For cli.CategorizableFlag:
func (f *DirectoryFlag) GetCategory() string { return f.Category }
// For cli.DocGenerationFlag:
func (f *DirectoryFlag) TakesValue() bool { return true }
func (f *DirectoryFlag) GetUsage() string { return f.Usage }
func (f *DirectoryFlag) GetValue() string { return f.Value.String() }
func (f *DirectoryFlag) GetEnvVars() []string { return f.EnvVars }
func (f *DirectoryFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
type TextMarshaler interface {
encoding.TextMarshaler
encoding.TextUnmarshaler
}
// textMarshalerVal turns a TextMarshaler into a flag.Value
type textMarshalerVal struct {
v TextMarshaler
}
func (v textMarshalerVal) String() string {
if v.v == nil {
return ""
}
text, _ := v.v.MarshalText()
return string(text)
}
func (v textMarshalerVal) Set(s string) error {
return v.v.UnmarshalText([]byte(s))
}
var (
_ cli.Flag = (*TextMarshalerFlag)(nil)
_ cli.RequiredFlag = (*TextMarshalerFlag)(nil)
_ cli.VisibleFlag = (*TextMarshalerFlag)(nil)
_ cli.DocGenerationFlag = (*TextMarshalerFlag)(nil)
_ cli.CategorizableFlag = (*TextMarshalerFlag)(nil)
)
// TextMarshalerFlag wraps a TextMarshaler value.
type TextMarshalerFlag struct {
Name string
Category string
DefaultText string
Usage string
Required bool
Hidden bool
HasBeenSet bool
Value TextMarshaler
Aliases []string
EnvVars []string
}
// For cli.Flag:
func (f *TextMarshalerFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) }
func (f *TextMarshalerFlag) IsSet() bool { return f.HasBeenSet }
func (f *TextMarshalerFlag) String() string { return cli.FlagStringer(f) }
func (f *TextMarshalerFlag) Apply(set *flag.FlagSet) error {
for _, envVar := range f.EnvVars {
envVar = strings.TrimSpace(envVar)
if value, found := syscall.Getenv(envVar); found {
if err := f.Value.UnmarshalText([]byte(value)); err != nil {
return fmt.Errorf("could not parse %q from environment variable %q for flag %s: %s", value, envVar, f.Name, err)
}
f.HasBeenSet = true
break
}
}
eachName(f, func(name string) {
set.Var(textMarshalerVal{f.Value}, f.Name, f.Usage)
})
return nil
}
// For cli.RequiredFlag:
func (f *TextMarshalerFlag) IsRequired() bool { return f.Required }
// For cli.VisibleFlag:
func (f *TextMarshalerFlag) IsVisible() bool { return !f.Hidden }
// For cli.CategorizableFlag:
func (f *TextMarshalerFlag) GetCategory() string { return f.Category }
// For cli.DocGenerationFlag:
func (f *TextMarshalerFlag) TakesValue() bool { return true }
func (f *TextMarshalerFlag) GetUsage() string { return f.Usage }
func (f *TextMarshalerFlag) GetEnvVars() []string { return f.EnvVars }
func (f *TextMarshalerFlag) GetValue() string {
t, err := f.Value.MarshalText()
if err != nil {
return "(ERR: " + err.Error() + ")"
}
return string(t)
}
func (f *TextMarshalerFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// GlobalTextMarshaler returns the value of a TextMarshalerFlag from the global flag set.
func GlobalTextMarshaler(ctx *cli.Context, name string) TextMarshaler {
val := ctx.Generic(name)
if val == nil {
return nil
}
return val.(textMarshalerVal).v
}
var (
_ cli.Flag = (*BigFlag)(nil)
_ cli.RequiredFlag = (*BigFlag)(nil)
_ cli.VisibleFlag = (*BigFlag)(nil)
_ cli.DocGenerationFlag = (*BigFlag)(nil)
_ cli.CategorizableFlag = (*BigFlag)(nil)
)
// BigFlag is a command line flag that accepts 256 bit big integers in decimal or
// hexadecimal syntax.
type BigFlag struct {
Name string
Category string
DefaultText string
Usage string
Required bool
Hidden bool
HasBeenSet bool
Value *big.Int
Aliases []string
EnvVars []string
}
// For cli.Flag:
func (f *BigFlag) Names() []string { return append([]string{f.Name}, f.Aliases...) }
func (f *BigFlag) IsSet() bool { return f.HasBeenSet }
func (f *BigFlag) String() string { return cli.FlagStringer(f) }
func (f *BigFlag) Apply(set *flag.FlagSet) error {
for _, envVar := range f.EnvVars {
envVar = strings.TrimSpace(envVar)
if value, found := syscall.Getenv(envVar); found {
if _, ok := f.Value.SetString(value, 10); !ok {
return fmt.Errorf("could not parse %q from environment variable %q for flag %s", value, envVar, f.Name)
}
f.HasBeenSet = true
break
}
}
eachName(f, func(name string) {
f.Value = new(big.Int)
set.Var((*bigValue)(f.Value), f.Name, f.Usage)
})
return nil
}
// For cli.RequiredFlag:
func (f *BigFlag) IsRequired() bool { return f.Required }
// For cli.VisibleFlag:
func (f *BigFlag) IsVisible() bool { return !f.Hidden }
// For cli.CategorizableFlag:
func (f *BigFlag) GetCategory() string { return f.Category }
// For cli.DocGenerationFlag:
func (f *BigFlag) TakesValue() bool { return true }
func (f *BigFlag) GetUsage() string { return f.Usage }
func (f *BigFlag) GetValue() string { return f.Value.String() }
func (f *BigFlag) GetEnvVars() []string { return f.EnvVars }
func (f *BigFlag) GetDefaultText() string {
if f.DefaultText != "" {
return f.DefaultText
}
return f.GetValue()
}
// bigValue turns *big.Int into a flag.Value
type bigValue big.Int
func (b *bigValue) String() string {
if b == nil {
return ""
}
return (*big.Int)(b).String()
}
func (b *bigValue) Set(s string) error {
intVal, ok := math.ParseBig256(s)
if !ok {
return errors.New("invalid integer syntax")
}
*b = (bigValue)(*intVal)
return nil
}
// GlobalBig returns the value of a BigFlag from the global flag set.
func GlobalBig(ctx *cli.Context, name string) *big.Int {
val := ctx.Generic(name)
if val == nil {
return nil
}
return (*big.Int)(val.(*bigValue))
}
// Expands a file path
// 1. replace tilde with users home dir
// 2. expands embedded environment variables
// 3. cleans the path, e.g. /a/b/../c -> /a/c
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
func expandPath(p string) string {
// Named pipes are not file paths on windows, ignore
if strings.HasPrefix(p, `\\.\pipe`) {
return p
}
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
if home := HomeDir(); home != "" {
p = home + p[1:]
}
}
return filepath.Clean(os.ExpandEnv(p))
}
func HomeDir() string {
if home := os.Getenv("HOME"); home != "" {
return home
}
if usr, err := user.Current(); err == nil {
return usr.HomeDir
}
return ""
}
func eachName(f cli.Flag, fn func(string)) {
for _, name := range f.Names() {
name = strings.Trim(name, " ")
fn(name)
}
}

View file

@ -1,61 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package flags
import (
"os"
"os/user"
"runtime"
"testing"
)
func TestPathExpansion(t *testing.T) {
user, _ := user.Current()
var tests map[string]string
if runtime.GOOS == "windows" {
tests = map[string]string{
`/home/someuser/tmp`: `\home\someuser\tmp`,
`~/tmp`: user.HomeDir + `\tmp`,
`~thisOtherUser/b/`: `~thisOtherUser\b`,
`$DDDXXX/a/b`: `\tmp\a\b`,
`/a/b/`: `\a\b`,
`C:\Documents\Newsletters\`: `C:\Documents\Newsletters`,
`C:\`: `C:\`,
`\\.\pipe\\pipe\geth621383`: `\\.\pipe\\pipe\geth621383`,
}
} else {
tests = map[string]string{
`/home/someuser/tmp`: `/home/someuser/tmp`,
`~/tmp`: user.HomeDir + `/tmp`,
`~thisOtherUser/b/`: `~thisOtherUser/b`,
`$DDDXXX/a/b`: `/tmp/a/b`,
`/a/b/`: `/a/b`,
`C:\Documents\Newsletters\`: `C:\Documents\Newsletters\`,
`C:\`: `C:\`,
`\\.\pipe\\pipe\geth621383`: `\\.\pipe\\pipe\geth621383`,
}
}
os.Setenv(`DDDXXX`, `/tmp`)
for test, expected := range tests {
got := expandPath(test)
if got != expected {
t.Errorf(`test %s, got %s, expected %s\n`, test, got, expected)
}
}
}

View file

@ -1,310 +0,0 @@
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package flags
import (
"fmt"
"os"
"regexp"
"sort"
"strings"
"github.com/ethereum/go-ethereum/internal/version"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
)
// usecolor defines whether the CLI help should use colored output or normal dumb
// colorless terminal formatting.
var usecolor = (isatty.IsTerminal(os.Stdout.Fd()) || isatty.IsCygwinTerminal(os.Stdout.Fd())) && os.Getenv("TERM") != "dumb"
// NewApp creates an app with sane defaults.
func NewApp(usage string) *cli.App {
git, _ := version.VCS()
app := cli.NewApp()
app.EnableBashCompletion = true
app.Version = params.VersionWithCommit(git.Commit, git.Date)
app.Usage = usage
app.Copyright = "Copyright 2013-2023 The go-ethereum Authors"
app.Before = func(ctx *cli.Context) error {
MigrateGlobalFlags(ctx)
return nil
}
return app
}
// Merge merges the given flag slices.
func Merge(groups ...[]cli.Flag) []cli.Flag {
var ret []cli.Flag
for _, group := range groups {
ret = append(ret, group...)
}
return ret
}
var migrationApplied = map[*cli.Command]struct{}{}
// MigrateGlobalFlags makes all global flag values available in the
// context. This should be called as early as possible in app.Before.
//
// Example:
//
// geth account new --keystore /tmp/mykeystore --lightkdf
//
// is equivalent after calling this method with:
//
// geth --keystore /tmp/mykeystore --lightkdf account new
//
// i.e. in the subcommand Action function of 'account new', ctx.Bool("lightkdf)
// will return true even if --lightkdf is set as a global option.
//
// This function may become unnecessary when https://github.com/urfave/cli/pull/1245 is merged.
func MigrateGlobalFlags(ctx *cli.Context) {
var iterate func(cs []*cli.Command, fn func(*cli.Command))
iterate = func(cs []*cli.Command, fn func(*cli.Command)) {
for _, cmd := range cs {
if _, ok := migrationApplied[cmd]; ok {
continue
}
migrationApplied[cmd] = struct{}{}
fn(cmd)
iterate(cmd.Subcommands, fn)
}
}
// This iterates over all commands and wraps their action function.
iterate(ctx.App.Commands, func(cmd *cli.Command) {
if cmd.Action == nil {
return
}
action := cmd.Action
cmd.Action = func(ctx *cli.Context) error {
doMigrateFlags(ctx)
return action(ctx)
}
})
}
func doMigrateFlags(ctx *cli.Context) {
// Figure out if there are any aliases of commands. If there are, we want
// to ignore them when iterating over the flags.
aliases := make(map[string]bool)
for _, fl := range ctx.Command.Flags {
for _, alias := range fl.Names()[1:] {
aliases[alias] = true
}
}
for _, name := range ctx.FlagNames() {
for _, parent := range ctx.Lineage()[1:] {
if parent.IsSet(name) {
// When iterating across the lineage, we will be served both
// the 'canon' and alias formats of all commmands. In most cases,
// it's fine to set it in the ctx multiple times (one for each
// name), however, the Slice-flags are not fine.
// The slice-flags accumulate, so if we set it once as
// "foo" and once as alias "F", then both will be present in the slice.
if _, isAlias := aliases[name]; isAlias {
continue
}
// If it is a string-slice, we need to set it as
// "alfa, beta, gamma" instead of "[alfa beta gamma]", in order
// for the backing StringSlice to parse it properly.
if result := parent.StringSlice(name); len(result) > 0 {
ctx.Set(name, strings.Join(result, ","))
} else {
ctx.Set(name, parent.String(name))
}
break
}
}
}
}
func init() {
if usecolor {
// Annotate all help categories with colors
cli.AppHelpTemplate = regexp.MustCompile("[A-Z ]+:").ReplaceAllString(cli.AppHelpTemplate, "\u001B[33m$0\u001B[0m")
// Annotate flag categories with colors (private template, so need to
// copy-paste the entire thing here...)
cli.AppHelpTemplate = strings.ReplaceAll(cli.AppHelpTemplate, "{{template \"visibleFlagCategoryTemplate\" .}}", "{{range .VisibleFlagCategories}}\n {{if .Name}}\u001B[33m{{.Name}}\u001B[0m\n\n {{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}}\n{{else}}{{$e}}\n {{end}}{{end}}{{end}}")
}
cli.FlagStringer = FlagString
}
// FlagString prints a single flag in help.
func FlagString(f cli.Flag) string {
df, ok := f.(cli.DocGenerationFlag)
if !ok {
return ""
}
needsPlaceholder := df.TakesValue()
placeholder := ""
if needsPlaceholder {
placeholder = "value"
}
namesText := cli.FlagNamePrefixer(df.Names(), placeholder)
defaultValueString := ""
if s := df.GetDefaultText(); s != "" {
defaultValueString = " (default: " + s + ")"
}
envHint := strings.TrimSpace(cli.FlagEnvHinter(df.GetEnvVars(), ""))
if envHint != "" {
envHint = " (" + envHint[1:len(envHint)-1] + ")"
}
usage := strings.TrimSpace(df.GetUsage())
usage = wordWrap(usage, 80)
usage = indent(usage, 10)
if usecolor {
return fmt.Sprintf("\n \u001B[32m%-35s%-35s\u001B[0m%s\n%s", namesText, defaultValueString, envHint, usage)
} else {
return fmt.Sprintf("\n %-35s%-35s%s\n%s", namesText, defaultValueString, envHint, usage)
}
}
func indent(s string, nspace int) string {
ind := strings.Repeat(" ", nspace)
return ind + strings.ReplaceAll(s, "\n", "\n"+ind)
}
func wordWrap(s string, width int) string {
var (
output strings.Builder
lineLength = 0
)
for {
sp := strings.IndexByte(s, ' ')
var word string
if sp == -1 {
word = s
} else {
word = s[:sp]
}
wlen := len(word)
over := lineLength+wlen >= width
if over {
output.WriteByte('\n')
lineLength = 0
} else {
if lineLength != 0 {
output.WriteByte(' ')
lineLength++
}
}
output.WriteString(word)
lineLength += wlen
if sp == -1 {
break
}
s = s[wlen+1:]
}
return output.String()
}
// AutoEnvVars extends all the specific CLI flags with automatically generated
// env vars by capitalizing the flag, replacing . with _ and prefixing it with
// the specified string.
//
// Note, the prefix should *not* contain the separator underscore, that will be
// added automatically.
func AutoEnvVars(flags []cli.Flag, prefix string) {
for _, flag := range flags {
envvar := strings.ToUpper(prefix + "_" + strings.ReplaceAll(strings.ReplaceAll(flag.Names()[0], ".", "_"), "-", "_"))
switch flag := flag.(type) {
case *cli.StringFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.StringSliceFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.BoolFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.IntFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.Int64Flag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.Uint64Flag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.Float64Flag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.DurationFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *cli.PathFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *BigFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *TextMarshalerFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
case *DirectoryFlag:
flag.EnvVars = append(flag.EnvVars, envvar)
}
}
}
// CheckEnvVars iterates over all the environment variables and checks if any of
// them look like a CLI flag but is not consumed. This can be used to detect old
// or mistyped names.
func CheckEnvVars(ctx *cli.Context, flags []cli.Flag, prefix string) {
known := make(map[string]string)
for _, flag := range flags {
docflag, ok := flag.(cli.DocGenerationFlag)
if !ok {
continue
}
for _, envvar := range docflag.GetEnvVars() {
known[envvar] = flag.Names()[0]
}
}
keyvals := os.Environ()
sort.Strings(keyvals)
for _, keyval := range keyvals {
key := strings.Split(keyval, "=")[0]
if !strings.HasPrefix(key, prefix) {
continue
}
if flag, ok := known[key]; ok {
if ctx.Count(flag) > 0 {
log.Info("Config environment variable found", "envvar", key, "shadowedby", "--"+flag)
} else {
log.Info("Config environment variable found", "envvar", key)
}
} else {
log.Warn("Unknown config environment variable", "envvar", key)
}
}
}

View file

@ -1,18 +0,0 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package guide is a small test suite to ensure snippets in the dev guide work.
package guide

View file

@ -1,97 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// This file contains the code snippets from the developer's guide embedded into
// Go tests. This ensures that any code published in out guides will not break
// accidentally via some code update. If some API changes nonetheless that needs
// modifying this file, please port any modification over into the developer's
// guide wiki pages too!
package guide
import (
"math/big"
"path/filepath"
"testing"
"time"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
// Tests that the account management snippets work correctly.
func TestAccountManagement(t *testing.T) {
// Create a temporary folder to work with
workdir := t.TempDir()
// Create an encrypted keystore (using light scrypt parameters)
ks := keystore.NewKeyStore(filepath.Join(workdir, "keystore"), keystore.LightScryptN, keystore.LightScryptP)
// Create a new account with the specified encryption passphrase
newAcc, err := ks.NewAccount("Creation password")
if err != nil {
t.Fatalf("Failed to create new account: %v", err)
}
// Export the newly created account with a different passphrase. The returned
// data from this method invocation is a JSON encoded, encrypted key-file
jsonAcc, err := ks.Export(newAcc, "Creation password", "Export password")
if err != nil {
t.Fatalf("Failed to export account: %v", err)
}
// Update the passphrase on the account created above inside the local keystore
if err := ks.Update(newAcc, "Creation password", "Update password"); err != nil {
t.Fatalf("Failed to update account: %v", err)
}
// Delete the account updated above from the local keystore
if err := ks.Delete(newAcc, "Update password"); err != nil {
t.Fatalf("Failed to delete account: %v", err)
}
// Import back the account we've exported (and then deleted) above with yet
// again a fresh passphrase
if _, err := ks.Import(jsonAcc, "Export password", "Import password"); err != nil {
t.Fatalf("Failed to import account: %v", err)
}
// Create a new account to sign transactions with
signer, err := ks.NewAccount("Signer password")
if err != nil {
t.Fatalf("Failed to create signer account: %v", err)
}
tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 0, big.NewInt(0), nil)
chain := big.NewInt(1)
// Sign a transaction with a single authorization
if _, err := ks.SignTxWithPassphrase(signer, "Signer password", tx, chain); err != nil {
t.Fatalf("Failed to sign with passphrase: %v", err)
}
// Sign a transaction with multiple manually cancelled authorizations
if err := ks.Unlock(signer, "Signer password"); err != nil {
t.Fatalf("Failed to unlock account: %v", err)
}
if _, err := ks.SignTx(signer, tx, chain); err != nil {
t.Fatalf("Failed to sign with unlocked account: %v", err)
}
if err := ks.Lock(signer.Address); err != nil {
t.Fatalf("Failed to lock account: %v", err)
}
// Sign a transaction with multiple automatically cancelled authorizations
if err := ks.TimedUnlock(signer, "Signer password", time.Second); err != nil {
t.Fatalf("Failed to time unlock account: %v", err)
}
if _, err := ks.SignTx(signer, tx, chain); err != nil {
t.Fatalf("Failed to sign with time unlocked account: %v", err)
}
}

View file

@ -1,93 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package jsre
import (
"regexp"
"sort"
"strings"
"github.com/dop251/goja"
)
// JS numerical token
var numerical = regexp.MustCompile(`^(NaN|-?((\d*\.\d+|\d+)([Ee][+-]?\d+)?|Infinity))$`)
// CompleteKeywords returns potential continuations for the given line. Since line is
// evaluated, callers need to make sure that evaluating line does not have side effects.
func (jsre *JSRE) CompleteKeywords(line string) []string {
var results []string
jsre.Do(func(vm *goja.Runtime) {
results = getCompletions(vm, line)
})
return results
}
func getCompletions(vm *goja.Runtime, line string) (results []string) {
parts := strings.Split(line, ".")
if len(parts) == 0 {
return nil
}
// Find the right-most fully named object in the line. e.g. if line = "x.y.z"
// and "x.y" is an object, obj will reference "x.y".
obj := vm.GlobalObject()
for i := 0; i < len(parts)-1; i++ {
if numerical.MatchString(parts[i]) {
return nil
}
v := obj.Get(parts[i])
if v == nil || goja.IsNull(v) || goja.IsUndefined(v) {
return nil // No object was found
}
obj = v.ToObject(vm)
}
// Go over the keys of the object and retain the keys matching prefix.
// Example: if line = "x.y.z" and "x.y" exists and has keys "zebu", "zebra"
// and "platypus", then "x.y.zebu" and "x.y.zebra" will be added to results.
prefix := parts[len(parts)-1]
iterOwnAndConstructorKeys(vm, obj, func(k string) {
if strings.HasPrefix(k, prefix) {
if len(parts) == 1 {
results = append(results, k)
} else {
results = append(results, strings.Join(parts[:len(parts)-1], ".")+"."+k)
}
}
})
// Append opening parenthesis (for functions) or dot (for objects)
// if the line itself is the only completion.
if len(results) == 1 && results[0] == line {
// Accessing the property will cause it to be evaluated.
// This can cause an error, e.g. in case of web3.eth.protocolVersion
// which has been dropped from geth. Ignore the error for autocompletion
// purposes.
obj := SafeGet(obj, parts[len(parts)-1])
if obj != nil {
if _, isfunc := goja.AssertFunction(obj); isfunc {
results[0] += "("
} else {
results[0] += "."
}
}
}
sort.Strings(results)
return results
}

View file

@ -1,93 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package jsre
import (
"os"
"reflect"
"testing"
)
func TestCompleteKeywords(t *testing.T) {
re := New("", os.Stdout)
re.Run(`
function theClass() {
this.foo = 3;
this.gazonk = {xyz: 4};
}
theClass.prototype.someMethod = function () {};
var x = new theClass();
var y = new theClass();
y.someMethod = function override() {};
`)
var tests = []struct {
input string
want []string
}{
{
input: "St",
want: []string{"String"},
},
{
input: "x",
want: []string{"x."},
},
{
input: "x.someMethod",
want: []string{"x.someMethod("},
},
{
input: "x.",
want: []string{
"x.constructor",
"x.foo",
"x.gazonk",
"x.someMethod",
},
},
{
input: "y.",
want: []string{
"y.constructor",
"y.foo",
"y.gazonk",
"y.someMethod",
},
},
{
input: "x.gazonk.",
want: []string{
"x.gazonk.__proto__",
"x.gazonk.constructor",
"x.gazonk.hasOwnProperty",
"x.gazonk.isPrototypeOf",
"x.gazonk.propertyIsEnumerable",
"x.gazonk.toLocaleString",
"x.gazonk.toString",
"x.gazonk.valueOf",
"x.gazonk.xyz",
},
},
}
for _, test := range tests {
cs := re.CompleteKeywords(test.input)
if !reflect.DeepEqual(cs, test.want) {
t.Errorf("wrong completions for %q\ngot %v\nwant %v", test.input, cs, test.want)
}
}
}

File diff suppressed because one or more lines are too long

View file

@ -1,28 +0,0 @@
// Copyright 2017 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package deps contains the console JavaScript dependencies Go embedded.
package deps
import (
_ "embed"
)
//go:embed web3.js
var Web3JS string
//go:embed bignumber.js
var BigNumberJS string

File diff suppressed because it is too large Load diff

View file

@ -1,340 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package jsre provides execution environment for JavaScript.
package jsre
import (
crand "crypto/rand"
"encoding/binary"
"errors"
"fmt"
"io"
"math/rand"
"os"
"time"
"github.com/dop251/goja"
"github.com/ethereum/go-ethereum/common"
)
// JSRE is a JS runtime environment embedding the goja interpreter.
// It provides helper functions to load code from files, run code snippets
// and bind native go objects to JS.
//
// The runtime runs all code on a dedicated event loop and does not expose the underlying
// goja runtime directly. To use the runtime, call JSRE.Do. When binding a Go function,
// use the Call type to gain access to the runtime.
type JSRE struct {
assetPath string
output io.Writer
evalQueue chan *evalReq
stopEventLoop chan bool
closed chan struct{}
vm *goja.Runtime
}
// Call is the argument type of Go functions which are callable from JS.
type Call struct {
goja.FunctionCall
VM *goja.Runtime
}
// jsTimer is a single timer instance with a callback function
type jsTimer struct {
timer *time.Timer
duration time.Duration
interval bool
call goja.FunctionCall
}
// evalReq is a serialized vm execution request processed by runEventLoop.
type evalReq struct {
fn func(vm *goja.Runtime)
done chan bool
}
// runtime must be stopped with Stop() after use and cannot be used after stopping
func New(assetPath string, output io.Writer) *JSRE {
re := &JSRE{
assetPath: assetPath,
output: output,
closed: make(chan struct{}),
evalQueue: make(chan *evalReq),
stopEventLoop: make(chan bool),
vm: goja.New(),
}
go re.runEventLoop()
re.Set("loadScript", MakeCallback(re.vm, re.loadScript))
re.Set("inspect", re.prettyPrintJS)
return re
}
// randomSource returns a pseudo random value generator.
func randomSource() *rand.Rand {
bytes := make([]byte, 8)
seed := time.Now().UnixNano()
if _, err := crand.Read(bytes); err == nil {
seed = int64(binary.LittleEndian.Uint64(bytes))
}
src := rand.NewSource(seed)
return rand.New(src)
}
// This function runs the main event loop from a goroutine that is started
// when JSRE is created. Use Stop() before exiting to properly stop it.
// The event loop processes vm access requests from the evalQueue in a
// serialized way and calls timer callback functions at the appropriate time.
// Exported functions always access the vm through the event queue. You can
// call the functions of the goja vm directly to circumvent the queue. These
// functions should be used if and only if running a routine that was already
// called from JS through an RPC call.
func (re *JSRE) runEventLoop() {
defer close(re.closed)
r := randomSource()
re.vm.SetRandSource(r.Float64)
registry := map[*jsTimer]*jsTimer{}
ready := make(chan *jsTimer)
newTimer := func(call goja.FunctionCall, interval bool) (*jsTimer, goja.Value) {
delay := call.Argument(1).ToInteger()
if 0 >= delay {
delay = 1
}
timer := &jsTimer{
duration: time.Duration(delay) * time.Millisecond,
call: call,
interval: interval,
}
registry[timer] = timer
timer.timer = time.AfterFunc(timer.duration, func() {
ready <- timer
})
return timer, re.vm.ToValue(timer)
}
setTimeout := func(call goja.FunctionCall) goja.Value {
_, value := newTimer(call, false)
return value
}
setInterval := func(call goja.FunctionCall) goja.Value {
_, value := newTimer(call, true)
return value
}
clearTimeout := func(call goja.FunctionCall) goja.Value {
timer := call.Argument(0).Export()
if timer, ok := timer.(*jsTimer); ok {
timer.timer.Stop()
delete(registry, timer)
}
return goja.Undefined()
}
re.vm.Set("_setTimeout", setTimeout)
re.vm.Set("_setInterval", setInterval)
re.vm.RunString(`var setTimeout = function(args) {
if (arguments.length < 1) {
throw TypeError("Failed to execute 'setTimeout': 1 argument required, but only 0 present.");
}
return _setTimeout.apply(this, arguments);
}`)
re.vm.RunString(`var setInterval = function(args) {
if (arguments.length < 1) {
throw TypeError("Failed to execute 'setInterval': 1 argument required, but only 0 present.");
}
return _setInterval.apply(this, arguments);
}`)
re.vm.Set("clearTimeout", clearTimeout)
re.vm.Set("clearInterval", clearTimeout)
var waitForCallbacks bool
loop:
for {
select {
case timer := <-ready:
// execute callback, remove/reschedule the timer
var arguments []interface{}
if len(timer.call.Arguments) > 2 {
tmp := timer.call.Arguments[2:]
arguments = make([]interface{}, 2+len(tmp))
for i, value := range tmp {
arguments[i+2] = value
}
} else {
arguments = make([]interface{}, 1)
}
arguments[0] = timer.call.Arguments[0]
call, isFunc := goja.AssertFunction(timer.call.Arguments[0])
if !isFunc {
panic(re.vm.ToValue("js error: timer/timeout callback is not a function"))
}
call(goja.Null(), timer.call.Arguments...)
_, inreg := registry[timer] // when clearInterval is called from within the callback don't reset it
if timer.interval && inreg {
timer.timer.Reset(timer.duration)
} else {
delete(registry, timer)
if waitForCallbacks && (len(registry) == 0) {
break loop
}
}
case req := <-re.evalQueue:
// run the code, send the result back
req.fn(re.vm)
close(req.done)
if waitForCallbacks && (len(registry) == 0) {
break loop
}
case waitForCallbacks = <-re.stopEventLoop:
if !waitForCallbacks || (len(registry) == 0) {
break loop
}
}
}
for _, timer := range registry {
timer.timer.Stop()
delete(registry, timer)
}
}
// Do executes the given function on the JS event loop.
// When the runtime is stopped, fn will not execute.
func (re *JSRE) Do(fn func(*goja.Runtime)) {
done := make(chan bool)
req := &evalReq{fn, done}
select {
case re.evalQueue <- req:
<-done
case <-re.closed:
}
}
// Stop terminates the event loop, optionally waiting for all timers to expire.
func (re *JSRE) Stop(waitForCallbacks bool) {
timeout := time.NewTimer(10 * time.Millisecond)
defer timeout.Stop()
for {
select {
case <-re.closed:
return
case re.stopEventLoop <- waitForCallbacks:
<-re.closed
return
case <-timeout.C:
// JS is blocked, interrupt and try again.
re.vm.Interrupt(errors.New("JS runtime stopped"))
}
}
}
// Exec(file) loads and runs the contents of a file
// if a relative path is given, the jsre's assetPath is used
func (re *JSRE) Exec(file string) error {
code, err := os.ReadFile(common.AbsolutePath(re.assetPath, file))
if err != nil {
return err
}
return re.Compile(file, string(code))
}
// Run runs a piece of JS code.
func (re *JSRE) Run(code string) (v goja.Value, err error) {
re.Do(func(vm *goja.Runtime) { v, err = vm.RunString(code) })
return v, err
}
// Set assigns value v to a variable in the JS environment.
func (re *JSRE) Set(ns string, v interface{}) (err error) {
re.Do(func(vm *goja.Runtime) { vm.Set(ns, v) })
return err
}
// MakeCallback turns the given function into a function that's callable by JS.
func MakeCallback(vm *goja.Runtime, fn func(Call) (goja.Value, error)) goja.Value {
return vm.ToValue(func(call goja.FunctionCall) goja.Value {
result, err := fn(Call{call, vm})
if err != nil {
panic(vm.NewGoError(err))
}
return result
})
}
// Evaluate executes code and pretty prints the result to the specified output stream.
func (re *JSRE) Evaluate(code string, w io.Writer) {
re.Do(func(vm *goja.Runtime) {
val, err := vm.RunString(code)
if err != nil {
prettyError(vm, err, w)
} else {
prettyPrint(vm, val, w)
}
fmt.Fprintln(w)
})
}
// Interrupt stops the current JS evaluation.
func (re *JSRE) Interrupt(v interface{}) {
done := make(chan bool)
noop := func(*goja.Runtime) {}
select {
case re.evalQueue <- &evalReq{noop, done}:
// event loop is not blocked.
default:
re.vm.Interrupt(v)
}
}
// Compile compiles and then runs a piece of JS code.
func (re *JSRE) Compile(filename string, src string) (err error) {
re.Do(func(vm *goja.Runtime) { _, err = compileAndRun(vm, filename, src) })
return err
}
// loadScript loads and executes a JS file.
func (re *JSRE) loadScript(call Call) (goja.Value, error) {
file := call.Argument(0).ToString().String()
file = common.AbsolutePath(re.assetPath, file)
source, err := os.ReadFile(file)
if err != nil {
return nil, fmt.Errorf("could not read file %s: %v", file, err)
}
value, err := compileAndRun(re.vm, file, string(source))
if err != nil {
return nil, fmt.Errorf("error while compiling or running script: %v", err)
}
return value, nil
}
func compileAndRun(vm *goja.Runtime, filename string, src string) (goja.Value, error) {
script, err := goja.Compile(filename, src, false)
if err != nil {
return goja.Null(), err
}
return vm.RunProgram(script)
}

View file

@ -1,130 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package jsre
import (
"os"
"path"
"reflect"
"testing"
"time"
"github.com/dop251/goja"
)
type testNativeObjectBinding struct {
vm *goja.Runtime
}
type msg struct {
Msg string
}
func (no *testNativeObjectBinding) TestMethod(call goja.FunctionCall) goja.Value {
m := call.Argument(0).ToString().String()
return no.vm.ToValue(&msg{m})
}
func newWithTestJS(t *testing.T, testjs string) *JSRE {
dir := t.TempDir()
if testjs != "" {
if err := os.WriteFile(path.Join(dir, "test.js"), []byte(testjs), os.ModePerm); err != nil {
t.Fatal("cannot create test.js:", err)
}
}
jsre := New(dir, os.Stdout)
return jsre
}
func TestExec(t *testing.T) {
jsre := newWithTestJS(t, `msg = "testMsg"`)
err := jsre.Exec("test.js")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
val, err := jsre.Run("msg")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
if val.ExportType().Kind() != reflect.String {
t.Errorf("expected string value, got %v", val)
}
exp := "testMsg"
got := val.ToString().String()
if exp != got {
t.Errorf("expected '%v', got '%v'", exp, got)
}
jsre.Stop(false)
}
func TestNatto(t *testing.T) {
jsre := newWithTestJS(t, `setTimeout(function(){msg = "testMsg"}, 1);`)
err := jsre.Exec("test.js")
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
time.Sleep(100 * time.Millisecond)
val, err := jsre.Run("msg")
if err != nil {
t.Fatalf("expected no error, got %v", err)
}
if val.ExportType().Kind() != reflect.String {
t.Fatalf("expected string value, got %v", val)
}
exp := "testMsg"
got := val.ToString().String()
if exp != got {
t.Fatalf("expected '%v', got '%v'", exp, got)
}
jsre.Stop(false)
}
func TestBind(t *testing.T) {
jsre := New("", os.Stdout)
defer jsre.Stop(false)
jsre.Set("no", &testNativeObjectBinding{vm: jsre.vm})
_, err := jsre.Run(`no.TestMethod("testMsg")`)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
}
func TestLoadScript(t *testing.T) {
jsre := newWithTestJS(t, `msg = "testMsg"`)
_, err := jsre.Run(`loadScript("test.js")`)
if err != nil {
t.Errorf("expected no error, got %v", err)
}
val, err := jsre.Run("msg")
if err != nil {
t.Errorf("expected no error, got %v", err)
}
if val.ExportType().Kind() != reflect.String {
t.Errorf("expected string value, got %v", val)
}
exp := "testMsg"
got := val.ToString().String()
if exp != got {
t.Errorf("expected '%v', got '%v'", exp, got)
}
jsre.Stop(false)
}

View file

@ -1,301 +0,0 @@
// Copyright 2016 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package jsre
import (
"fmt"
"io"
"reflect"
"sort"
"strconv"
"strings"
"github.com/dop251/goja"
"github.com/fatih/color"
)
const (
maxPrettyPrintLevel = 3
indentString = " "
)
var (
FunctionColor = color.New(color.FgMagenta).SprintfFunc()
SpecialColor = color.New(color.Bold).SprintfFunc()
NumberColor = color.New(color.FgRed).SprintfFunc()
StringColor = color.New(color.FgGreen).SprintfFunc()
ErrorColor = color.New(color.FgHiRed).SprintfFunc()
)
// these fields are hidden when printing objects.
var boringKeys = map[string]bool{
"valueOf": true,
"toString": true,
"toLocaleString": true,
"hasOwnProperty": true,
"isPrototypeOf": true,
"propertyIsEnumerable": true,
"constructor": true,
}
// prettyPrint writes value to standard output.
func prettyPrint(vm *goja.Runtime, value goja.Value, w io.Writer) {
ppctx{vm: vm, w: w}.printValue(value, 0, false)
}
// prettyError writes err to standard output.
func prettyError(vm *goja.Runtime, err error, w io.Writer) {
failure := err.Error()
if gojaErr, ok := err.(*goja.Exception); ok {
failure = gojaErr.String()
}
fmt.Fprint(w, ErrorColor("%s", failure))
}
func (re *JSRE) prettyPrintJS(call goja.FunctionCall) goja.Value {
for _, v := range call.Arguments {
prettyPrint(re.vm, v, re.output)
fmt.Fprintln(re.output)
}
return goja.Undefined()
}
type ppctx struct {
vm *goja.Runtime
w io.Writer
}
func (ctx ppctx) indent(level int) string {
return strings.Repeat(indentString, level)
}
func (ctx ppctx) printValue(v goja.Value, level int, inArray bool) {
if goja.IsNull(v) || goja.IsUndefined(v) {
fmt.Fprint(ctx.w, SpecialColor(v.String()))
return
}
kind := v.ExportType().Kind()
switch {
case kind == reflect.Bool:
fmt.Fprint(ctx.w, SpecialColor("%t", v.ToBoolean()))
case kind == reflect.String:
fmt.Fprint(ctx.w, StringColor("%q", v.String()))
case kind >= reflect.Int && kind <= reflect.Complex128:
fmt.Fprint(ctx.w, NumberColor("%s", v.String()))
default:
if obj, ok := v.(*goja.Object); ok {
ctx.printObject(obj, level, inArray)
} else {
fmt.Fprintf(ctx.w, "<unprintable %T>", v)
}
}
}
// SafeGet attempt to get the value associated to `key`, and
// catches the panic that goja creates if an error occurs in
// key.
func SafeGet(obj *goja.Object, key string) (ret goja.Value) {
defer func() {
if r := recover(); r != nil {
ret = goja.Undefined()
}
}()
ret = obj.Get(key)
return ret
}
func (ctx ppctx) printObject(obj *goja.Object, level int, inArray bool) {
switch obj.ClassName() {
case "Array", "GoArray":
lv := obj.Get("length")
len := lv.ToInteger()
if len == 0 {
fmt.Fprintf(ctx.w, "[]")
return
}
if level > maxPrettyPrintLevel {
fmt.Fprint(ctx.w, "[...]")
return
}
fmt.Fprint(ctx.w, "[")
for i := int64(0); i < len; i++ {
el := obj.Get(strconv.FormatInt(i, 10))
if el != nil {
ctx.printValue(el, level+1, true)
}
if i < len-1 {
fmt.Fprintf(ctx.w, ", ")
}
}
fmt.Fprint(ctx.w, "]")
case "Object":
// Print values from bignumber.js as regular numbers.
if ctx.isBigNumber(obj) {
fmt.Fprint(ctx.w, NumberColor("%s", toString(obj)))
return
}
// Otherwise, print all fields indented, but stop if we're too deep.
keys := ctx.fields(obj)
if len(keys) == 0 {
fmt.Fprint(ctx.w, "{}")
return
}
if level > maxPrettyPrintLevel {
fmt.Fprint(ctx.w, "{...}")
return
}
fmt.Fprintln(ctx.w, "{")
for i, k := range keys {
v := SafeGet(obj, k)
fmt.Fprintf(ctx.w, "%s%s: ", ctx.indent(level+1), k)
ctx.printValue(v, level+1, false)
if i < len(keys)-1 {
fmt.Fprintf(ctx.w, ",")
}
fmt.Fprintln(ctx.w)
}
if inArray {
level--
}
fmt.Fprintf(ctx.w, "%s}", ctx.indent(level))
case "Function":
robj := obj.ToString()
desc := strings.Trim(strings.Split(robj.String(), "{")[0], " \t\n")
desc = strings.Replace(desc, " (", "(", 1)
fmt.Fprint(ctx.w, FunctionColor("%s", desc))
case "RegExp":
fmt.Fprint(ctx.w, StringColor("%s", toString(obj)))
default:
if level <= maxPrettyPrintLevel {
s := obj.ToString().String()
fmt.Fprintf(ctx.w, "<%s %s>", obj.ClassName(), s)
} else {
fmt.Fprintf(ctx.w, "<%s>", obj.ClassName())
}
}
}
func (ctx ppctx) fields(obj *goja.Object) []string {
var (
vals, methods []string
seen = make(map[string]bool)
)
add := func(k string) {
if seen[k] || boringKeys[k] || strings.HasPrefix(k, "_") {
return
}
seen[k] = true
key := SafeGet(obj, k)
if key == nil {
// The value corresponding to that key could not be found
// (typically because it is backed by an RPC call that is
// not supported by this instance. Add it to the list of
// values so that it appears as `undefined` to the user.
vals = append(vals, k)
} else {
if _, callable := goja.AssertFunction(key); callable {
methods = append(methods, k)
} else {
vals = append(vals, k)
}
}
}
iterOwnAndConstructorKeys(ctx.vm, obj, add)
sort.Strings(vals)
sort.Strings(methods)
return append(vals, methods...)
}
func iterOwnAndConstructorKeys(vm *goja.Runtime, obj *goja.Object, f func(string)) {
seen := make(map[string]bool)
iterOwnKeys(vm, obj, func(prop string) {
seen[prop] = true
f(prop)
})
if cp := constructorPrototype(vm, obj); cp != nil {
iterOwnKeys(vm, cp, func(prop string) {
if !seen[prop] {
f(prop)
}
})
}
}
func iterOwnKeys(vm *goja.Runtime, obj *goja.Object, f func(string)) {
Object := vm.Get("Object").ToObject(vm)
getOwnPropertyNames, isFunc := goja.AssertFunction(Object.Get("getOwnPropertyNames"))
if !isFunc {
panic(vm.ToValue("Object.getOwnPropertyNames isn't a function"))
}
rv, err := getOwnPropertyNames(goja.Null(), obj)
if err != nil {
panic(vm.ToValue(fmt.Sprintf("Error getting object properties: %v", err)))
}
gv := rv.Export()
switch gv := gv.(type) {
case []interface{}:
for _, v := range gv {
f(v.(string))
}
case []string:
for _, v := range gv {
f(v)
}
default:
panic(fmt.Errorf("Object.getOwnPropertyNames returned unexpected type %T", gv))
}
}
func (ctx ppctx) isBigNumber(v *goja.Object) bool {
// Handle numbers with custom constructor.
if obj := v.Get("constructor").ToObject(ctx.vm); obj != nil {
if strings.HasPrefix(toString(obj), "function BigNumber") {
return true
}
}
// Handle default constructor.
BigNumber := ctx.vm.Get("BigNumber").ToObject(ctx.vm)
if BigNumber == nil {
return false
}
prototype := BigNumber.Get("prototype").ToObject(ctx.vm)
isPrototypeOf, callable := goja.AssertFunction(prototype.Get("isPrototypeOf"))
if !callable {
return false
}
bv, _ := isPrototypeOf(prototype, v)
return bv.ToBoolean()
}
func toString(obj *goja.Object) string {
return obj.ToString().String()
}
func constructorPrototype(vm *goja.Runtime, obj *goja.Object) *goja.Object {
if v := obj.Get("constructor"); v != nil {
if v := v.ToObject(vm).Get("prototype"); v != nil {
return v.ToObject(vm)
}
}
return nil
}

View file

@ -1,35 +0,0 @@
// This file originates from Docker/Moby,
// https://github.com/moby/moby/blob/master/pkg/reexec/reexec.go
// Licensed under Apache License 2.0: https://github.com/moby/moby/blob/master/LICENSE
// Copyright 2013-2018 Docker, Inc.
//
// Package reexec facilitates the busybox style reexec of the docker binary that
// we require because of the forking limitations of using Go. Handlers can be
// registered with a name and the argv 0 of the exec of the binary will be used
// to find and execute custom init paths.
package reexec
import (
"fmt"
"os"
)
var registeredInitializers = make(map[string]func())
// Register adds an initialization func under the specified name
func Register(name string, initializer func()) {
if _, exists := registeredInitializers[name]; exists {
panic(fmt.Sprintf("reexec func already registered under name %q", name))
}
registeredInitializers[name] = initializer
}
// Init is called as the first part of the exec process and returns true if an
// initialization function was called.
func Init() bool {
if initializer, ok := registeredInitializers[os.Args[0]]; ok {
initializer()
return true
}
return false
}

View file

@ -1,14 +0,0 @@
// This file originates from Docker/Moby,
// https://github.com/moby/moby/blob/master/pkg/reexec/
// Licensed under Apache License 2.0: https://github.com/moby/moby/blob/master/LICENSE
// Copyright 2013-2018 Docker, Inc.
//go:build linux
package reexec
// Self returns the path to the current process's binary.
// Returns "/proc/self/exe".
func Self() string {
return "/proc/self/exe"
}

View file

@ -1,32 +0,0 @@
// This file originates from Docker/Moby,
// https://github.com/moby/moby/blob/master/pkg/reexec/
// Licensed under Apache License 2.0: https://github.com/moby/moby/blob/master/LICENSE
// Copyright 2013-2018 Docker, Inc.
//go:build !linux
package reexec
import (
"os"
"os/exec"
"path/filepath"
)
// Self returns the path to the current process's binary.
// Uses os.Args[0].
func Self() string {
name := os.Args[0]
if filepath.Base(name) == name {
if lp, err := exec.LookPath(name); err == nil {
return lp
}
}
// handle conversion of relative paths to absolute
if absName, err := filepath.Abs(name); err == nil {
return absName
}
// if we couldn't get absolute name, return original
// (NOTE: Go only errors on Abs() if os.Getwd fails)
return name
}

View file

@ -1,85 +0,0 @@
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package shutdowncheck
import (
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/rawdb"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/log"
)
// ShutdownTracker is a service that reports previous unclean shutdowns
// upon start. It needs to be started after a successful start-up and stopped
// after a successful shutdown, just before the db is closed.
type ShutdownTracker struct {
db ethdb.Database
stopCh chan struct{}
}
// NewShutdownTracker creates a new ShutdownTracker instance and has
// no other side-effect.
func NewShutdownTracker(db ethdb.Database) *ShutdownTracker {
return &ShutdownTracker{
db: db,
stopCh: make(chan struct{}),
}
}
// MarkStartup is to be called in the beginning when the node starts. It will:
// - Push a new startup marker to the db
// - Report previous unclean shutdowns
func (t *ShutdownTracker) MarkStartup() {
if uncleanShutdowns, discards, err := rawdb.PushUncleanShutdownMarker(t.db); err != nil {
log.Error("Could not update unclean-shutdown-marker list", "error", err)
} else {
if discards > 0 {
log.Warn("Old unclean shutdowns found", "count", discards)
}
for _, tstamp := range uncleanShutdowns {
t := time.Unix(int64(tstamp), 0)
log.Warn("Unclean shutdown detected", "booted", t,
"age", common.PrettyAge(t))
}
}
}
// Start runs an event loop that updates the current marker's timestamp every 5 minutes.
func (t *ShutdownTracker) Start() {
go func() {
ticker := time.NewTicker(5 * time.Minute)
defer ticker.Stop()
for {
select {
case <-ticker.C:
rawdb.UpdateUncleanShutdownMarker(t.db)
case <-t.stopCh:
return
}
}
}()
}
// Stop will stop the update loop and clear the current marker.
func (t *ShutdownTracker) Stop() {
// Stop update loop.
t.stopCh <- struct{}{}
// Clear last marker.
rawdb.PopUncleanShutdownMarker(t.db)
}

View file

@ -1,64 +0,0 @@
// Copyright 2021 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package syncx contains exotic synchronization primitives.
package syncx
// ClosableMutex is a mutex that can also be closed.
// Once closed, it can never be taken again.
type ClosableMutex struct {
ch chan struct{}
}
func NewClosableMutex() *ClosableMutex {
ch := make(chan struct{}, 1)
ch <- struct{}{}
return &ClosableMutex{ch}
}
// TryLock attempts to lock cm.
// If the mutex is closed, TryLock returns false.
func (cm *ClosableMutex) TryLock() bool {
_, ok := <-cm.ch
return ok
}
// MustLock locks cm.
// If the mutex is closed, MustLock panics.
func (cm *ClosableMutex) MustLock() {
_, ok := <-cm.ch
if !ok {
panic("mutex closed")
}
}
// Unlock unlocks cm.
func (cm *ClosableMutex) Unlock() {
select {
case cm.ch <- struct{}{}:
default:
panic("Unlock of already-unlocked ClosableMutex")
}
}
// Close locks the mutex, then closes it.
func (cm *ClosableMutex) Close() {
_, ok := <-cm.ch
if !ok {
panic("Close of already-closed ClosableMutex")
}
close(cm.ch)
}

View file

@ -1,203 +0,0 @@
// Copyright 2019 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package testlog provides a log handler for unit tests.
package testlog
import (
"bytes"
"context"
"fmt"
"sync"
"testing"
"github.com/ethereum/go-ethereum/log"
"golang.org/x/exp/slog"
)
const (
termTimeFormat = "01-02|15:04:05.000"
)
// logger implements log.Logger such that all output goes to the unit test log via
// t.Logf(). All methods in between logger.Trace, logger.Debug, etc. are marked as test
// helpers, so the file and line number in unit test output correspond to the call site
// which emitted the log message.
type logger struct {
t *testing.T
l log.Logger
mu *sync.Mutex
h *bufHandler
}
type bufHandler struct {
buf []slog.Record
attrs []slog.Attr
level slog.Level
}
func (h *bufHandler) Handle(_ context.Context, r slog.Record) error {
h.buf = append(h.buf, r)
return nil
}
func (h *bufHandler) Enabled(_ context.Context, lvl slog.Level) bool {
return lvl <= h.level
}
func (h *bufHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
records := make([]slog.Record, len(h.buf))
copy(records[:], h.buf[:])
return &bufHandler{
records,
append(h.attrs, attrs...),
h.level,
}
}
func (h *bufHandler) WithGroup(_ string) slog.Handler {
panic("not implemented")
}
// Logger returns a logger which logs to the unit test log of t.
func Logger(t *testing.T, level slog.Level) log.Logger {
handler := bufHandler{
[]slog.Record{},
[]slog.Attr{},
level,
}
return &logger{
t: t,
l: log.NewLogger(&handler),
mu: new(sync.Mutex),
h: &handler,
}
}
// LoggerWithHandler returns
func LoggerWithHandler(t *testing.T, handler slog.Handler) log.Logger {
var bh bufHandler
return &logger{
t: t,
l: log.NewLogger(handler),
mu: new(sync.Mutex),
h: &bh,
}
}
func (l *logger) Write(level slog.Level, msg string, ctx ...interface{}) {}
func (l *logger) Enabled(ctx context.Context, level slog.Level) bool {
return l.l.Enabled(ctx, level)
}
func (l *logger) Trace(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Trace(msg, ctx...)
l.flush()
}
func (l *logger) Log(level slog.Level, msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Log(level, msg, ctx...)
l.flush()
}
func (l *logger) Debug(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Debug(msg, ctx...)
l.flush()
}
func (l *logger) Info(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Info(msg, ctx...)
l.flush()
}
func (l *logger) Warn(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Warn(msg, ctx...)
l.flush()
}
func (l *logger) Error(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Error(msg, ctx...)
l.flush()
}
func (l *logger) Crit(msg string, ctx ...interface{}) {
l.t.Helper()
l.mu.Lock()
defer l.mu.Unlock()
l.l.Crit(msg, ctx...)
l.flush()
}
func (l *logger) With(ctx ...interface{}) log.Logger {
return &logger{l.t, l.l.With(ctx...), l.mu, l.h}
}
func (l *logger) New(ctx ...interface{}) log.Logger {
return l.With(ctx...)
}
// terminalFormat formats a message similarly to the NewTerminalHandler in the log package.
// The difference is that terminalFormat does not escape messages/attributes and does not pad attributes.
func (h *bufHandler) terminalFormat(r slog.Record) string {
buf := &bytes.Buffer{}
lvl := log.LevelAlignedString(r.Level)
attrs := []slog.Attr{}
r.Attrs(func(attr slog.Attr) bool {
attrs = append(attrs, attr)
return true
})
attrs = append(h.attrs, attrs...)
fmt.Fprintf(buf, "%s[%s] %s ", lvl, r.Time.Format(termTimeFormat), r.Message)
if length := len(r.Message); length < 40 {
buf.Write(bytes.Repeat([]byte{' '}, 40-length))
}
for _, attr := range attrs {
fmt.Fprintf(buf, " %s=%s", attr.Key, string(log.FormatSlogValue(attr.Value, nil)))
}
buf.WriteByte('\n')
return buf.String()
}
// flush writes all buffered messages and clears the buffer.
func (l *logger) flush() {
l.t.Helper()
for _, r := range l.h.buf {
l.t.Logf("%s", l.h.terminalFormat(r))
}
l.h.buf = nil
}

View file

@ -1,338 +0,0 @@
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package utesting provides a standalone replacement for package testing.
//
// This package exists because package testing cannot easily be embedded into a
// standalone go program. It provides an API that mirrors the standard library
// testing API.
package utesting
import (
"bytes"
"fmt"
"io"
"regexp"
"runtime"
"sync"
"time"
)
// Test represents a single test.
type Test struct {
Name string
Fn func(*T)
}
// Result is the result of a test execution.
type Result struct {
Name string
Failed bool
Output string
Duration time.Duration
}
// MatchTests returns the tests whose name matches a regular expression.
func MatchTests(tests []Test, expr string) []Test {
var results []Test
re, err := regexp.Compile(expr)
if err != nil {
return nil
}
for _, test := range tests {
if re.MatchString(test.Name) {
results = append(results, test)
}
}
return results
}
// RunTests executes all given tests in order and returns their results.
// If the report writer is non-nil, a test report is written to it in real time.
func RunTests(tests []Test, report io.Writer) []Result {
if report == nil {
report = io.Discard
}
results := run(tests, newConsoleOutput(report))
fails := CountFailures(results)
fmt.Fprintf(report, "%v/%v tests passed.\n", len(tests)-fails, len(tests))
return results
}
// RunTAP runs the given tests and writes Test Anything Protocol output
// to the report writer.
func RunTAP(tests []Test, report io.Writer) []Result {
return run(tests, newTAP(report, len(tests)))
}
func run(tests []Test, output testOutput) []Result {
var results = make([]Result, len(tests))
for i, test := range tests {
buffer := new(bytes.Buffer)
logOutput := io.MultiWriter(buffer, output)
output.testStart(test.Name)
start := time.Now()
results[i].Name = test.Name
results[i].Failed = runTest(test, logOutput)
results[i].Duration = time.Since(start)
results[i].Output = buffer.String()
output.testResult(results[i])
}
return results
}
// testOutput is implemented by output formats.
type testOutput interface {
testStart(name string)
Write([]byte) (int, error)
testResult(Result)
}
// consoleOutput prints test results similarly to go test.
type consoleOutput struct {
out io.Writer
indented *indentWriter
curTest string
wroteHeader bool
}
func newConsoleOutput(w io.Writer) *consoleOutput {
return &consoleOutput{
out: w,
indented: newIndentWriter(" ", w),
}
}
// testStart signals the start of a new test.
func (c *consoleOutput) testStart(name string) {
c.curTest = name
c.wroteHeader = false
}
// Write handles test log output.
func (c *consoleOutput) Write(b []byte) (int, error) {
if !c.wroteHeader {
// This is the first output line from the test. Print a "-- RUN" header.
fmt.Fprintln(c.out, "-- RUN", c.curTest)
c.wroteHeader = true
}
return c.indented.Write(b)
}
// testResult prints the final test result line.
func (c *consoleOutput) testResult(r Result) {
c.indented.flush()
pd := r.Duration.Truncate(100 * time.Microsecond)
if r.Failed {
fmt.Fprintf(c.out, "-- FAIL %s (%v)\n", r.Name, pd)
} else {
fmt.Fprintf(c.out, "-- OK %s (%v)\n", r.Name, pd)
}
}
// tapOutput produces Test Anything Protocol v13 output.
type tapOutput struct {
out io.Writer
indented *indentWriter
counter int
}
func newTAP(out io.Writer, numTests int) *tapOutput {
fmt.Fprintf(out, "1..%d\n", numTests)
return &tapOutput{
out: out,
indented: newIndentWriter("# ", out),
}
}
func (t *tapOutput) testStart(name string) {
t.counter++
}
// Write does nothing for TAP because there is no real-time output of test logs.
func (t *tapOutput) Write(b []byte) (int, error) {
return len(b), nil
}
func (t *tapOutput) testResult(r Result) {
status := "ok"
if r.Failed {
status = "not ok"
}
fmt.Fprintln(t.out, status, t.counter, r.Name)
t.indented.Write([]byte(r.Output))
t.indented.flush()
}
// indentWriter indents all written text.
type indentWriter struct {
out io.Writer
indent string
inLine bool
}
func newIndentWriter(indent string, out io.Writer) *indentWriter {
return &indentWriter{out: out, indent: indent}
}
func (w *indentWriter) Write(b []byte) (n int, err error) {
for len(b) > 0 {
if !w.inLine {
if _, err = io.WriteString(w.out, w.indent); err != nil {
return n, err
}
w.inLine = true
}
end := bytes.IndexByte(b, '\n')
if end == -1 {
nn, err := w.out.Write(b)
n += nn
return n, err
}
line := b[:end+1]
nn, err := w.out.Write(line)
n += nn
if err != nil {
return n, err
}
b = b[end+1:]
w.inLine = false
}
return n, err
}
// flush ensures the current line is terminated.
func (w *indentWriter) flush() {
if w.inLine {
fmt.Println(w.out)
w.inLine = false
}
}
// CountFailures returns the number of failed tests in the result slice.
func CountFailures(rr []Result) int {
count := 0
for _, r := range rr {
if r.Failed {
count++
}
}
return count
}
// Run executes a single test.
func Run(test Test) (bool, string) {
output := new(bytes.Buffer)
failed := runTest(test, output)
return failed, output.String()
}
func runTest(test Test, output io.Writer) bool {
t := &T{output: output}
done := make(chan struct{})
go func() {
defer close(done)
defer func() {
if err := recover(); err != nil {
buf := make([]byte, 4096)
i := runtime.Stack(buf, false)
t.Logf("panic: %v\n\n%s", err, buf[:i])
t.Fail()
}
}()
test.Fn(t)
}()
<-done
return t.failed
}
// T is the value given to the test function. The test can signal failures
// and log output by calling methods on this object.
type T struct {
mu sync.Mutex
failed bool
output io.Writer
}
// Helper exists for compatibility with testing.T.
func (t *T) Helper() {}
// FailNow marks the test as having failed and stops its execution by calling
// runtime.Goexit (which then runs all deferred calls in the current goroutine).
func (t *T) FailNow() {
t.Fail()
runtime.Goexit()
}
// Fail marks the test as having failed but continues execution.
func (t *T) Fail() {
t.mu.Lock()
defer t.mu.Unlock()
t.failed = true
}
// Failed reports whether the test has failed.
func (t *T) Failed() bool {
t.mu.Lock()
defer t.mu.Unlock()
return t.failed
}
// Log formats its arguments using default formatting, analogous to Println, and records
// the text in the error log.
func (t *T) Log(vs ...interface{}) {
t.mu.Lock()
defer t.mu.Unlock()
fmt.Fprintln(t.output, vs...)
}
// Logf formats its arguments according to the format, analogous to Printf, and records
// the text in the error log. A final newline is added if not provided.
func (t *T) Logf(format string, vs ...interface{}) {
t.mu.Lock()
defer t.mu.Unlock()
if len(format) == 0 || format[len(format)-1] != '\n' {
format += "\n"
}
fmt.Fprintf(t.output, format, vs...)
}
// Error is equivalent to Log followed by Fail.
func (t *T) Error(vs ...interface{}) {
t.Log(vs...)
t.Fail()
}
// Errorf is equivalent to Logf followed by Fail.
func (t *T) Errorf(format string, vs ...interface{}) {
t.Logf(format, vs...)
t.Fail()
}
// Fatal is equivalent to Log followed by FailNow.
func (t *T) Fatal(vs ...interface{}) {
t.Log(vs...)
t.FailNow()
}
// Fatalf is equivalent to Logf followed by FailNow.
func (t *T) Fatalf(format string, vs ...interface{}) {
t.Logf(format, vs...)
t.FailNow()
}

View file

@ -1,139 +0,0 @@
// Copyright 2020 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package utesting
import (
"bytes"
"regexp"
"strings"
"testing"
)
func TestTest(t *testing.T) {
tests := []Test{
{
Name: "successful test",
Fn: func(t *T) {},
},
{
Name: "failing test",
Fn: func(t *T) {
t.Log("output")
t.Error("failed")
},
},
{
Name: "panicking test",
Fn: func(t *T) {
panic("oh no")
},
},
}
results := RunTests(tests, nil)
if results[0].Failed || results[0].Output != "" {
t.Fatalf("wrong result for successful test: %#v", results[0])
}
if !results[1].Failed || results[1].Output != "output\nfailed\n" {
t.Fatalf("wrong result for failing test: %#v", results[1])
}
if !results[2].Failed || !strings.HasPrefix(results[2].Output, "panic: oh no\n") {
t.Fatalf("wrong result for panicking test: %#v", results[2])
}
}
var outputTests = []Test{
{
Name: "TestWithLogs",
Fn: func(t *T) {
t.Log("output line 1")
t.Log("output line 2\noutput line 3")
},
},
{
Name: "TestNoLogs",
Fn: func(t *T) {},
},
{
Name: "FailWithLogs",
Fn: func(t *T) {
t.Log("output line 1")
t.Error("failed 1")
},
},
{
Name: "FailMessage",
Fn: func(t *T) {
t.Error("failed 2")
},
},
{
Name: "FailNoOutput",
Fn: func(t *T) {
t.Fail()
},
},
}
func TestOutput(t *testing.T) {
var buf bytes.Buffer
RunTests(outputTests, &buf)
want := regexp.MustCompile(`
^-- RUN TestWithLogs
output line 1
output line 2
output line 3
-- OK TestWithLogs \([^)]+\)
-- OK TestNoLogs \([^)]+\)
-- RUN FailWithLogs
output line 1
failed 1
-- FAIL FailWithLogs \([^)]+\)
-- RUN FailMessage
failed 2
-- FAIL FailMessage \([^)]+\)
-- FAIL FailNoOutput \([^)]+\)
2/5 tests passed.
$`[1:])
if !want.MatchString(buf.String()) {
t.Fatalf("output does not match: %q", buf.String())
}
}
func TestOutputTAP(t *testing.T) {
var buf bytes.Buffer
RunTAP(outputTests, &buf)
want := `
1..5
ok 1 TestWithLogs
# output line 1
# output line 2
# output line 3
ok 2 TestNoLogs
not ok 3 FailWithLogs
# output line 1
# failed 1
not ok 4 FailMessage
# failed 2
not ok 5 FailNoOutput
`
if buf.String() != want[1:] {
t.Fatalf("output does not match: %q", buf.String())
}
}

View file

@ -1,52 +0,0 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
package version
import (
"runtime/debug"
"time"
)
// In go 1.18 and beyond, the go tool embeds VCS information into the build.
const (
govcsTimeLayout = "2006-01-02T15:04:05Z"
ourTimeLayout = "20060102"
)
// buildInfoVCS returns VCS information of the build.
func buildInfoVCS(info *debug.BuildInfo) (s VCSInfo, ok bool) {
for _, v := range info.Settings {
switch v.Key {
case "vcs.revision":
s.Commit = v.Value
case "vcs.modified":
if v.Value == "true" {
s.Dirty = true
}
case "vcs.time":
t, err := time.Parse(govcsTimeLayout, v.Value)
if err == nil {
s.Date = t.Format(ourTimeLayout)
}
}
}
if s.Commit != "" && s.Date != "" {
ok = true
}
return
}

View file

@ -1,141 +0,0 @@
// Copyright 2022 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package version implements reading of build version information.
package version
import (
"fmt"
"runtime"
"runtime/debug"
"strings"
"github.com/ethereum/go-ethereum/params"
)
const ourPath = "github.com/ethereum/go-ethereum" // Path to our module
// These variables are set at build-time by the linker when the build is
// done by build/ci.go.
var gitCommit, gitDate string
// VCSInfo represents the git repository state.
type VCSInfo struct {
Commit string // head commit hash
Date string // commit time in YYYYMMDD format
Dirty bool
}
// VCS returns version control information of the current executable.
func VCS() (VCSInfo, bool) {
if gitCommit != "" {
// Use information set by the build script if present.
return VCSInfo{Commit: gitCommit, Date: gitDate}, true
}
if buildInfo, ok := debug.ReadBuildInfo(); ok {
if buildInfo.Main.Path == ourPath {
return buildInfoVCS(buildInfo)
}
}
return VCSInfo{}, false
}
// ClientName creates a software name/version identifier according to common
// conventions in the Ethereum p2p network.
func ClientName(clientIdentifier string) string {
git, _ := VCS()
return fmt.Sprintf("%s/v%v/%v-%v/%v",
strings.Title(clientIdentifier),
params.VersionWithCommit(git.Commit, git.Date),
runtime.GOOS, runtime.GOARCH,
runtime.Version(),
)
}
// runtimeInfo returns build and platform information about the current binary.
//
// If the package that is currently executing is a prefixed by our go-ethereum
// module path, it will print out commit and date VCS information. Otherwise,
// it will assume it's imported by a third-party and will return the imported
// version and whether it was replaced by another module.
func Info() (version, vcs string) {
version = params.VersionWithMeta
buildInfo, ok := debug.ReadBuildInfo()
if !ok {
return version, ""
}
version = versionInfo(buildInfo)
if status, ok := VCS(); ok {
modified := ""
if status.Dirty {
modified = " (dirty)"
}
commit := status.Commit
if len(commit) > 8 {
commit = commit[:8]
}
vcs = commit + "-" + status.Date + modified
}
return version, vcs
}
// versionInfo returns version information for the currently executing
// implementation.
//
// Depending on how the code is instantiated, it returns different amounts of
// information. If it is unable to determine which module is related to our
// package it falls back to the hardcoded values in the params package.
func versionInfo(info *debug.BuildInfo) string {
// If the main package is from our repo, prefix version with "geth".
if strings.HasPrefix(info.Path, ourPath) {
return fmt.Sprintf("geth %s", info.Main.Version)
}
// Not our main package, so explicitly print out the module path and
// version.
var version string
if info.Main.Path != "" && info.Main.Version != "" {
// These can be empty when invoked with "go run".
version = fmt.Sprintf("%s@%s ", info.Main.Path, info.Main.Version)
}
mod := findModule(info, ourPath)
if mod == nil {
// If our module path wasn't imported, it's unclear which
// version of our code they are running. Fallback to hardcoded
// version.
return version + fmt.Sprintf("geth %s", params.VersionWithMeta)
}
// Our package is a dependency for the main module. Return path and
// version data for both.
version += fmt.Sprintf("%s@%s", mod.Path, mod.Version)
if mod.Replace != nil {
// If our package was replaced by something else, also note that.
version += fmt.Sprintf(" (replaced by %s@%s)", mod.Replace.Path, mod.Replace.Version)
}
return version
}
// findModule returns the module at path.
func findModule(info *debug.BuildInfo, path string) *debug.Module {
if info.Path == ourPath {
return &info.Main
}
for _, mod := range info.Deps {
if mod.Path == path {
return mod
}
}
return nil
}

View file

@ -1,913 +0,0 @@
// Copyright 2015 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package web3ext contains geth specific web3.js extensions.
package web3ext
var Modules = map[string]string{
"admin": AdminJs,
"clique": CliqueJs,
"ethash": EthashJs,
"debug": DebugJs,
"eth": EthJs,
"miner": MinerJs,
"net": NetJs,
"personal": PersonalJs,
"rpc": RpcJs,
"txpool": TxpoolJs,
"les": LESJs,
"vflux": VfluxJs,
"dev": DevJs,
}
const CliqueJs = `
web3._extend({
property: 'clique',
methods: [
new web3._extend.Method({
name: 'getSnapshot',
call: 'clique_getSnapshot',
params: 1,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
}),
new web3._extend.Method({
name: 'getSnapshotAtHash',
call: 'clique_getSnapshotAtHash',
params: 1
}),
new web3._extend.Method({
name: 'getSigners',
call: 'clique_getSigners',
params: 1,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
}),
new web3._extend.Method({
name: 'getSignersAtHash',
call: 'clique_getSignersAtHash',
params: 1
}),
new web3._extend.Method({
name: 'propose',
call: 'clique_propose',
params: 2
}),
new web3._extend.Method({
name: 'discard',
call: 'clique_discard',
params: 1
}),
new web3._extend.Method({
name: 'status',
call: 'clique_status',
params: 0
}),
new web3._extend.Method({
name: 'getSigner',
call: 'clique_getSigner',
params: 1,
inputFormatter: [null]
}),
],
properties: [
new web3._extend.Property({
name: 'proposals',
getter: 'clique_proposals'
}),
]
});
`
const EthashJs = `
web3._extend({
property: 'ethash',
methods: [
new web3._extend.Method({
name: 'getWork',
call: 'ethash_getWork',
params: 0
}),
new web3._extend.Method({
name: 'getHashrate',
call: 'ethash_getHashrate',
params: 0
}),
new web3._extend.Method({
name: 'submitWork',
call: 'ethash_submitWork',
params: 3,
}),
new web3._extend.Method({
name: 'submitHashrate',
call: 'ethash_submitHashrate',
params: 2,
}),
]
});
`
const AdminJs = `
web3._extend({
property: 'admin',
methods: [
new web3._extend.Method({
name: 'addPeer',
call: 'admin_addPeer',
params: 1
}),
new web3._extend.Method({
name: 'removePeer',
call: 'admin_removePeer',
params: 1
}),
new web3._extend.Method({
name: 'addTrustedPeer',
call: 'admin_addTrustedPeer',
params: 1
}),
new web3._extend.Method({
name: 'removeTrustedPeer',
call: 'admin_removeTrustedPeer',
params: 1
}),
new web3._extend.Method({
name: 'exportChain',
call: 'admin_exportChain',
params: 3,
inputFormatter: [null, null, null]
}),
new web3._extend.Method({
name: 'importChain',
call: 'admin_importChain',
params: 1
}),
new web3._extend.Method({
name: 'sleepBlocks',
call: 'admin_sleepBlocks',
params: 2
}),
new web3._extend.Method({
name: 'startHTTP',
call: 'admin_startHTTP',
params: 5,
inputFormatter: [null, null, null, null, null]
}),
new web3._extend.Method({
name: 'stopHTTP',
call: 'admin_stopHTTP'
}),
// This method is deprecated.
new web3._extend.Method({
name: 'startRPC',
call: 'admin_startRPC',
params: 5,
inputFormatter: [null, null, null, null, null]
}),
// This method is deprecated.
new web3._extend.Method({
name: 'stopRPC',
call: 'admin_stopRPC'
}),
new web3._extend.Method({
name: 'startWS',
call: 'admin_startWS',
params: 4,
inputFormatter: [null, null, null, null]
}),
new web3._extend.Method({
name: 'stopWS',
call: 'admin_stopWS'
}),
],
properties: [
new web3._extend.Property({
name: 'nodeInfo',
getter: 'admin_nodeInfo'
}),
new web3._extend.Property({
name: 'peers',
getter: 'admin_peers'
}),
new web3._extend.Property({
name: 'datadir',
getter: 'admin_datadir'
}),
]
});
`
const DebugJs = `
web3._extend({
property: 'debug',
methods: [
new web3._extend.Method({
name: 'accountRange',
call: 'debug_accountRange',
params: 6,
inputFormatter: [web3._extend.formatters.inputDefaultBlockNumberFormatter, null, null, null, null, null],
}),
new web3._extend.Method({
name: 'printBlock',
call: 'debug_printBlock',
params: 1,
outputFormatter: console.log
}),
new web3._extend.Method({
name: 'getRawHeader',
call: 'debug_getRawHeader',
params: 1
}),
new web3._extend.Method({
name: 'getRawBlock',
call: 'debug_getRawBlock',
params: 1
}),
new web3._extend.Method({
name: 'getRawReceipts',
call: 'debug_getRawReceipts',
params: 1
}),
new web3._extend.Method({
name: 'getRawTransaction',
call: 'debug_getRawTransaction',
params: 1
}),
new web3._extend.Method({
name: 'setHead',
call: 'debug_setHead',
params: 1
}),
new web3._extend.Method({
name: 'seedHash',
call: 'debug_seedHash',
params: 1
}),
new web3._extend.Method({
name: 'dumpBlock',
call: 'debug_dumpBlock',
params: 1,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
}),
new web3._extend.Method({
name: 'chaindbProperty',
call: 'debug_chaindbProperty',
params: 1,
outputFormatter: console.log
}),
new web3._extend.Method({
name: 'chaindbCompact',
call: 'debug_chaindbCompact',
}),
new web3._extend.Method({
name: 'verbosity',
call: 'debug_verbosity',
params: 1
}),
new web3._extend.Method({
name: 'vmodule',
call: 'debug_vmodule',
params: 1
}),
new web3._extend.Method({
name: 'backtraceAt',
call: 'debug_backtraceAt',
params: 1,
}),
new web3._extend.Method({
name: 'stacks',
call: 'debug_stacks',
params: 1,
inputFormatter: [null],
outputFormatter: console.log
}),
new web3._extend.Method({
name: 'freeOSMemory',
call: 'debug_freeOSMemory',
params: 0,
}),
new web3._extend.Method({
name: 'setGCPercent',
call: 'debug_setGCPercent',
params: 1,
}),
new web3._extend.Method({
name: 'memStats',
call: 'debug_memStats',
params: 0,
}),
new web3._extend.Method({
name: 'gcStats',
call: 'debug_gcStats',
params: 0,
}),
new web3._extend.Method({
name: 'cpuProfile',
call: 'debug_cpuProfile',
params: 2
}),
new web3._extend.Method({
name: 'startCPUProfile',
call: 'debug_startCPUProfile',
params: 1
}),
new web3._extend.Method({
name: 'stopCPUProfile',
call: 'debug_stopCPUProfile',
params: 0
}),
new web3._extend.Method({
name: 'goTrace',
call: 'debug_goTrace',
params: 2
}),
new web3._extend.Method({
name: 'startGoTrace',
call: 'debug_startGoTrace',
params: 1
}),
new web3._extend.Method({
name: 'stopGoTrace',
call: 'debug_stopGoTrace',
params: 0
}),
new web3._extend.Method({
name: 'blockProfile',
call: 'debug_blockProfile',
params: 2
}),
new web3._extend.Method({
name: 'setBlockProfileRate',
call: 'debug_setBlockProfileRate',
params: 1
}),
new web3._extend.Method({
name: 'writeBlockProfile',
call: 'debug_writeBlockProfile',
params: 1
}),
new web3._extend.Method({
name: 'mutexProfile',
call: 'debug_mutexProfile',
params: 2
}),
new web3._extend.Method({
name: 'setMutexProfileFraction',
call: 'debug_setMutexProfileFraction',
params: 1
}),
new web3._extend.Method({
name: 'writeMutexProfile',
call: 'debug_writeMutexProfile',
params: 1
}),
new web3._extend.Method({
name: 'writeMemProfile',
call: 'debug_writeMemProfile',
params: 1
}),
new web3._extend.Method({
name: 'traceBlock',
call: 'debug_traceBlock',
params: 2,
inputFormatter: [null, null]
}),
new web3._extend.Method({
name: 'traceBlockFromFile',
call: 'debug_traceBlockFromFile',
params: 2,
inputFormatter: [null, null]
}),
new web3._extend.Method({
name: 'traceBadBlock',
call: 'debug_traceBadBlock',
params: 1,
inputFormatter: [null]
}),
new web3._extend.Method({
name: 'standardTraceBadBlockToFile',
call: 'debug_standardTraceBadBlockToFile',
params: 2,
inputFormatter: [null, null]
}),
new web3._extend.Method({
name: 'intermediateRoots',
call: 'debug_intermediateRoots',
params: 2,
inputFormatter: [null, null]
}),
new web3._extend.Method({
name: 'standardTraceBlockToFile',
call: 'debug_standardTraceBlockToFile',
params: 2,
inputFormatter: [null, null]
}),
new web3._extend.Method({
name: 'traceBlockByNumber',
call: 'debug_traceBlockByNumber',
params: 2,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, null]
}),
new web3._extend.Method({
name: 'traceBlockByHash',
call: 'debug_traceBlockByHash',
params: 2,
inputFormatter: [null, null]
}),
new web3._extend.Method({
name: 'traceTransaction',
call: 'debug_traceTransaction',
params: 2,
inputFormatter: [null, null]
}),
new web3._extend.Method({
name: 'traceCall',
call: 'debug_traceCall',
params: 3,
inputFormatter: [null, null, null]
}),
new web3._extend.Method({
name: 'preimage',
call: 'debug_preimage',
params: 1,
inputFormatter: [null]
}),
new web3._extend.Method({
name: 'getBadBlocks',
call: 'debug_getBadBlocks',
params: 0,
}),
new web3._extend.Method({
name: 'storageRangeAt',
call: 'debug_storageRangeAt',
params: 5,
}),
new web3._extend.Method({
name: 'getModifiedAccountsByNumber',
call: 'debug_getModifiedAccountsByNumber',
params: 2,
inputFormatter: [null, null],
}),
new web3._extend.Method({
name: 'getModifiedAccountsByHash',
call: 'debug_getModifiedAccountsByHash',
params: 2,
inputFormatter:[null, null],
}),
new web3._extend.Method({
name: 'freezeClient',
call: 'debug_freezeClient',
params: 1,
}),
new web3._extend.Method({
name: 'getAccessibleState',
call: 'debug_getAccessibleState',
params: 2,
inputFormatter:[web3._extend.formatters.inputBlockNumberFormatter, web3._extend.formatters.inputBlockNumberFormatter],
}),
new web3._extend.Method({
name: 'dbGet',
call: 'debug_dbGet',
params: 1
}),
new web3._extend.Method({
name: 'dbAncient',
call: 'debug_dbAncient',
params: 2
}),
new web3._extend.Method({
name: 'dbAncients',
call: 'debug_dbAncients',
params: 0
}),
new web3._extend.Method({
name: 'setTrieFlushInterval',
call: 'debug_setTrieFlushInterval',
params: 1
}),
new web3._extend.Method({
name: 'getTrieFlushInterval',
call: 'debug_getTrieFlushInterval',
params: 0
}),
],
properties: []
});
`
const EthJs = `
web3._extend({
property: 'eth',
methods: [
new web3._extend.Method({
name: 'chainId',
call: 'eth_chainId',
params: 0
}),
new web3._extend.Method({
name: 'sign',
call: 'eth_sign',
params: 2,
inputFormatter: [web3._extend.formatters.inputAddressFormatter, null]
}),
new web3._extend.Method({
name: 'resend',
call: 'eth_resend',
params: 3,
inputFormatter: [web3._extend.formatters.inputTransactionFormatter, web3._extend.utils.fromDecimal, web3._extend.utils.fromDecimal]
}),
new web3._extend.Method({
name: 'signTransaction',
call: 'eth_signTransaction',
params: 1,
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
}),
new web3._extend.Method({
name: 'estimateGas',
call: 'eth_estimateGas',
params: 3,
inputFormatter: [web3._extend.formatters.inputCallFormatter, web3._extend.formatters.inputBlockNumberFormatter, null],
outputFormatter: web3._extend.utils.toDecimal
}),
new web3._extend.Method({
name: 'submitTransaction',
call: 'eth_submitTransaction',
params: 1,
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
}),
new web3._extend.Method({
name: 'fillTransaction',
call: 'eth_fillTransaction',
params: 1,
inputFormatter: [web3._extend.formatters.inputTransactionFormatter]
}),
new web3._extend.Method({
name: 'getHeaderByNumber',
call: 'eth_getHeaderByNumber',
params: 1,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter]
}),
new web3._extend.Method({
name: 'getHeaderByHash',
call: 'eth_getHeaderByHash',
params: 1
}),
new web3._extend.Method({
name: 'getBlockByNumber',
call: 'eth_getBlockByNumber',
params: 2,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, function (val) { return !!val; }]
}),
new web3._extend.Method({
name: 'getBlockByHash',
call: 'eth_getBlockByHash',
params: 2,
inputFormatter: [null, function (val) { return !!val; }]
}),
new web3._extend.Method({
name: 'getRawTransaction',
call: 'eth_getRawTransactionByHash',
params: 1
}),
new web3._extend.Method({
name: 'getRawTransactionFromBlock',
call: function(args) {
return (web3._extend.utils.isString(args[0]) && args[0].indexOf('0x') === 0) ? 'eth_getRawTransactionByBlockHashAndIndex' : 'eth_getRawTransactionByBlockNumberAndIndex';
},
params: 2,
inputFormatter: [web3._extend.formatters.inputBlockNumberFormatter, web3._extend.utils.toHex]
}),
new web3._extend.Method({
name: 'getProof',
call: 'eth_getProof',
params: 3,
inputFormatter: [web3._extend.formatters.inputAddressFormatter, null, web3._extend.formatters.inputBlockNumberFormatter]
}),
new web3._extend.Method({
name: 'createAccessList',
call: 'eth_createAccessList',
params: 2,
inputFormatter: [null, web3._extend.formatters.inputBlockNumberFormatter],
}),
new web3._extend.Method({
name: 'feeHistory',
call: 'eth_feeHistory',
params: 3,
inputFormatter: [null, web3._extend.formatters.inputBlockNumberFormatter, null]
}),
new web3._extend.Method({
name: 'getLogs',
call: 'eth_getLogs',
params: 1,
}),
new web3._extend.Method({
name: 'call',
call: 'eth_call',
params: 4,
inputFormatter: [web3._extend.formatters.inputCallFormatter, web3._extend.formatters.inputDefaultBlockNumberFormatter, null, null],
}),
new web3._extend.Method({
name: 'getBlockReceipts',
call: 'eth_getBlockReceipts',
params: 1,
}),
],
properties: [
new web3._extend.Property({
name: 'pendingTransactions',
getter: 'eth_pendingTransactions',
outputFormatter: function(txs) {
var formatted = [];
for (var i = 0; i < txs.length; i++) {
formatted.push(web3._extend.formatters.outputTransactionFormatter(txs[i]));
formatted[i].blockHash = null;
}
return formatted;
}
}),
new web3._extend.Property({
name: 'maxPriorityFeePerGas',
getter: 'eth_maxPriorityFeePerGas',
outputFormatter: web3._extend.utils.toBigNumber
}),
]
});
`
const MinerJs = `
web3._extend({
property: 'miner',
methods: [
new web3._extend.Method({
name: 'start',
call: 'miner_start',
}),
new web3._extend.Method({
name: 'stop',
call: 'miner_stop'
}),
new web3._extend.Method({
name: 'setEtherbase',
call: 'miner_setEtherbase',
params: 1,
inputFormatter: [web3._extend.formatters.inputAddressFormatter]
}),
new web3._extend.Method({
name: 'setExtra',
call: 'miner_setExtra',
params: 1
}),
new web3._extend.Method({
name: 'setGasPrice',
call: 'miner_setGasPrice',
params: 1,
inputFormatter: [web3._extend.utils.fromDecimal]
}),
new web3._extend.Method({
name: 'setGasLimit',
call: 'miner_setGasLimit',
params: 1,
inputFormatter: [web3._extend.utils.fromDecimal]
}),
new web3._extend.Method({
name: 'setRecommitInterval',
call: 'miner_setRecommitInterval',
params: 1,
}),
new web3._extend.Method({
name: 'getHashrate',
call: 'miner_getHashrate'
}),
],
properties: []
});
`
const NetJs = `
web3._extend({
property: 'net',
methods: [],
properties: [
new web3._extend.Property({
name: 'version',
getter: 'net_version'
}),
]
});
`
const PersonalJs = `
web3._extend({
property: 'personal',
methods: [
new web3._extend.Method({
name: 'importRawKey',
call: 'personal_importRawKey',
params: 2
}),
new web3._extend.Method({
name: 'sign',
call: 'personal_sign',
params: 3,
inputFormatter: [null, web3._extend.formatters.inputAddressFormatter, null]
}),
new web3._extend.Method({
name: 'ecRecover',
call: 'personal_ecRecover',
params: 2
}),
new web3._extend.Method({
name: 'openWallet',
call: 'personal_openWallet',
params: 2
}),
new web3._extend.Method({
name: 'deriveAccount',
call: 'personal_deriveAccount',
params: 3
}),
new web3._extend.Method({
name: 'signTransaction',
call: 'personal_signTransaction',
params: 2,
inputFormatter: [web3._extend.formatters.inputTransactionFormatter, null]
}),
new web3._extend.Method({
name: 'unpair',
call: 'personal_unpair',
params: 2
}),
new web3._extend.Method({
name: 'initializeWallet',
call: 'personal_initializeWallet',
params: 1
})
],
properties: [
new web3._extend.Property({
name: 'listWallets',
getter: 'personal_listWallets'
}),
]
})
`
const RpcJs = `
web3._extend({
property: 'rpc',
methods: [],
properties: [
new web3._extend.Property({
name: 'modules',
getter: 'rpc_modules'
}),
]
});
`
const TxpoolJs = `
web3._extend({
property: 'txpool',
methods: [],
properties:
[
new web3._extend.Property({
name: 'content',
getter: 'txpool_content'
}),
new web3._extend.Property({
name: 'inspect',
getter: 'txpool_inspect'
}),
new web3._extend.Property({
name: 'status',
getter: 'txpool_status',
outputFormatter: function(status) {
status.pending = web3._extend.utils.toDecimal(status.pending);
status.queued = web3._extend.utils.toDecimal(status.queued);
return status;
}
}),
new web3._extend.Method({
name: 'contentFrom',
call: 'txpool_contentFrom',
params: 1,
}),
]
});
`
const LESJs = `
web3._extend({
property: 'les',
methods:
[
new web3._extend.Method({
name: 'getCheckpoint',
call: 'les_getCheckpoint',
params: 1
}),
new web3._extend.Method({
name: 'clientInfo',
call: 'les_clientInfo',
params: 1
}),
new web3._extend.Method({
name: 'priorityClientInfo',
call: 'les_priorityClientInfo',
params: 3
}),
new web3._extend.Method({
name: 'setClientParams',
call: 'les_setClientParams',
params: 2
}),
new web3._extend.Method({
name: 'setDefaultParams',
call: 'les_setDefaultParams',
params: 1
}),
new web3._extend.Method({
name: 'addBalance',
call: 'les_addBalance',
params: 2
}),
],
properties:
[
new web3._extend.Property({
name: 'latestCheckpoint',
getter: 'les_latestCheckpoint'
}),
new web3._extend.Property({
name: 'checkpointContractAddress',
getter: 'les_getCheckpointContractAddress'
}),
new web3._extend.Property({
name: 'serverInfo',
getter: 'les_serverInfo'
}),
]
});
`
const VfluxJs = `
web3._extend({
property: 'vflux',
methods:
[
new web3._extend.Method({
name: 'distribution',
call: 'vflux_distribution',
params: 2
}),
new web3._extend.Method({
name: 'timeout',
call: 'vflux_timeout',
params: 2
}),
new web3._extend.Method({
name: 'value',
call: 'vflux_value',
params: 2
}),
],
properties:
[
new web3._extend.Property({
name: 'requestStats',
getter: 'vflux_requestStats'
}),
]
});
`
const DevJs = `
web3._extend({
property: 'dev',
methods:
[
new web3._extend.Method({
name: 'addWithdrawal',
call: 'dev_addWithdrawal',
params: 1
}),
new web3._extend.Method({
name: 'setFeeRecipient',
call: 'dev_setFeeRecipient',
params: 1
}),
],
});
`