good morning!!!!

Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • github/maticnetwork/bor
  • open/bor
2 results
Show changes
Showing
with 1782 additions and 0 deletions
package cli
import (
"fmt"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
)
type AccountImportCommand struct {
*Meta
}
// Help implements the cli.Command interface
func (a *AccountImportCommand) Help() string {
return `Usage: bor account import
Import a private key into a new account.
Import an account:
$ bor account import key.json
` + a.Flags().Help()
}
func (a *AccountImportCommand) Flags() *flagset.Flagset {
return a.NewFlagSet("account import")
}
// Synopsis implements the cli.Command interface
func (a *AccountImportCommand) Synopsis() string {
return "Import a private key into a new account"
}
// Run implements the cli.Command interface
func (a *AccountImportCommand) Run(args []string) int {
flags := a.Flags()
if err := flags.Parse(args); err != nil {
a.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
a.UI.Error("Expected one argument")
return 1
}
key, err := crypto.LoadECDSA(args[0])
if err != nil {
a.UI.Error(fmt.Sprintf("Failed to load the private key '%s': %v", args[0], err))
return 1
}
keystore, err := a.GetKeystore()
if err != nil {
a.UI.Error(fmt.Sprintf("Failed to get keystore: %v", err))
return 1
}
password, err := a.AskPassword()
if err != nil {
a.UI.Error(err.Error())
return 1
}
acct, err := keystore.ImportECDSA(key, password)
if err != nil {
utils.Fatalf("Could not create the account: %v", err)
}
a.UI.Output(fmt.Sprintf("Account created: %s", acct.Address.String()))
return 0
}
package cli
import (
"fmt"
"github.com/ethereum/go-ethereum/accounts"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
)
type AccountListCommand struct {
*Meta
}
// Help implements the cli.Command interface
func (a *AccountListCommand) Help() string {
return `Usage: bor account list
List the local accounts.
` + a.Flags().Help()
}
func (a *AccountListCommand) Flags() *flagset.Flagset {
return a.NewFlagSet("account list")
}
// Synopsis implements the cli.Command interface
func (a *AccountListCommand) Synopsis() string {
return "List the local accounts"
}
// Run implements the cli.Command interface
func (a *AccountListCommand) Run(args []string) int {
flags := a.Flags()
if err := flags.Parse(args); err != nil {
a.UI.Error(err.Error())
return 1
}
keystore, err := a.GetKeystore()
if err != nil {
a.UI.Error(fmt.Sprintf("Failed to get keystore: %v", err))
return 1
}
a.UI.Output(formatAccounts(keystore.Accounts()))
return 0
}
func formatAccounts(accts []accounts.Account) string {
if len(accts) == 0 {
return "No accounts found"
}
rows := make([]string, len(accts)+1)
rows[0] = "Index|Address"
for i, d := range accts {
rows[i+1] = fmt.Sprintf("%d|%s",
i,
d.Address.String())
}
return formatList(rows)
}
package cli
import (
"fmt"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
)
type AccountNewCommand struct {
*Meta
}
// Help implements the cli.Command interface
func (a *AccountNewCommand) Help() string {
return `Usage: bor account new
Create a new local account.
` + a.Flags().Help()
}
func (a *AccountNewCommand) Flags() *flagset.Flagset {
return a.NewFlagSet("account new")
}
// Synopsis implements the cli.Command interface
func (a *AccountNewCommand) Synopsis() string {
return "Create a new local account"
}
// Run implements the cli.Command interface
func (a *AccountNewCommand) Run(args []string) int {
flags := a.Flags()
if err := flags.Parse(args); err != nil {
a.UI.Error(err.Error())
return 1
}
keystore, err := a.GetKeystore()
if err != nil {
a.UI.Error(fmt.Sprintf("Failed to get keystore: %v", err))
return 1
}
password, err := a.AskPassword()
if err != nil {
a.UI.Error(err.Error())
return 1
}
account, err := keystore.NewAccount(password)
if err != nil {
a.UI.Error(fmt.Sprintf("Failed to create new account: %v", err))
return 1
}
a.UI.Output("\nYour new key was generated")
a.UI.Output(fmt.Sprintf("Public address of the key: %s", account.Address.Hex()))
a.UI.Output(fmt.Sprintf("Path of the secret key file: %s", account.URL.Path))
return 0
}
package cli
import (
"github.com/mitchellh/cli"
)
// ChainCommand is the command to group the peers commands
type ChainCommand struct {
UI cli.Ui
}
// Help implements the cli.Command interface
func (c *ChainCommand) Help() string {
return `Usage: bor chain <subcommand>
This command groups actions to interact with the chain.
Set the new head of the chain:
$ bor chain sethead <number>`
}
// Synopsis implements the cli.Command interface
func (c *ChainCommand) Synopsis() string {
return "Interact with the chain"
}
// Run implements the cli.Command interface
func (c *ChainCommand) Run(args []string) int {
return cli.RunResultHelp
}
package cli
import (
"context"
"fmt"
"strconv"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
)
// ChainSetHeadCommand is the command to group the peers commands
type ChainSetHeadCommand struct {
*Meta2
yes bool
}
// Help implements the cli.Command interface
func (c *ChainSetHeadCommand) Help() string {
return `Usage: bor chain sethead <number> [--yes]
This command sets the current chain to a certain block`
}
func (c *ChainSetHeadCommand) Flags() *flagset.Flagset {
flags := c.NewFlagSet("chain sethead")
flags.BoolFlag(&flagset.BoolFlag{
Name: "yes",
Usage: "Force set head",
Default: false,
Value: &c.yes,
})
return flags
}
// Synopsis implements the cli.Command interface
func (c *ChainSetHeadCommand) Synopsis() string {
return "Set the new head of the chain"
}
// Run implements the cli.Command interface
func (c *ChainSetHeadCommand) Run(args []string) int {
flags := c.Flags()
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
c.UI.Error("No number provided")
return 1
}
borClt, err := c.BorConn()
if err != nil {
c.UI.Error(err.Error())
return 1
}
arg := args[0]
fmt.Println(arg)
number, err := strconv.Atoi(arg)
if err != nil {
c.UI.Error(err.Error())
return 1
}
if !c.yes {
response, err := c.UI.Ask("Are you sure you want to reset the database? (y/n)")
if err != nil {
c.UI.Error(err.Error())
return 1
}
if response != "y" {
c.UI.Output("set head aborted")
return 0
}
}
if _, err := borClt.ChainSetHead(context.Background(), &proto.ChainSetHeadRequest{Number: uint64(number)}); err != nil {
c.UI.Error(err.Error())
return 1
}
c.UI.Output("Done!")
return 0
}
package cli
import (
"context"
"fmt"
"os"
"os/signal"
"syscall"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
)
// ChainWatchCommand is the command to group the peers commands
type ChainWatchCommand struct {
*Meta2
}
// Help implements the cli.Command interface
func (c *ChainWatchCommand) Help() string {
return `Usage: bor chain watch
This command is used to view the chainHead, reorg and fork events in real-time`
}
func (c *ChainWatchCommand) Flags() *flagset.Flagset {
flags := c.NewFlagSet("chain watch")
return flags
}
// Synopsis implements the cli.Command interface
func (c *ChainWatchCommand) Synopsis() string {
return "Watch the chainHead, reorg and fork events in real-time"
}
// Run implements the cli.Command interface
func (c *ChainWatchCommand) Run(args []string) int {
flags := c.Flags()
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
borClt, err := c.BorConn()
if err != nil {
c.UI.Error(err.Error())
return 1
}
sub, err := borClt.ChainWatch(context.Background(), &proto.ChainWatchRequest{})
if err != nil {
c.UI.Error(err.Error())
return 1
}
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, os.Interrupt, syscall.SIGTERM)
go func() {
<-signalCh
sub.CloseSend()
}()
for {
msg, err := sub.Recv()
if err != nil {
// if err == EOF if finished on the other side
c.UI.Output(err.Error())
break
}
c.UI.Output(formatHeadEvent(msg))
}
return 0
}
func formatHeadEvent(msg *proto.ChainWatchResponse) string {
var out string
if msg.Type == core.Chain2HeadCanonicalEvent {
out = fmt.Sprintf("Block Added : %v", msg.Newchain)
} else if msg.Type == core.Chain2HeadForkEvent {
out = fmt.Sprintf("New Fork Block : %v", msg.Newchain)
} else if msg.Type == core.Chain2HeadReorgEvent {
out = fmt.Sprintf("Reorg Detected \nAdded : %v \nRemoved : %v", msg.Newchain, msg.Oldchain)
}
return out
}
package cli
import (
"fmt"
"os"
"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
"github.com/ethereum/go-ethereum/node"
"github.com/mitchellh/cli"
"github.com/ryanuber/columnize"
"google.golang.org/grpc"
)
func Run(args []string) int {
commands := commands()
cli := &cli.CLI{
Name: "bor",
Args: args,
Commands: commands,
}
exitCode, err := cli.Run()
if err != nil {
fmt.Fprintf(os.Stderr, "Error executing CLI: %s\n", err.Error())
return 1
}
return exitCode
}
func commands() map[string]cli.CommandFactory {
ui := &cli.BasicUi{
Reader: os.Stdin,
Writer: os.Stdout,
ErrorWriter: os.Stderr,
}
meta2 := &Meta2{
UI: ui,
}
meta := &Meta{
UI: ui,
}
return map[string]cli.CommandFactory{
"server": func() (cli.Command, error) {
return &server.Command{
UI: ui,
}, nil
},
"version": func() (cli.Command, error) {
return &VersionCommand{
UI: ui,
}, nil
},
"debug": func() (cli.Command, error) {
return &DebugCommand{
Meta2: meta2,
}, nil
},
"chain": func() (cli.Command, error) {
return &ChainCommand{
UI: ui,
}, nil
},
"chain watch": func() (cli.Command, error) {
return &ChainWatchCommand{
Meta2: meta2,
}, nil
},
"chain sethead": func() (cli.Command, error) {
return &ChainSetHeadCommand{
Meta2: meta2,
}, nil
},
"account": func() (cli.Command, error) {
return &Account{
UI: ui,
}, nil
},
"account new": func() (cli.Command, error) {
return &AccountNewCommand{
Meta: meta,
}, nil
},
"account import": func() (cli.Command, error) {
return &AccountImportCommand{
Meta: meta,
}, nil
},
"account list": func() (cli.Command, error) {
return &AccountListCommand{
Meta: meta,
}, nil
},
"peers": func() (cli.Command, error) {
return &PeersCommand{
UI: ui,
}, nil
},
"peers add": func() (cli.Command, error) {
return &PeersAddCommand{
Meta2: meta2,
}, nil
},
"peers remove": func() (cli.Command, error) {
return &PeersRemoveCommand{
Meta2: meta2,
}, nil
},
"peers list": func() (cli.Command, error) {
return &PeersListCommand{
Meta2: meta2,
}, nil
},
"peers status": func() (cli.Command, error) {
return &PeersStatusCommand{
Meta2: meta2,
}, nil
},
"status": func() (cli.Command, error) {
return &StatusCommand{
Meta2: meta2,
}, nil
},
}
}
type Meta2 struct {
UI cli.Ui
addr string
}
func (m *Meta2) NewFlagSet(n string) *flagset.Flagset {
f := flagset.NewFlagSet(n)
f.StringFlag(&flagset.StringFlag{
Name: "address",
Value: &m.addr,
Usage: "Address of the grpc endpoint",
Default: "127.0.0.1:3131",
})
return f
}
func (m *Meta2) Conn() (*grpc.ClientConn, error) {
conn, err := grpc.Dial(m.addr, grpc.WithInsecure())
if err != nil {
return nil, fmt.Errorf("failed to connect to server: %v", err)
}
return conn, nil
}
func (m *Meta2) BorConn() (proto.BorClient, error) {
conn, err := m.Conn()
if err != nil {
return nil, err
}
return proto.NewBorClient(conn), nil
}
// Meta is a helper utility for the commands
type Meta struct {
UI cli.Ui
dataDir string
keyStoreDir string
}
func (m *Meta) NewFlagSet(n string) *flagset.Flagset {
f := flagset.NewFlagSet(n)
f.StringFlag(&flagset.StringFlag{
Name: "datadir",
Value: &m.dataDir,
Usage: "Path of the data directory to store information",
})
f.StringFlag(&flagset.StringFlag{
Name: "keystore",
Value: &m.keyStoreDir,
Usage: "Path of the data directory to store information",
})
return f
}
func (m *Meta) AskPassword() (string, error) {
return m.UI.AskSecret("Your new account is locked with a password. Please give a password. Do not forget this password")
}
func (m *Meta) GetKeystore() (*keystore.KeyStore, error) {
cfg := node.DefaultConfig
cfg.DataDir = m.dataDir
cfg.KeyStoreDir = m.keyStoreDir
stack, err := node.New(&cfg)
if err != nil {
return nil, err
}
keydir := stack.KeyStoreDir()
scryptN := keystore.StandardScryptN
scryptP := keystore.StandardScryptP
keys := keystore.NewKeyStore(keydir, scryptN, scryptP)
return keys, nil
}
func formatList(in []string) string {
columnConf := columnize.DefaultConfig()
columnConf.Empty = "<none>"
return columnize.Format(in, columnConf)
}
func formatKV(in []string) string {
columnConf := columnize.DefaultConfig()
columnConf.Empty = "<none>"
columnConf.Glue = " = "
return columnize.Format(in, columnConf)
}
package cli
// Based on https://github.com/hashicorp/nomad/blob/main/command/operator_debug.go
import (
"archive/tar"
"compress/gzip"
"context"
"fmt"
"io"
"io/ioutil"
"os"
"os/signal"
"path/filepath"
"strings"
"syscall"
"time"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
"github.com/golang/protobuf/jsonpb"
gproto "github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes/empty"
grpc_net_conn "github.com/mitchellh/go-grpc-net-conn"
)
type DebugCommand struct {
*Meta2
seconds uint64
output string
}
// Help implements the cli.Command interface
func (d *DebugCommand) Help() string {
return `Usage: bor debug
Build an archive containing Bor pprof traces
` + d.Flags().Help()
}
func (d *DebugCommand) Flags() *flagset.Flagset {
flags := d.NewFlagSet("debug")
flags.Uint64Flag(&flagset.Uint64Flag{
Name: "seconds",
Usage: "seconds to trace",
Value: &d.seconds,
Default: 2,
})
flags.StringFlag(&flagset.StringFlag{
Name: "output",
Value: &d.output,
Usage: "Output directory",
})
return flags
}
// Synopsis implements the cli.Command interface
func (d *DebugCommand) Synopsis() string {
return "Build an archive containing Bor pprof traces"
}
// Run implements the cli.Command interface
func (d *DebugCommand) Run(args []string) int {
flags := d.Flags()
if err := flags.Parse(args); err != nil {
d.UI.Error(err.Error())
return 1
}
clt, err := d.BorConn()
if err != nil {
d.UI.Error(err.Error())
return 1
}
stamped := "bor-debug-" + time.Now().UTC().Format("2006-01-02-150405Z")
// Create the output directory
var tmp string
if d.output != "" {
// User specified output directory
tmp = filepath.Join(d.output, stamped)
_, err := os.Stat(tmp)
if !os.IsNotExist(err) {
d.UI.Error("Output directory already exists")
return 1
}
} else {
// Generate temp directory
tmp, err = ioutil.TempDir(os.TempDir(), stamped)
if err != nil {
d.UI.Error(fmt.Sprintf("Error creating tmp directory: %s", err.Error()))
return 1
}
defer os.RemoveAll(tmp)
}
d.UI.Output("Starting debugger...")
d.UI.Output("")
// ensure destine folder exists
if err := os.MkdirAll(tmp, os.ModePerm); err != nil {
d.UI.Error(fmt.Sprintf("failed to create parent directory: %v", err))
return 1
}
pprofProfile := func(ctx context.Context, profile string, filename string) error {
req := &proto.PprofRequest{
Seconds: int64(d.seconds),
}
switch profile {
case "cpu":
req.Type = proto.PprofRequest_CPU
case "trace":
req.Type = proto.PprofRequest_TRACE
default:
req.Type = proto.PprofRequest_LOOKUP
req.Profile = profile
}
stream, err := clt.Pprof(ctx, req)
if err != nil {
return err
}
// wait for open request
msg, err := stream.Recv()
if err != nil {
return err
}
if _, ok := msg.Event.(*proto.PprofResponse_Open_); !ok {
return fmt.Errorf("expected open message")
}
// create the stream
conn := &grpc_net_conn.Conn{
Stream: stream,
Response: &proto.PprofResponse_Input{},
Decode: grpc_net_conn.SimpleDecoder(func(msg gproto.Message) *[]byte {
return &msg.(*proto.PprofResponse_Input).Data
}),
}
file, err := os.OpenFile(filepath.Join(tmp, filename+".prof"), os.O_RDWR|os.O_CREATE, 0644)
if err != nil {
return err
}
defer file.Close()
if _, err := io.Copy(file, conn); err != nil {
return err
}
return nil
}
ctx, cancelFn := context.WithCancel(context.Background())
trapSignal(cancelFn)
profiles := map[string]string{
"heap": "heap",
"cpu": "cpu",
"trace": "trace",
}
for profile, filename := range profiles {
if err := pprofProfile(ctx, profile, filename); err != nil {
d.UI.Error(fmt.Sprintf("Error creating profile '%s': %v", profile, err))
return 1
}
}
// append the status
{
statusResp, err := clt.Status(ctx, &empty.Empty{})
if err != nil {
d.UI.Output(fmt.Sprintf("Failed to get status: %v", err))
return 1
}
m := jsonpb.Marshaler{}
data, err := m.MarshalToString(statusResp)
if err != nil {
d.UI.Output(err.Error())
return 1
}
if err := ioutil.WriteFile(filepath.Join(tmp, "status.json"), []byte(data), 0644); err != nil {
d.UI.Output(fmt.Sprintf("Failed to write status: %v", err))
return 1
}
}
// Exit before archive if output directory was specified
if d.output != "" {
d.UI.Output(fmt.Sprintf("Created debug directory: %s", tmp))
return 0
}
// Create archive tarball
archiveFile := stamped + ".tar.gz"
if err = tarCZF(archiveFile, tmp, stamped); err != nil {
d.UI.Error(fmt.Sprintf("Error creating archive: %s", err.Error()))
return 1
}
d.UI.Output(fmt.Sprintf("Created debug archive: %s", archiveFile))
return 0
}
func trapSignal(cancel func()) {
sigCh := make(chan os.Signal, 1)
signal.Notify(sigCh,
syscall.SIGHUP,
syscall.SIGINT,
syscall.SIGTERM,
syscall.SIGQUIT)
go func() {
<-sigCh
cancel()
}()
}
func tarCZF(archive string, src, target string) error {
// ensure the src actually exists before trying to tar it
if _, err := os.Stat(src); err != nil {
return fmt.Errorf("unable to tar files - %v", err.Error())
}
// create the archive
fh, err := os.Create(archive)
if err != nil {
return err
}
defer fh.Close()
zz := gzip.NewWriter(fh)
defer zz.Close()
tw := tar.NewWriter(zz)
defer tw.Close()
// tar
return filepath.Walk(src, func(file string, fi os.FileInfo, err error) error {
// return on any error
if err != nil {
return err
}
if !fi.Mode().IsRegular() {
return nil
}
header, err := tar.FileInfoHeader(fi, fi.Name())
if err != nil {
return err
}
// remove leading path to the src, so files are relative to the archive
path := strings.ReplaceAll(file, src, "")
if target != "" {
path = filepath.Join([]string{target, path}...)
}
path = strings.TrimPrefix(path, string(filepath.Separator))
header.Name = path
if err := tw.WriteHeader(header); err != nil {
return err
}
// copy the file contents
f, err := os.Open(file)
if err != nil {
return err
}
if _, err := io.Copy(tw, f); err != nil {
return err
}
f.Close()
return nil
})
}
package flagset
import (
"flag"
"fmt"
"math/big"
"strings"
"time"
)
type Flagset struct {
flags []*FlagVar
set *flag.FlagSet
}
func NewFlagSet(name string) *Flagset {
f := &Flagset{
flags: []*FlagVar{},
set: flag.NewFlagSet(name, flag.ContinueOnError),
}
return f
}
type FlagVar struct {
Name string
Usage string
}
func (f *Flagset) addFlag(fl *FlagVar) {
f.flags = append(f.flags, fl)
}
func (f *Flagset) Help() string {
str := "Options:\n\n"
items := []string{}
for _, item := range f.flags {
items = append(items, fmt.Sprintf(" -%s\n %s", item.Name, item.Usage))
}
return str + strings.Join(items, "\n\n")
}
func (f *Flagset) Parse(args []string) error {
return f.set.Parse(args)
}
func (f *Flagset) Args() []string {
return f.set.Args()
}
type BoolFlag struct {
Name string
Usage string
Default bool
Value *bool
}
func (f *Flagset) BoolFlag(b *BoolFlag) {
f.addFlag(&FlagVar{
Name: b.Name,
Usage: b.Usage,
})
f.set.BoolVar(b.Value, b.Name, b.Default, b.Usage)
}
type StringFlag struct {
Name string
Usage string
Default string
Value *string
}
func (f *Flagset) StringFlag(b *StringFlag) {
f.addFlag(&FlagVar{
Name: b.Name,
Usage: b.Usage,
})
f.set.StringVar(b.Value, b.Name, b.Default, b.Usage)
}
type IntFlag struct {
Name string
Usage string
Value *int
Default int
}
func (f *Flagset) IntFlag(i *IntFlag) {
f.addFlag(&FlagVar{
Name: i.Name,
Usage: i.Usage,
})
f.set.IntVar(i.Value, i.Name, i.Default, i.Usage)
}
type Uint64Flag struct {
Name string
Usage string
Value *uint64
Default uint64
}
func (f *Flagset) Uint64Flag(i *Uint64Flag) {
f.addFlag(&FlagVar{
Name: i.Name,
Usage: i.Usage,
})
f.set.Uint64Var(i.Value, i.Name, i.Default, i.Usage)
}
type BigIntFlag struct {
Name string
Usage string
Value *big.Int
}
func (b *BigIntFlag) String() string {
if b.Value == nil {
return ""
}
return b.Value.String()
}
func (b *BigIntFlag) Set(value string) error {
num := new(big.Int)
var ok bool
if strings.HasPrefix(value, "0x") {
num, ok = num.SetString(value[2:], 16)
} else {
num, ok = num.SetString(value, 10)
}
if !ok {
return fmt.Errorf("failed to set big int")
}
b.Value = num
return nil
}
func (f *Flagset) BigIntFlag(b *BigIntFlag) {
f.addFlag(&FlagVar{
Name: b.Name,
Usage: b.Usage,
})
f.set.Var(b, b.Name, b.Usage)
}
type SliceStringFlag struct {
Name string
Usage string
Value *[]string
}
func (i *SliceStringFlag) String() string {
if i.Value == nil {
return ""
}
return strings.Join(*i.Value, ",")
}
func (i *SliceStringFlag) Set(value string) error {
*i.Value = append(*i.Value, strings.Split(value, ",")...)
return nil
}
func (f *Flagset) SliceStringFlag(s *SliceStringFlag) {
f.addFlag(&FlagVar{
Name: s.Name,
Usage: s.Usage,
})
f.set.Var(s, s.Name, s.Usage)
}
type DurationFlag struct {
Name string
Usage string
Value *time.Duration
Default time.Duration
}
func (f *Flagset) DurationFlag(d *DurationFlag) {
f.addFlag(&FlagVar{
Name: d.Name,
Usage: d.Usage,
})
f.set.DurationVar(d.Value, d.Name, d.Default, "")
}
type MapStringFlag struct {
Name string
Usage string
Value *map[string]string
}
func (m *MapStringFlag) String() string {
if m.Value == nil {
return ""
}
ls := []string{}
for k, v := range *m.Value {
ls = append(ls, k+"="+v)
}
return strings.Join(ls, ",")
}
func (m *MapStringFlag) Set(value string) error {
if m.Value == nil {
m.Value = &map[string]string{}
}
for _, t := range strings.Split(value, ",") {
if t != "" {
kv := strings.Split(t, "=")
if len(kv) == 2 {
(*m.Value)[kv[0]] = kv[1]
}
}
}
return nil
}
func (f *Flagset) MapStringFlag(m *MapStringFlag) {
f.addFlag(&FlagVar{
Name: m.Name,
Usage: m.Usage,
})
f.set.Var(m, m.Name, m.Usage)
}
type Float64Flag struct {
Name string
Usage string
Value *float64
Default float64
}
func (f *Flagset) Float64Flag(i *Float64Flag) {
f.addFlag(&FlagVar{
Name: i.Name,
Usage: i.Usage,
})
f.set.Float64Var(i.Value, i.Name, i.Default, "")
}
package flagset
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
)
func TestFlagsetBool(t *testing.T) {
f := NewFlagSet("")
value := false
f.BoolFlag(&BoolFlag{
Name: "flag",
Value: &value,
})
assert.NoError(t, f.Parse([]string{"--flag", "true"}))
assert.Equal(t, value, true)
}
func TestFlagsetSliceString(t *testing.T) {
f := NewFlagSet("")
value := []string{}
f.SliceStringFlag(&SliceStringFlag{
Name: "flag",
Value: &value,
})
assert.NoError(t, f.Parse([]string{"--flag", "a,b", "--flag", "c"}))
assert.Equal(t, value, []string{"a", "b", "c"})
}
func TestFlagsetDuration(t *testing.T) {
f := NewFlagSet("")
value := time.Duration(0)
f.DurationFlag(&DurationFlag{
Name: "flag",
Value: &value,
})
assert.NoError(t, f.Parse([]string{"--flag", "1m"}))
assert.Equal(t, value, 1*time.Minute)
}
func TestFlagsetMapString(t *testing.T) {
f := NewFlagSet("")
value := map[string]string{}
f.MapStringFlag(&MapStringFlag{
Name: "flag",
Value: &value,
})
assert.NoError(t, f.Parse([]string{"--flag", "a=b,c=d"}))
assert.Equal(t, value, map[string]string{"a": "b", "c": "d"})
}
package cli
import (
"github.com/mitchellh/cli"
)
// PeersCommand is the command to group the peers commands
type PeersCommand struct {
UI cli.Ui
}
// Help implements the cli.Command interface
func (c *PeersCommand) Help() string {
return `Usage: bor peers <subcommand>
This command groups actions to interact with peers.
List the connected peers:
$ bor peers list
Add a new peer by enode:
$ bor peers add <enode>
Remove a connected peer by enode:
$ bor peers remove <enode>
Display information about a peer:
$ bor peers status <peer id>`
}
// Synopsis implements the cli.Command interface
func (c *PeersCommand) Synopsis() string {
return "Interact with peers"
}
// Run implements the cli.Command interface
func (c *PeersCommand) Run(args []string) int {
return cli.RunResultHelp
}
package cli
import (
"context"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
)
// PeersAddCommand is the command to group the peers commands
type PeersAddCommand struct {
*Meta2
trusted bool
}
// Help implements the cli.Command interface
func (p *PeersAddCommand) Help() string {
return `Usage: bor peers add <enode>
Joins the local client to another remote peer.
` + p.Flags().Help()
}
func (p *PeersAddCommand) Flags() *flagset.Flagset {
flags := p.NewFlagSet("peers add")
flags.BoolFlag(&flagset.BoolFlag{
Name: "trusted",
Usage: "Add the peer as a trusted",
Value: &p.trusted,
})
return flags
}
// Synopsis implements the cli.Command interface
func (c *PeersAddCommand) Synopsis() string {
return "Join the client to a remote peer"
}
// Run implements the cli.Command interface
func (c *PeersAddCommand) Run(args []string) int {
flags := c.Flags()
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
c.UI.Error("No enode address provided")
return 1
}
borClt, err := c.BorConn()
if err != nil {
c.UI.Error(err.Error())
return 1
}
req := &proto.PeersAddRequest{
Enode: args[0],
Trusted: c.trusted,
}
if _, err := borClt.PeersAdd(context.Background(), req); err != nil {
c.UI.Error(err.Error())
return 1
}
return 0
}
package cli
import (
"context"
"fmt"
"strings"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
)
// PeersListCommand is the command to group the peers commands
type PeersListCommand struct {
*Meta2
}
// Help implements the cli.Command interface
func (p *PeersListCommand) Help() string {
return `Usage: bor peers list
Lists the connected peers
` + p.Flags().Help()
}
func (p *PeersListCommand) Flags() *flagset.Flagset {
flags := p.NewFlagSet("peers list")
return flags
}
// Synopsis implements the cli.Command interface
func (c *PeersListCommand) Synopsis() string {
return ""
}
// Run implements the cli.Command interface
func (c *PeersListCommand) Run(args []string) int {
flags := c.Flags()
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
borClt, err := c.BorConn()
if err != nil {
c.UI.Error(err.Error())
return 1
}
req := &proto.PeersListRequest{}
resp, err := borClt.PeersList(context.Background(), req)
if err != nil {
c.UI.Error(err.Error())
return 1
}
c.UI.Output(formatPeers(resp.Peers))
return 0
}
func formatPeers(peers []*proto.Peer) string {
if len(peers) == 0 {
return "No peers found"
}
rows := make([]string, len(peers)+1)
rows[0] = "ID|Enode|Name|Caps|Static|Trusted"
for i, d := range peers {
enode := strings.TrimPrefix(d.Enode, "enode://")
rows[i+1] = fmt.Sprintf("%s|%s|%s|%s|%v|%v",
d.Id,
enode[:10],
d.Name,
strings.Join(d.Caps, ","),
d.Static,
d.Trusted)
}
return formatList(rows)
}
package cli
import (
"context"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
)
// PeersRemoveCommand is the command to group the peers commands
type PeersRemoveCommand struct {
*Meta2
trusted bool
}
// Help implements the cli.Command interface
func (p *PeersRemoveCommand) Help() string {
return `Usage: bor peers remove <enode>
Disconnects the local client from a connected peer if exists.
` + p.Flags().Help()
}
func (p *PeersRemoveCommand) Flags() *flagset.Flagset {
flags := p.NewFlagSet("peers remove")
flags.BoolFlag(&flagset.BoolFlag{
Name: "trusted",
Usage: "Add the peer as a trusted",
Value: &p.trusted,
})
return flags
}
// Synopsis implements the cli.Command interface
func (c *PeersRemoveCommand) Synopsis() string {
return "Disconnects a peer from the client"
}
// Run implements the cli.Command interface
func (c *PeersRemoveCommand) Run(args []string) int {
flags := c.Flags()
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
c.UI.Error("No enode address provided")
return 1
}
borClt, err := c.BorConn()
if err != nil {
c.UI.Error(err.Error())
return 1
}
req := &proto.PeersRemoveRequest{
Enode: args[0],
Trusted: c.trusted,
}
if _, err := borClt.PeersRemove(context.Background(), req); err != nil {
c.UI.Error(err.Error())
return 1
}
return 0
}
package cli
import (
"context"
"fmt"
"strings"
"github.com/ethereum/go-ethereum/internal/cli/flagset"
"github.com/ethereum/go-ethereum/internal/cli/server/proto"
)
// PeersStatusCommand is the command to group the peers commands
type PeersStatusCommand struct {
*Meta2
}
// Help implements the cli.Command interface
func (p *PeersStatusCommand) Help() string {
return `Usage: bor peers status <peer id>
Display the status of a peer by its id.
` + p.Flags().Help()
}
func (p *PeersStatusCommand) Flags() *flagset.Flagset {
flags := p.NewFlagSet("peers status")
return flags
}
// Synopsis implements the cli.Command interface
func (c *PeersStatusCommand) Synopsis() string {
return "Display the status of a peer"
}
// Run implements the cli.Command interface
func (c *PeersStatusCommand) Run(args []string) int {
flags := c.Flags()
if err := flags.Parse(args); err != nil {
c.UI.Error(err.Error())
return 1
}
args = flags.Args()
if len(args) != 1 {
c.UI.Error("No enode address provided")
return 1
}
borClt, err := c.BorConn()
if err != nil {
c.UI.Error(err.Error())
return 1
}
req := &proto.PeersStatusRequest{
Enode: args[0],
}
resp, err := borClt.PeersStatus(context.Background(), req)
if err != nil {
c.UI.Error(err.Error())
return 1
}
c.UI.Output(formatPeer(resp.Peer))
return 0
}
func formatPeer(peer *proto.Peer) string {
base := formatKV([]string{
fmt.Sprintf("Name|%s", peer.Name),
fmt.Sprintf("ID|%s", peer.Id),
fmt.Sprintf("ENR|%s", peer.Enr),
fmt.Sprintf("Capabilities|%s", strings.Join(peer.Caps, ",")),
fmt.Sprintf("Enode|%s", peer.Enode),
fmt.Sprintf("Static|%v", peer.Static),
fmt.Sprintf("Trusted|%v", peer.Trusted),
})
return base
}
This diff is collapsed.
This diff is collapsed.
package chains
import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
)
type Chain struct {
Hash common.Hash
Genesis *core.Genesis
Bootnodes []string
NetworkId uint64
DNS []string
}
var chains = map[string]*Chain{
"mainnet": mainnetBor,
"mumbai": mumbaiTestnet,
}
func GetChain(name string) (*Chain, bool) {
chain, ok := chains[name]
return chain, ok
}
package chains
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)
// GetDeveloperChain returns the developer mode configs.
func GetDeveloperChain(period uint64, faucet common.Address) *Chain {
// Override the default period to the user requested one
config := *params.AllCliqueProtocolChanges
config.Clique = &params.CliqueConfig{
Period: period,
Epoch: config.Clique.Epoch,
}
// Assemble and return the chain having genesis with the
// precompiles and faucet pre-funded
return &Chain{
Hash: common.Hash{},
NetworkId: 1337,
Genesis: &core.Genesis{
Config: &config,
ExtraData: append(append(make([]byte, 32), faucet[:]...), make([]byte, crypto.SignatureLength)...),
GasLimit: 11500000,
BaseFee: big.NewInt(params.InitialBaseFee),
Difficulty: big.NewInt(1),
Alloc: map[common.Address]core.GenesisAccount{
common.BytesToAddress([]byte{1}): {Balance: big.NewInt(1)}, // ECRecover
common.BytesToAddress([]byte{2}): {Balance: big.NewInt(1)}, // SHA256
common.BytesToAddress([]byte{3}): {Balance: big.NewInt(1)}, // RIPEMD
common.BytesToAddress([]byte{4}): {Balance: big.NewInt(1)}, // Identity
common.BytesToAddress([]byte{5}): {Balance: big.NewInt(1)}, // ModExp
common.BytesToAddress([]byte{6}): {Balance: big.NewInt(1)}, // ECAdd
common.BytesToAddress([]byte{7}): {Balance: big.NewInt(1)}, // ECScalarMul
common.BytesToAddress([]byte{8}): {Balance: big.NewInt(1)}, // ECPairing
common.BytesToAddress([]byte{9}): {Balance: big.NewInt(1)}, // BLAKE2b
faucet: {Balance: new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(9))},
},
},
Bootnodes: []string{},
}
}
package chains
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/params"
)
var mainnetBor = &Chain{
Hash: common.HexToHash("0xa9c28ce2141b56c474f1dc504bee9b01eb1bd7d1a507580d5519d4437a97de1b"),
NetworkId: 137,
Genesis: &core.Genesis{
Config: &params.ChainConfig{
ChainID: big.NewInt(137),
HomesteadBlock: big.NewInt(0),
DAOForkBlock: nil,
DAOForkSupport: true,
EIP150Hash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
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(3395000),
MuirGlacierBlock: big.NewInt(3395000),
BerlinBlock: big.NewInt(14750000),
LondonBlock: big.NewInt(23850000),
Bor: &params.BorConfig{
JaipurBlock: 23850000,
Period: map[string]uint64{
"0": 2,
},
ProducerDelay: 6,
Sprint: 64,
BackupMultiplier: map[string]uint64{
"0": 2,
},
ValidatorContract: "0x0000000000000000000000000000000000001000",
StateReceiverContract: "0x0000000000000000000000000000000000001001",
OverrideStateSyncRecords: map[string]int{
"14949120": 8,
"14949184": 0,
"14953472": 0,
"14953536": 5,
"14953600": 0,
"14953664": 0,
"14953728": 0,
"14953792": 0,
"14953856": 0,
},
BurntContract: map[string]string{
"23850000": "0x70bca57f4579f58670ab2d18ef16e02c17553c38",
},
BlockAlloc: map[string]interface{}{
// write as interface since that is how it is decoded in genesis
"22156660": map[string]interface{}{
"0000000000000000000000000000000000001010": map[string]interface{}{
"balance": "0x0",
"code": "0x60806040526004361061019c5760003560e01c806377d32e94116100ec578063acd06cb31161008a578063e306f77911610064578063e306f77914610a7b578063e614d0d614610aa6578063f2fde38b14610ad1578063fc0c546a14610b225761019c565b8063acd06cb31461097a578063b789543c146109cd578063cc79f97b14610a505761019c565b80639025e64c116100c65780639025e64c146107c957806395d89b4114610859578063a9059cbb146108e9578063abceeba21461094f5761019c565b806377d32e94146106315780638da5cb5b146107435780638f32d59b1461079a5761019c565b806347e7ef24116101595780637019d41a116101335780637019d41a1461053357806370a082311461058a578063715018a6146105ef578063771282f6146106065761019c565b806347e7ef2414610410578063485cc9551461046b57806360f96a8f146104dc5761019c565b806306fdde03146101a15780631499c5921461023157806318160ddd1461028257806319d27d9c146102ad5780632e1a7d4d146103b1578063313ce567146103df575b600080fd5b3480156101ad57600080fd5b506101b6610b79565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156101f65780820151818401526020810190506101db565b50505050905090810190601f1680156102235780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561023d57600080fd5b506102806004803603602081101561025457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bb6565b005b34801561028e57600080fd5b50610297610c24565b6040518082815260200191505060405180910390f35b3480156102b957600080fd5b5061036f600480360360a08110156102d057600080fd5b81019080803590602001906401000000008111156102ed57600080fd5b8201836020820111156102ff57600080fd5b8035906020019184600183028401116401000000008311171561032157600080fd5b9091929391929390803590602001909291908035906020019092919080359060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610c3a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6103dd600480360360208110156103c757600080fd5b8101908080359060200190929190505050610caa565b005b3480156103eb57600080fd5b506103f4610dfc565b604051808260ff1660ff16815260200191505060405180910390f35b34801561041c57600080fd5b506104696004803603604081101561043357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e05565b005b34801561047757600080fd5b506104da6004803603604081101561048e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610fc1565b005b3480156104e857600080fd5b506104f1611090565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561053f57600080fd5b506105486110b6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561059657600080fd5b506105d9600480360360208110156105ad57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506110dc565b6040518082815260200191505060405180910390f35b3480156105fb57600080fd5b506106046110fd565b005b34801561061257600080fd5b5061061b6111cd565b6040518082815260200191505060405180910390f35b34801561063d57600080fd5b506107016004803603604081101561065457600080fd5b81019080803590602001909291908035906020019064010000000081111561067b57600080fd5b82018360208201111561068d57600080fd5b803590602001918460018302840111640100000000831117156106af57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506111d3565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561074f57600080fd5b50610758611358565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156107a657600080fd5b506107af611381565b604051808215151515815260200191505060405180910390f35b3480156107d557600080fd5b506107de6113d8565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561081e578082015181840152602081019050610803565b50505050905090810190601f16801561084b5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561086557600080fd5b5061086e611411565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156108ae578082015181840152602081019050610893565b50505050905090810190601f1680156108db5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610935600480360360408110156108ff57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061144e565b604051808215151515815260200191505060405180910390f35b34801561095b57600080fd5b50610964611474565b6040518082815260200191505060405180910390f35b34801561098657600080fd5b506109b36004803603602081101561099d57600080fd5b8101908080359060200190929190505050611501565b604051808215151515815260200191505060405180910390f35b3480156109d957600080fd5b50610a3a600480360360808110156109f057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291908035906020019092919080359060200190929190505050611521565b6040518082815260200191505060405180910390f35b348015610a5c57600080fd5b50610a65611541565b6040518082815260200191505060405180910390f35b348015610a8757600080fd5b50610a90611546565b6040518082815260200191505060405180910390f35b348015610ab257600080fd5b50610abb61154c565b6040518082815260200191505060405180910390f35b348015610add57600080fd5b50610b2060048036036020811015610af457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506115d9565b005b348015610b2e57600080fd5b50610b376115f6565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b60606040518060400160405280600b81526020017f4d6174696320546f6b656e000000000000000000000000000000000000000000815250905090565b6040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b6000601260ff16600a0a6402540be40002905090565b60006040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260108152602001807f44697361626c656420666561747572650000000000000000000000000000000081525060200191505060405180910390fd5b60003390506000610cba826110dc565b9050610cd18360065461161c90919063ffffffff16565b600681905550600083118015610ce657508234145b610d58576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f496e73756666696369656e7420616d6f756e740000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167febff2602b3f468259e1e99f613fed6691f3a6526effe6ef3e768ba7ae7a36c4f8584610dd4876110dc565b60405180848152602001838152602001828152602001935050505060405180910390a3505050565b60006012905090565b610e0d611381565b610e1657600080fd5b600081118015610e535750600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614155b610ea8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611da76023913960400191505060405180910390fd5b6000610eb3836110dc565b905060008390508073ffffffffffffffffffffffffffffffffffffffff166108fc849081150290604051600060405180830381858888f19350505050158015610f00573d6000803e3d6000fd5b50610f168360065461163c90919063ffffffff16565b6006819055508373ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f4e2ca0515ed1aef1395f66b5303bb5d6f1bf9d61a353fa53f73f8ac9973fa9f68585610f98896110dc565b60405180848152602001838152602001828152602001935050505060405180910390a350505050565b600760009054906101000a900460ff1615611027576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611d846023913960400191505060405180910390fd5b6001600760006101000a81548160ff02191690831515021790555080600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555061108c8261165b565b5050565b600360009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b600460009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008173ffffffffffffffffffffffffffffffffffffffff16319050919050565b611105611381565b61110e57600080fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b60065481565b60008060008060418551146111ee5760009350505050611352565b602085015192506040850151915060ff6041860151169050601b8160ff16101561121957601b810190505b601b8160ff16141580156112315750601c8160ff1614155b156112425760009350505050611352565b60018682858560405160008152602001604052604051808581526020018460ff1660ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa15801561129f573d6000803e3d6000fd5b505050602060405103519350600073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16141561134e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4572726f7220696e2065637265636f766572000000000000000000000000000081525060200191505060405180910390fd5b5050505b92915050565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614905090565b6040518060400160405280600181526020017f890000000000000000000000000000000000000000000000000000000000000081525081565b60606040518060400160405280600581526020017f4d41544943000000000000000000000000000000000000000000000000000000815250905090565b6000813414611460576000905061146e565b61146b338484611753565b90505b92915050565b6040518060800160405280605b8152602001611e1c605b91396040516020018082805190602001908083835b602083106114c357805182526020820191506020810190506020830392506114a0565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b60056020528060005260406000206000915054906101000a900460ff1681565b600061153761153286868686611b10565b611be6565b9050949350505050565b608981565b60015481565b604051806080016040528060528152602001611dca605291396040516020018082805190602001908083835b6020831061159b5780518252602082019150602081019050602083039250611578565b6001836020036101000a0380198251168184511680821785525050505050509050019150506040516020818303038152906040528051906020012081565b6115e1611381565b6115ea57600080fd5b6115f38161165b565b50565b600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008282111561162b57600080fd5b600082840390508091505092915050565b60008082840190508381101561165157600080fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff16141561169557600080fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b6000803073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156117d357600080fd5b505afa1580156117e7573d6000803e3d6000fd5b505050506040513d60208110156117fd57600080fd5b8101908080519060200190929190505050905060003073ffffffffffffffffffffffffffffffffffffffff166370a08231866040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b15801561188f57600080fd5b505afa1580156118a3573d6000803e3d6000fd5b505050506040513d60208110156118b957600080fd5b810190808051906020019092919050505090506118d7868686611c30565b8473ffffffffffffffffffffffffffffffffffffffff168673ffffffffffffffffffffffffffffffffffffffff16600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167fe6497e3ee548a3372136af2fcb0696db31fc6cf20260707645068bd3fe97f3c48786863073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156119df57600080fd5b505afa1580156119f3573d6000803e3d6000fd5b505050506040513d6020811015611a0957600080fd5b81019080805190602001909291905050503073ffffffffffffffffffffffffffffffffffffffff166370a082318e6040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b158015611a9757600080fd5b505afa158015611aab573d6000803e3d6000fd5b505050506040513d6020811015611ac157600080fd5b8101908080519060200190929190505050604051808681526020018581526020018481526020018381526020018281526020019550505050505060405180910390a46001925050509392505050565b6000806040518060800160405280605b8152602001611e1c605b91396040516020018082805190602001908083835b60208310611b625780518252602082019150602081019050602083039250611b3f565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120905060405181815273ffffffffffffffffffffffffffffffffffffffff8716602082015285604082015284606082015283608082015260a0812092505081915050949350505050565b60008060015490506040517f190100000000000000000000000000000000000000000000000000000000000081528160028201528360228201526042812092505081915050919050565b3073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611cd2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260138152602001807f63616e27742073656e6420746f204d524332300000000000000000000000000081525060200191505060405180910390fd5b8173ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f19350505050158015611d18573d6000803e3d6000fd5b508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a350505056fe54686520636f6e747261637420697320616c726561647920696e697469616c697a6564496e73756666696369656e7420616d6f756e74206f7220696e76616c69642075736572454950373132446f6d61696e28737472696e67206e616d652c737472696e672076657273696f6e2c75696e7432353620636861696e49642c6164647265737320766572696679696e67436f6e747261637429546f6b656e5472616e736665724f726465722861646472657373207370656e6465722c75696e7432353620746f6b656e49644f72416d6f756e742c6279746573333220646174612c75696e743235362065787069726174696f6e29a265627a7a72315820a4a6f71a98ac3fc613c3a8f1e2e11b9eb9b6b39f125f7d9508916c2b8fb02c7164736f6c63430005100032",
},
},
},
},
},
Nonce: 0,
Timestamp: 1590824836,
GasLimit: 10000000,
Difficulty: big.NewInt(1),
Mixhash: common.HexToHash("0x0000000000000000000000000000000000000000000000000000000000000000"),
Coinbase: common.HexToAddress("0x0000000000000000000000000000000000000000"),
Alloc: readPrealloc("allocs/mainnet.json"),
},
Bootnodes: []string{
"enode://0cb82b395094ee4a2915e9714894627de9ed8498fb881cec6db7c65e8b9a5bd7f2f25cc84e71e89d0947e51c76e85d0847de848c7782b13c0255247a6758178c@44.232.55.71:30303",
"enode://88116f4295f5a31538ae409e4d44ad40d22e44ee9342869e7d68bdec55b0f83c1530355ce8b41fbec0928a7d75a5745d528450d30aec92066ab6ba1ee351d710@159.203.9.164:30303",
},
}