diff --git a/.gitignore b/.gitignore
index 0271db9ecd..d98f7c9227 100644
--- a/.gitignore
+++ b/.gitignore
@@ -50,3 +50,5 @@ profile.cov
**/yarn-error.log
cmd/geth/node/
cmd/geth/__debug_bin
+cmd/bootnode/bootnode
+graphql/__debug_bin
diff --git a/Dockerfile b/Dockerfile
index 10bd6ba8c0..ecbc855cd4 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -6,13 +6,15 @@ ARG BUILDNUM=""
# Build Geth in a stock Go builder container
FROM golang:1.19-alpine as builder
-RUN apk add --no-cache make gcc musl-dev linux-headers git bash
+RUN apk add --no-cache make cmake gcc musl-dev linux-headers git bash build-base libc-dev
# Get dependencies - will also be cached if we won't change go.mod/go.sum
COPY go.mod /go-ethereum/
COPY go.sum /go-ethereum/
RUN cd /go-ethereum && go mod download
ADD . /go-ethereum
+ENV CGO_CFLAGS="-O -D__BLST_PORTABLE__"
+ENV CGO_CFLAGS_ALLOW="-O -D__BLST_PORTABLE__"
RUN cd /go-ethereum && go run build/ci.go install ./cmd/geth
# Pull Geth into a second stage deploy alpine container
@@ -26,9 +28,10 @@ ENV BSC_HOME=/bsc
ENV HOME=${BSC_HOME}
ENV DATA_DIR=/data
+ARG VERSION_GCC=11.2.1_git20220219-r2
ENV PACKAGES ca-certificates jq \
bash bind-tools tini \
- grep curl sed
+ grep curl sed gcc==${VERSION_GCC}
RUN apk add --no-cache $PACKAGES \
&& rm -rf /var/cache/apk/* \
@@ -56,4 +59,4 @@ USER ${BSC_USER_UID}:${BSC_USER_GID}
# rpc ws graphql
EXPOSE 8545 8546 8547 30303 30303/udp
-ENTRYPOINT ["/sbin/tini", "--", "./docker-entrypoint.sh"]
+ENTRYPOINT ["/sbin/tini", "--", "./docker-entrypoint.sh"]
\ No newline at end of file
diff --git a/accounts/abi/bind/backends/simulated.go b/accounts/abi/bind/backends/simulated.go
index f8ceec8838..131ab8740f 100644
--- a/accounts/abi/bind/backends/simulated.go
+++ b/accounts/abi/bind/backends/simulated.go
@@ -826,11 +826,22 @@ type filterBackend struct {
func (fb *filterBackend) ChainDb() ethdb.Database { return fb.db }
func (fb *filterBackend) EventMux() *event.TypeMux { panic("not supported") }
-func (fb *filterBackend) HeaderByNumber(ctx context.Context, block rpc.BlockNumber) (*types.Header, error) {
- if block == rpc.LatestBlockNumber {
+func (fb *filterBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber) (*types.Header, error) {
+ switch number {
+ case rpc.PendingBlockNumber:
+ if block := fb.backend.pendingBlock; block != nil {
+ return block.Header(), nil
+ }
+ return nil, nil
+ case rpc.LatestBlockNumber:
return fb.bc.CurrentHeader(), nil
+ case rpc.FinalizedBlockNumber:
+ return fb.bc.CurrentFinalBlock(), nil
+ case rpc.SafeBlockNumber:
+ return fb.bc.CurrentSafeBlock(), nil
+ default:
+ return fb.bc.GetHeaderByNumber(uint64(number.Int64())), nil
}
- return fb.bc.GetHeaderByNumber(uint64(block.Int64())), nil
}
func (fb *filterBackend) HeaderByHash(ctx context.Context, hash common.Hash) (*types.Header, error) {
@@ -869,10 +880,18 @@ func (fb *filterBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.
return nullSubscription()
}
+func (fb *filterBackend) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription {
+ return nullSubscription()
+}
+
func (fb *filterBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
return fb.bc.SubscribeChainEvent(ch)
}
+func (fb *filterBackend) SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription {
+ return fb.bc.SubscribeFinalizedHeaderEvent(ch)
+}
+
func (fb *filterBackend) SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription {
return fb.bc.SubscribeRemovedLogsEvent(ch)
}
diff --git a/beacon/engine/types.go b/beacon/engine/types.go
new file mode 100644
index 0000000000..ecdf67176c
--- /dev/null
+++ b/beacon/engine/types.go
@@ -0,0 +1,18 @@
+// 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 .
+
+// just for prysm compile pass
+package engine
diff --git a/cmd/geth/blsaccountcmd.go b/cmd/geth/blsaccountcmd.go
new file mode 100644
index 0000000000..07c6b24814
--- /dev/null
+++ b/cmd/geth/blsaccountcmd.go
@@ -0,0 +1,552 @@
+package main
+
+import (
+ "context"
+ "encoding/hex"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "path/filepath"
+ "strings"
+
+ "github.com/google/uuid"
+ "github.com/logrusorgru/aurora"
+ "github.com/prysmaticlabs/prysm/v3/crypto/bls"
+ "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil"
+ "github.com/prysmaticlabs/prysm/v3/io/prompt"
+ "github.com/prysmaticlabs/prysm/v3/validator/accounts"
+ "github.com/prysmaticlabs/prysm/v3/validator/accounts/iface"
+ "github.com/prysmaticlabs/prysm/v3/validator/accounts/petnames"
+ "github.com/prysmaticlabs/prysm/v3/validator/accounts/wallet"
+ "github.com/prysmaticlabs/prysm/v3/validator/keymanager"
+ "github.com/prysmaticlabs/prysm/v3/validator/keymanager/local"
+ keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
+ "gopkg.in/urfave/cli.v1"
+
+ "github.com/ethereum/go-ethereum/cmd/utils"
+ "github.com/ethereum/go-ethereum/signer/core"
+)
+
+const (
+ BLSWalletPath = "bls/wallet"
+ BLSKeystorePath = "bls/keystore"
+)
+
+var (
+ au = aurora.NewAurora(true)
+)
+
+var (
+ blsCommand = cli.Command{
+ Name: "bls",
+ Usage: "Manage BLS wallet and accounts",
+ ArgsUsage: "",
+ Category: "BLS ACCOUNT COMMANDS",
+ Description: `
+
+Manage BLS wallet and accounts, before creating or importing BLS accounts, create
+BLS wallet first. One BLS wallet is enough for all BLS accounts, the first BLS
+account in the wallet will be used to vote for fast finality now.
+
+It only supports interactive mode now, when you are prompted for password, please
+input your password, and take care the wallet password which is different from accounts'
+password.
+
+There are generally two steps to manage a BLS account:
+1.Create a BLS wallet: geth bls wallet create
+2.Create a BLS account: geth bls account new
+ or import a BLS account: geth bls account import `,
+ Subcommands: []cli.Command{
+ {
+ Name: "wallet",
+ Usage: "Manage BLS wallet",
+ ArgsUsage: "",
+ Category: "BLS ACCOUNT COMMANDS",
+ Description: `
+
+Create a BLS wallet to manage BLS accounts, this should before creating
+or import a BLS account. The BLS wallet dir should be "/bls/wallet".`,
+ Subcommands: []cli.Command{
+ {
+ Name: "create",
+ Usage: "Create BLS wallet",
+ Action: utils.MigrateFlags(blsWalletCreate),
+ ArgsUsage: "",
+ Category: "BLS ACCOUNT COMMANDS",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ },
+ Description: `
+ geth bls wallet create
+
+will prompt for your password then create a BLS wallet in "/bls/wallet",
+don't create BLS wallet repeatedly'.`,
+ },
+ },
+ },
+ {
+ Name: "account",
+ Usage: "Manage BLS accounts",
+ ArgsUsage: "",
+ Category: "BLS ACCOUNT COMMANDS",
+ Description: `
+
+Manage BLS accounts,list all existing accounts, import a BLS private key into
+a new account, create a new account or delete an existing account.
+
+Make sure you remember the password you gave when creating a new account.
+Without it you are not able to unlock your account. And this password is
+different from the wallet password, please take care.
+
+Note that exporting your key in unencrypted format is NOT supported.
+
+Keys are stored under /bls/keystore.
+It is safe to transfer the entire directory or the individual keys therein
+between ethereum nodes by simply copying.
+
+Make sure you backup your BLS keys regularly.`,
+ Subcommands: []cli.Command{
+ {
+ Name: "new",
+ Usage: "Create a BLS account",
+ Action: utils.MigrateFlags(blsAccountCreate),
+ ArgsUsage: "",
+ Category: "BLS ACCOUNT COMMANDS",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ },
+ Description: `
+ geth bls account new
+
+Creates a new BLS account and imports the account into the BLS wallet.
+
+If the BLS wallet not created yet, it will try to create BLS wallet first.
+
+The account is saved in encrypted format, you are prompted for a password.
+You must remember this password to unlock your account in the future.`,
+ },
+ {
+ Name: "import",
+ Usage: "Import a BLS account",
+ Action: utils.MigrateFlags(blsAccountImport),
+ ArgsUsage: "",
+ Category: "BLS ACCOUNT COMMANDS",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ },
+ Description: `
+ geth bls account import
+
+Import a encrypted BLS account from keystore file into the BLS wallet.
+
+If the BLS wallet not created yet, it will try to create BLS wallet first.`,
+ },
+ {
+ Name: "list",
+ Usage: "Print summary of existing BLS accounts",
+ Action: utils.MigrateFlags(blsAccountList),
+ ArgsUsage: "",
+ Category: "BLS ACCOUNT COMMANDS",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ },
+ Description: `
+ geth bls account list
+
+Print summary of existing BLS accounts in the current BLS wallet.`,
+ },
+ {
+ Name: "delete",
+ Usage: "Delete the selected BLS account from the BLS wallet",
+ Action: utils.MigrateFlags(blsAccountDelete),
+ ArgsUsage: "",
+ Category: "BLS ACCOUNT COMMANDS",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ },
+ Description: `
+ geth bls account delete
+
+Delete the selected BLS account from the BLS wallet.`,
+ },
+ },
+ },
+ },
+ }
+)
+
+// blsWalletCreate creates a BLS wallet in /bls/wallet.
+func blsWalletCreate(ctx *cli.Context) error {
+ cfg := gethConfig{Node: defaultNodeConfig()}
+ // Load config file.
+ if file := ctx.GlobalString(configFileFlag.Name); file != "" {
+ if err := loadConfig(file, &cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ }
+ utils.SetNodeConfig(ctx, &cfg.Node)
+
+ dir := filepath.Join(cfg.Node.DataDir, BLSWalletPath)
+ dirExists, err := wallet.Exists(dir)
+ if err != nil {
+ utils.Fatalf("Check BLS wallet exists error: %v.", err)
+ }
+ if dirExists {
+ utils.Fatalf("BLS wallet already exists in /bls/wallet.")
+ }
+
+ password := utils.GetPassPhrase("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true)
+
+ opts := []accounts.Option{}
+ opts = append(opts, accounts.WithWalletDir(dir))
+ opts = append(opts, accounts.WithWalletPassword(password))
+ opts = append(opts, accounts.WithKeymanagerType(keymanager.Local))
+ opts = append(opts, accounts.WithSkipMnemonicConfirm(true))
+ acc, err := accounts.NewCLIManager(opts...)
+ if err != nil {
+ utils.Fatalf("New Accounts CLI Manager failed: %v.", err)
+ }
+ if _, err := acc.WalletCreate(context.Background()); err != nil {
+ utils.Fatalf("Create BLS wallet failed: %v.", err)
+ }
+
+ fmt.Println("Create BLS wallet successfully!")
+ return nil
+}
+
+// openOrCreateBLSWallet opens BLS wallet in /bls/wallet, if wallet
+// not exists, then creates BLS wallet in /bls/wallet.
+func openOrCreateBLSWallet(ctx *cli.Context, cfg *gethConfig) (*wallet.Wallet, error) {
+ var w *wallet.Wallet
+ walletDir := filepath.Join(cfg.Node.DataDir, BLSWalletPath)
+ dirExists, err := wallet.Exists(walletDir)
+ if err != nil {
+ utils.Fatalf("Check dir %s failed: %v.", walletDir, err)
+ }
+ if !dirExists {
+ fmt.Println("BLS wallet not exists, creating BLS wallet...")
+ password := utils.GetPassPhrase("Your new BLS wallet will be locked with a password. Please give a password. Do not forget this password.", true)
+
+ opts := []accounts.Option{}
+ opts = append(opts, accounts.WithWalletDir(walletDir))
+ opts = append(opts, accounts.WithWalletPassword(password))
+ opts = append(opts, accounts.WithKeymanagerType(keymanager.Local))
+ opts = append(opts, accounts.WithSkipMnemonicConfirm(true))
+ acc, err := accounts.NewCLIManager(opts...)
+ if err != nil {
+ utils.Fatalf("New Accounts CLI Manager failed: %v.", err)
+ }
+ w, err := acc.WalletCreate(context.Background())
+ if err != nil {
+ utils.Fatalf("Create BLS wallet failed: %v.", err)
+ }
+
+ fmt.Println("Create BLS wallet successfully!")
+ return w, nil
+ }
+
+ walletPassword := utils.GetPassPhrase("Enter the password for your BLS wallet.", false)
+ w, err = wallet.OpenWallet(context.Background(), &wallet.Config{
+ WalletDir: walletDir,
+ WalletPassword: walletPassword,
+ })
+ if err != nil {
+ utils.Fatalf("Open BLS wallet failed: %v.", err)
+ }
+ return w, nil
+}
+
+// blsAccountCreate creates a BLS account in /bls/keystore,
+// and import the created account into the BLS wallet.
+func blsAccountCreate(ctx *cli.Context) error {
+ cfg := gethConfig{Node: defaultNodeConfig()}
+ // Load config file.
+ if file := ctx.GlobalString(configFileFlag.Name); file != "" {
+ if err := loadConfig(file, &cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ }
+ utils.SetNodeConfig(ctx, &cfg.Node)
+
+ w, _ := openOrCreateBLSWallet(ctx, &cfg)
+ if w.KeymanagerKind() != keymanager.Local {
+ utils.Fatalf("BLS wallet has wrong key manager kind.")
+ }
+ km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
+ if err != nil {
+ utils.Fatalf("Initialize key manager failed: %v.", err)
+ }
+ k, ok := km.(keymanager.Importer)
+ if !ok {
+ utils.Fatalf("The BLS keymanager cannot import keystores")
+ }
+
+ keystoreDir := filepath.Join(cfg.Node.DataDir, BLSKeystorePath)
+ if err := os.MkdirAll(keystoreDir, 0755); err != nil {
+ utils.Fatalf("Could not access keystore dir: %v.", err)
+ }
+ accountPassword := utils.GetPassPhrase("Your new BLS account will be encrypted with a password. Please give a password. Do not forget this password.", true)
+ if err := core.ValidatePasswordFormat(accountPassword); err != nil {
+ utils.Fatalf("Password invalid: %v.", err)
+ }
+
+ encryptor := keystorev4.New()
+ secretKey, err := bls.RandKey()
+ if err != nil {
+ utils.Fatalf("Could not generate BLS secret key: %v.", err)
+ }
+ pubKeyBytes := secretKey.PublicKey().Marshal()
+ cryptoFields, err := encryptor.Encrypt(secretKey.Marshal(), accountPassword)
+ if err != nil {
+ utils.Fatalf("Could not encrypt secret key: %v.", err)
+ }
+ id, err := uuid.NewRandom()
+ if err != nil {
+ utils.Fatalf("Could not generate uuid: %v.", err)
+ }
+ keystore := &keymanager.Keystore{
+ Crypto: cryptoFields,
+ ID: id.String(),
+ Pubkey: fmt.Sprintf("%x", pubKeyBytes),
+ Version: encryptor.Version(),
+ Name: encryptor.Name(),
+ }
+
+ encodedFile, err := json.MarshalIndent(keystore, "", "\t")
+ if err != nil {
+ utils.Fatalf("Could not marshal keystore to JSON file: %v.", err)
+ }
+ keystoreFile, err := os.Create(fmt.Sprintf("%s/keystore-%s.json", keystoreDir, petnames.DeterministicName(pubKeyBytes, "-")))
+ if err != nil {
+ utils.Fatalf("Could not create keystore file: %v.", err)
+ }
+ if _, err := keystoreFile.Write(encodedFile); err != nil {
+ utils.Fatalf("Could not write keystore file contents: %v.", err)
+ }
+ fmt.Println("Successfully create a BLS account.")
+
+ fmt.Println("Importing BLS account, this may take a while...")
+ _, err = accounts.ImportAccounts(context.Background(), &accounts.ImportAccountsConfig{
+ Importer: k,
+ Keystores: []*keymanager.Keystore{keystore},
+ AccountPassword: accountPassword,
+ })
+ if err != nil {
+ utils.Fatalf("Import BLS account failed: %v.", err)
+ }
+ fmt.Printf("Successfully import created BLS account.\n")
+ return nil
+}
+
+// blsAccountImport imports a BLS account into the BLS wallet.
+func blsAccountImport(ctx *cli.Context) error {
+ keyfile := ctx.Args().First()
+ if len(keyfile) == 0 {
+ utils.Fatalf("The keystore file must be given as argument.")
+ }
+ keyJSON, err := ioutil.ReadFile(keyfile)
+ if err != nil {
+ utils.Fatalf("Could not read keystore file: %v", err)
+ }
+ keystore := &keymanager.Keystore{}
+ if err := json.Unmarshal(keyJSON, keystore); err != nil {
+ utils.Fatalf("Could not decode keystore file: %v.", err)
+ }
+ if keystore.Pubkey == "" {
+ utils.Fatalf(" Missing public key, wrong keystore file.")
+ }
+
+ cfg := gethConfig{Node: defaultNodeConfig()}
+ // Load config file.
+ if file := ctx.GlobalString(configFileFlag.Name); file != "" {
+ if err := loadConfig(file, &cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ }
+ utils.SetNodeConfig(ctx, &cfg.Node)
+
+ w, _ := openOrCreateBLSWallet(ctx, &cfg)
+ if w.KeymanagerKind() != keymanager.Local {
+ utils.Fatalf("BLS wallet has wrong key manager kind.")
+ }
+ km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
+ if err != nil {
+ utils.Fatalf("Initialize key manager failed: %v.", err)
+ }
+ k, ok := km.(keymanager.Importer)
+ if !ok {
+ utils.Fatalf("The BLS keymanager cannot import keystores")
+ }
+
+ password := utils.GetPassPhrase("Enter the password for your imported account.", false)
+ fmt.Println("Importing BLS account, this may take a while...")
+ _, err = accounts.ImportAccounts(context.Background(), &accounts.ImportAccountsConfig{
+ Importer: k,
+ Keystores: []*keymanager.Keystore{keystore},
+ AccountPassword: password,
+ })
+ if err != nil {
+ utils.Fatalf("Import BLS account failed: %v.", err)
+ }
+ fmt.Println("Successfully import BLS account.")
+ return nil
+}
+
+// blsAccountList prints existing BLS accounts in the BLS wallet.
+func blsAccountList(ctx *cli.Context) error {
+ cfg := gethConfig{Node: defaultNodeConfig()}
+ // Load config file.
+ if file := ctx.GlobalString(configFileFlag.Name); file != "" {
+ if err := loadConfig(file, &cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ }
+ utils.SetNodeConfig(ctx, &cfg.Node)
+
+ walletDir := filepath.Join(cfg.Node.DataDir, BLSWalletPath)
+ dirExists, err := wallet.Exists(walletDir)
+ if err != nil || !dirExists {
+ utils.Fatalf("BLS wallet not exists.")
+ }
+
+ walletPassword := utils.GetPassPhrase("Enter the password for your BLS wallet.", false)
+ w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
+ WalletDir: walletDir,
+ WalletPassword: walletPassword,
+ })
+ if err != nil {
+ utils.Fatalf("Open BLS wallet failed: %v.", err)
+ }
+ km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
+ if err != nil {
+ utils.Fatalf("Initialize key manager failed: %v.", err)
+ }
+
+ ikm, ok := km.(*local.Keymanager)
+ if !ok {
+ utils.Fatalf("Could not assert keymanager interface to concrete type.")
+ }
+ accountNames, err := ikm.ValidatingAccountNames()
+ if err != nil {
+ utils.Fatalf("Could not fetch account names: %v.", err)
+ }
+ numAccounts := au.BrightYellow(len(accountNames))
+ fmt.Printf("(keymanager kind) %s\n", au.BrightGreen("imported wallet").Bold())
+ fmt.Println("")
+ if len(accountNames) == 1 {
+ fmt.Printf("Showing %d BLS account\n", numAccounts)
+ } else {
+ fmt.Printf("Showing %d BLS accounts\n", numAccounts)
+ }
+ pubKeys, err := km.FetchValidatingPublicKeys(context.Background())
+ if err != nil {
+ utils.Fatalf("Could not fetch BLS public keys: %v.", err)
+ }
+ for i := 0; i < len(accountNames); i++ {
+ fmt.Println("")
+ fmt.Printf("%s | %s\n", au.BrightBlue(fmt.Sprintf("Account %d", i)).Bold(), au.BrightGreen(accountNames[i]).Bold())
+ fmt.Printf("%s %#x\n", au.BrightMagenta("[BLS public key]").Bold(), pubKeys[i])
+ }
+ fmt.Println("")
+ return nil
+}
+
+// blsAccountDelete deletes a selected BLS account from the BLS wallet.
+func blsAccountDelete(ctx *cli.Context) error {
+ if len(ctx.Args()) == 0 {
+ utils.Fatalf("No BLS account specified to delete.")
+ }
+ var filteredPubKeys []bls.PublicKey
+ for _, str := range ctx.Args() {
+ pkString := str
+ if strings.Contains(pkString, "0x") {
+ pkString = pkString[2:]
+ }
+ pubKeyBytes, err := hex.DecodeString(pkString)
+ if err != nil {
+ utils.Fatalf("Could not decode string %s as hex.", pkString)
+ }
+ blsPublicKey, err := bls.PublicKeyFromBytes(pubKeyBytes)
+ if err != nil {
+ utils.Fatalf("%#x is not a valid BLS public key.", pubKeyBytes)
+ }
+ filteredPubKeys = append(filteredPubKeys, blsPublicKey)
+ }
+
+ cfg := gethConfig{Node: defaultNodeConfig()}
+ // Load config file.
+ if file := ctx.GlobalString(configFileFlag.Name); file != "" {
+ if err := loadConfig(file, &cfg); err != nil {
+ utils.Fatalf("%v", err)
+ }
+ }
+ utils.SetNodeConfig(ctx, &cfg.Node)
+
+ walletDir := filepath.Join(cfg.Node.DataDir, BLSWalletPath)
+ dirExists, err := wallet.Exists(walletDir)
+ if err != nil || !dirExists {
+ utils.Fatalf("BLS wallet not exists.")
+ }
+
+ walletPassword := utils.GetPassPhrase("Enter the password for your BLS wallet.", false)
+ w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
+ WalletDir: walletDir,
+ WalletPassword: walletPassword,
+ })
+ if err != nil {
+ utils.Fatalf("Open BLS wallet failed: %v.", err)
+ }
+ km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
+ if err != nil {
+ utils.Fatalf("Initialize key manager failed: %v.", err)
+ }
+ pubkeys, err := km.FetchValidatingPublicKeys(context.Background())
+ if err != nil {
+ utils.Fatalf("Could not fetch BLS public keys: %v.", err)
+ }
+
+ rawPublicKeys := make([][]byte, len(filteredPubKeys))
+ formattedPubKeys := make([]string, len(filteredPubKeys))
+ for i, pk := range filteredPubKeys {
+ pubKeyBytes := pk.Marshal()
+ rawPublicKeys[i] = pubKeyBytes
+ formattedPubKeys[i] = fmt.Sprintf("%#x", bytesutil.Trunc(pubKeyBytes))
+ }
+ allAccountStr := strings.Join(formattedPubKeys, ", ")
+ if len(filteredPubKeys) == 1 {
+ promptText := "Are you sure you want to delete 1 account? (%s) Y/N"
+ resp, err := prompt.ValidatePrompt(
+ os.Stdin, fmt.Sprintf(promptText, au.BrightGreen(formattedPubKeys[0])), prompt.ValidateYesOrNo,
+ )
+ if err != nil {
+ return err
+ }
+ if strings.EqualFold(resp, "n") {
+ return nil
+ }
+ } else {
+ promptText := "Are you sure you want to delete %d accounts? (%s) Y/N"
+ if len(filteredPubKeys) == len(pubkeys) {
+ promptText = fmt.Sprintf("Are you sure you want to delete all accounts? Y/N (%s)", au.BrightGreen(allAccountStr))
+ } else {
+ promptText = fmt.Sprintf(promptText, len(filteredPubKeys), au.BrightGreen(allAccountStr))
+ }
+ resp, err := prompt.ValidatePrompt(os.Stdin, promptText, prompt.ValidateYesOrNo)
+ if err != nil {
+ return err
+ }
+ if strings.EqualFold(resp, "n") {
+ return nil
+ }
+ }
+
+ if err := accounts.DeleteAccount(context.Background(), &accounts.DeleteConfig{
+ Keymanager: km,
+ DeletePublicKeys: rawPublicKeys,
+ }); err != nil {
+ utils.Fatalf("Delete account failed: %v.", err)
+ }
+
+ return nil
+}
diff --git a/cmd/geth/main.go b/cmd/geth/main.go
index 6ea505b503..e65ac3dd08 100644
--- a/cmd/geth/main.go
+++ b/cmd/geth/main.go
@@ -72,6 +72,7 @@ var (
utils.DisableSnapProtocolFlag,
utils.DisableDiffProtocolFlag,
utils.EnableTrustProtocolFlag,
+ utils.DisableBscProtocolFlag,
utils.DiffSyncFlag,
utils.PipeCommitFlag,
utils.RangeLimitFlag,
@@ -168,6 +169,9 @@ var (
utils.BlockAmountReserved,
utils.CheckSnapshotWithMPT,
utils.EnableDoubleSignMonitorFlag,
+ utils.BLSPasswordFileFlag,
+ utils.BLSWalletDirFlag,
+ utils.VoteJournalDirFlag,
}
rpcFlags = []cli.Flag{
@@ -251,6 +255,7 @@ func init() {
utils.ShowDeprecated,
// See snapshot.go
snapshotCommand,
+ blsCommand,
}
sort.Sort(cli.CommandsByName(app.Commands))
diff --git a/cmd/geth/usage.go b/cmd/geth/usage.go
index 5054067909..52b3bcd09d 100644
--- a/cmd/geth/usage.go
+++ b/cmd/geth/usage.go
@@ -43,6 +43,7 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.DisableSnapProtocolFlag,
utils.DisableDiffProtocolFlag,
utils.EnableTrustProtocolFlag,
+ utils.DisableBscProtocolFlag,
utils.RangeLimitFlag,
utils.SmartCardDaemonPathFlag,
utils.NetworkIdFlag,
@@ -59,6 +60,9 @@ var AppHelpFlagGroups = []flags.FlagGroup{
utils.TriesInMemoryFlag,
utils.BlockAmountReserved,
utils.CheckSnapshotWithMPT,
+ utils.BLSPasswordFileFlag,
+ utils.BLSWalletDirFlag,
+ utils.VoteJournalDirFlag,
},
},
{
@@ -237,6 +241,12 @@ var AppHelpFlagGroups = []flags.FlagGroup{
cli.HelpFlag,
},
},
+ {
+ Name: "BLS ACCOUNT",
+ Flags: []cli.Flag{
+ utils.DataDirFlag,
+ },
+ },
}
func init() {
diff --git a/cmd/utils/flags.go b/cmd/utils/flags.go
index 9f4e4b6d10..f7b0abcfe0 100644
--- a/cmd/utils/flags.go
+++ b/cmd/utils/flags.go
@@ -25,6 +25,7 @@ import (
"math"
"math/big"
"os"
+ "path/filepath"
"runtime"
godebug "runtime/debug"
"strconv"
@@ -133,6 +134,11 @@ var (
Name: "enabletrustprotocol",
Usage: "Enable trust protocol",
}
+ DisableBscProtocolFlag = cli.BoolFlag{
+ Name: "disablebscprotocol",
+ Usage: "Disable bsc protocol",
+ }
+
DiffSyncFlag = cli.BoolFlag{
Name: "diffsync",
Usage: "Enable diffy sync, Please note that enable diffsync will improve the syncing speed, " +
@@ -890,6 +896,21 @@ var (
Name: "monitor.doublesign",
Usage: "Enable double sign monitor to check whether any validator signs multiple blocks",
}
+
+ BLSPasswordFileFlag = cli.StringFlag{
+ Name: "blspassword",
+ Usage: "File path for the BLS password, which contains the password to unlock BLS wallet for managing votes in fast_finality feature",
+ }
+
+ BLSWalletDirFlag = DirectoryFlag{
+ Name: "blswallet",
+ Usage: "Path for the blsWallet dir in fast finality feature (default = inside the datadir)",
+ }
+
+ VoteJournalDirFlag = DirectoryFlag{
+ Name: "vote-journal-path",
+ Usage: "Path for the voteJournal dir in fast finality feature (default = inside the datadir)",
+ }
)
// MakeDataDir retrieves the currently requested data directory, terminating
@@ -1305,6 +1326,8 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
setDataDir(ctx, cfg)
setSmartCard(ctx, cfg)
setMonitor(ctx, cfg)
+ setBLSWalletDir(ctx, cfg)
+ setVoteJournalDir(ctx, cfg)
if ctx.GlobalIsSet(ExternalSignerFlag.Name) {
cfg.ExternalSigner = ctx.GlobalString(ExternalSignerFlag.Name)
@@ -1337,6 +1360,10 @@ func SetNodeConfig(ctx *cli.Context, cfg *node.Config) {
if ctx.GlobalIsSet(InsecureUnlockAllowedFlag.Name) {
cfg.InsecureUnlockAllowed = ctx.GlobalBool(InsecureUnlockAllowedFlag.Name)
}
+
+ if ctx.GlobalIsSet(BLSPasswordFileFlag.Name) {
+ cfg.BLSPasswordFile = ctx.GlobalString(BLSPasswordFileFlag.Name)
+ }
}
func setSmartCard(ctx *cli.Context, cfg *node.Config) {
@@ -1368,6 +1395,24 @@ func setDataDir(ctx *cli.Context, cfg *node.Config) {
}
}
+func setVoteJournalDir(ctx *cli.Context, cfg *node.Config) {
+ dataDir := cfg.DataDir
+ if ctx.GlobalIsSet(VoteJournalDirFlag.Name) {
+ cfg.VoteJournalDir = ctx.GlobalString(VoteJournalDirFlag.Name)
+ } else {
+ cfg.VoteJournalDir = filepath.Join(dataDir, "voteJournal")
+ }
+}
+
+func setBLSWalletDir(ctx *cli.Context, cfg *node.Config) {
+ dataDir := cfg.DataDir
+ if ctx.GlobalIsSet(BLSWalletDirFlag.Name) {
+ cfg.BLSWalletDir = ctx.GlobalString(BLSWalletDirFlag.Name)
+ } else {
+ cfg.BLSWalletDir = filepath.Join(dataDir, "bls/wallet")
+ }
+}
+
func setGPO(ctx *cli.Context, cfg *gasprice.Config, light bool) {
// If we are running the light client, apply another group
// settings for gas oracle.
@@ -1645,6 +1690,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
if ctx.GlobalIsSet(EnableTrustProtocolFlag.Name) {
cfg.EnableTrustProtocol = ctx.GlobalIsSet(EnableTrustProtocolFlag.Name)
}
+ if ctx.GlobalIsSet(DisableBscProtocolFlag.Name) {
+ cfg.DisableBscProtocol = ctx.GlobalIsSet(DisableBscProtocolFlag.Name)
+ }
if ctx.GlobalIsSet(DiffSyncFlag.Name) {
log.Warn("The --diffsync flag is deprecated and will be removed in the future!")
}
@@ -1721,7 +1769,7 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
cfg.RPCTxFeeCap = ctx.GlobalFloat64(RPCGlobalTxFeeCapFlag.Name)
}
if ctx.GlobalIsSet(NoDiscoverFlag.Name) {
- cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs, cfg.TrustDiscoveryURLs = []string{}, []string{}, []string{}
+ cfg.EthDiscoveryURLs, cfg.SnapDiscoveryURLs, cfg.TrustDiscoveryURLs, cfg.BscDiscoveryURLs = []string{}, []string{}, []string{}, []string{}
} else if ctx.GlobalIsSet(DNSDiscoveryFlag.Name) {
urls := ctx.GlobalString(DNSDiscoveryFlag.Name)
if urls == "" {
@@ -1812,6 +1860,7 @@ func SetDNSDiscoveryDefaults(cfg *ethconfig.Config, genesis common.Hash) {
cfg.EthDiscoveryURLs = []string{url}
cfg.SnapDiscoveryURLs = cfg.EthDiscoveryURLs
cfg.TrustDiscoveryURLs = cfg.EthDiscoveryURLs
+ cfg.BscDiscoveryURLs = cfg.EthDiscoveryURLs
}
}
diff --git a/common/math/integer.go b/common/math/integer.go
index 50d3eba1f5..36643b5bca 100644
--- a/common/math/integer.go
+++ b/common/math/integer.go
@@ -96,3 +96,10 @@ func SafeMul(x, y uint64) (uint64, bool) {
hi, lo := bits.Mul64(x, y)
return lo, hi != 0
}
+
+func CeilDiv(x, y int) int {
+ if y == 0 {
+ return 0
+ }
+ return (x + y - 1) / y
+}
diff --git a/consensus/consensus.go b/consensus/consensus.go
index 87632a9d0d..30c4559043 100644
--- a/consensus/consensus.go
+++ b/consensus/consensus.go
@@ -57,6 +57,10 @@ type ChainHeaderReader interface {
GetHighestVerifiedHeader() *types.Header
}
+type VotePool interface {
+ FetchVoteByBlockHash(blockHash common.Hash) []*types.VoteEnvelope
+}
+
// ChainReader defines a small collection of methods needed to access the local
// blockchain during header and/or uncle verification.
type ChainReader interface {
@@ -148,4 +152,8 @@ type PoSA interface {
EnoughDistance(chain ChainReader, header *types.Header) bool
IsLocalBlock(header *types.Header) bool
AllowLightProcess(chain ChainReader, currentHeader *types.Header) bool
+ GetJustifiedNumberAndHash(chain ChainHeaderReader, header *types.Header) (uint64, common.Hash, error)
+ GetFinalizedHeader(chain ChainHeaderReader, header *types.Header) *types.Header
+ VerifyVote(chain ChainHeaderReader, vote *types.VoteEnvelope) error
+ IsActiveValidatorAt(chain ChainHeaderReader, header *types.Header) bool
}
diff --git a/consensus/parlia/abi.go b/consensus/parlia/abi.go
index e841eb5cd5..16ddb1eab4 100644
--- a/consensus/parlia/abi.go
+++ b/consensus/parlia/abi.go
@@ -1,6 +1,6 @@
package parlia
-const validatorSetABI = `
+const validatorSetABIBeforeBoneh = `
[
{
"anonymous": false,
@@ -1388,7 +1388,1605 @@ const validatorSetABI = `
"stateMutability": "view",
"type": "function"
}
- ]
+]
+`
+
+const validatorSetABI = `
+[
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"batchTransfer",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ },
+ {
+ "indexed":false,
+ "internalType":"string",
+ "name":"reason",
+ "type":"string"
+ }
+ ],
+ "name":"batchTransferFailed",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ },
+ {
+ "indexed":false,
+ "internalType":"bytes",
+ "name":"reason",
+ "type":"bytes"
+ }
+ ],
+ "name":"batchTransferLowerFailed",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ },
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"deprecatedDeposit",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ },
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"deprecatedFinalityRewardDeposit",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address payable",
+ "name":"validator",
+ "type":"address"
+ },
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"directTransfer",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address payable",
+ "name":"validator",
+ "type":"address"
+ },
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"directTransferFail",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":false,
+ "internalType":"string",
+ "name":"message",
+ "type":"string"
+ }
+ ],
+ "name":"failReasonWithStr",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"feeBurned",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ },
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"finalityRewardDeposit",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":false,
+ "internalType":"string",
+ "name":"key",
+ "type":"string"
+ },
+ {
+ "indexed":false,
+ "internalType":"bytes",
+ "name":"value",
+ "type":"bytes"
+ }
+ ],
+ "name":"paramChange",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"systemTransfer",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":false,
+ "internalType":"uint8",
+ "name":"channelId",
+ "type":"uint8"
+ },
+ {
+ "indexed":false,
+ "internalType":"bytes",
+ "name":"msgBytes",
+ "type":"bytes"
+ }
+ ],
+ "name":"unexpectedPackage",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ },
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"validatorDeposit",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ }
+ ],
+ "name":"validatorEmptyJailed",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ }
+ ],
+ "name":"validatorEnterMaintenance",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ }
+ ],
+ "name":"validatorExitMaintenance",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ },
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"validatorFelony",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ }
+ ],
+ "name":"validatorJailed",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+ {
+ "indexed":true,
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ },
+ {
+ "indexed":false,
+ "internalType":"uint256",
+ "name":"amount",
+ "type":"uint256"
+ }
+ ],
+ "name":"validatorMisdemeanor",
+ "type":"event"
+ },
+ {
+ "anonymous":false,
+ "inputs":[
+
+ ],
+ "name":"validatorSetUpdated",
+ "type":"event"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"BIND_CHANNELID",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"BURN_ADDRESS",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"BURN_RATIO_SCALE",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"CODE_OK",
+ "outputs":[
+ {
+ "internalType":"uint32",
+ "name":"",
+ "type":"uint32"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"CROSS_CHAIN_CONTRACT_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"CROSS_STAKE_CHANNELID",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"DUSTY_INCOMING",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"EPOCH",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"ERROR_FAIL_CHECK_VALIDATORS",
+ "outputs":[
+ {
+ "internalType":"uint32",
+ "name":"",
+ "type":"uint32"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"ERROR_FAIL_DECODE",
+ "outputs":[
+ {
+ "internalType":"uint32",
+ "name":"",
+ "type":"uint32"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"ERROR_LEN_OF_VAL_MISMATCH",
+ "outputs":[
+ {
+ "internalType":"uint32",
+ "name":"",
+ "type":"uint32"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"ERROR_RELAYFEE_TOO_LARGE",
+ "outputs":[
+ {
+ "internalType":"uint32",
+ "name":"",
+ "type":"uint32"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"ERROR_UNKNOWN_PACKAGE_TYPE",
+ "outputs":[
+ {
+ "internalType":"uint32",
+ "name":"",
+ "type":"uint32"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"EXPIRE_TIME_SECOND_GAP",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"GOV_CHANNELID",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"GOV_HUB_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"INCENTIVIZE_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"INIT_BURN_RATIO",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"INIT_FINALITY_REWARD_RATIO",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"INIT_MAINTAIN_SLASH_SCALE",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"INIT_MAX_NUM_OF_MAINTAINING",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"INIT_NUM_OF_CABINETS",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"INIT_VALIDATORSET_BYTES",
+ "outputs":[
+ {
+ "internalType":"bytes",
+ "name":"",
+ "type":"bytes"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"JAIL_MESSAGE_TYPE",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"LIGHT_CLIENT_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"MAX_NUM_OF_VALIDATORS",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"PRECISION",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"RELAYERHUB_CONTRACT_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"SLASH_CHANNELID",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"SLASH_CONTRACT_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"STAKING_CHANNELID",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"STAKING_CONTRACT_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"SYSTEM_REWARD_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"TOKEN_HUB_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"TOKEN_MANAGER_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"TRANSFER_IN_CHANNELID",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"TRANSFER_OUT_CHANNELID",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"VALIDATORS_UPDATE_MESSAGE_TYPE",
+ "outputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"VALIDATOR_CONTRACT_ADDR",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"alreadyInit",
+ "outputs":[
+ {
+ "internalType":"bool",
+ "name":"",
+ "type":"bool"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"bscChainID",
+ "outputs":[
+ {
+ "internalType":"uint16",
+ "name":"",
+ "type":"uint16"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"burnRatio",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"burnRatioInitialized",
+ "outputs":[
+ {
+ "internalType":"bool",
+ "name":"",
+ "type":"bool"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"uint256",
+ "name":"index",
+ "type":"uint256"
+ }
+ ],
+ "name":"canEnterMaintenance",
+ "outputs":[
+ {
+ "internalType":"bool",
+ "name":"",
+ "type":"bool"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "name":"currentValidatorSet",
+ "outputs":[
+ {
+ "internalType":"address",
+ "name":"consensusAddress",
+ "type":"address"
+ },
+ {
+ "internalType":"address payable",
+ "name":"feeAddress",
+ "type":"address"
+ },
+ {
+ "internalType":"address",
+ "name":"BBCFeeAddress",
+ "type":"address"
+ },
+ {
+ "internalType":"uint64",
+ "name":"votingPower",
+ "type":"uint64"
+ },
+ {
+ "internalType":"bool",
+ "name":"jailed",
+ "type":"bool"
+ },
+ {
+ "internalType":"uint256",
+ "name":"incoming",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"address",
+ "name":"",
+ "type":"address"
+ }
+ ],
+ "name":"currentValidatorSetMap",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"address",
+ "name":"valAddr",
+ "type":"address"
+ }
+ ],
+ "name":"deposit",
+ "outputs":[
+
+ ],
+ "stateMutability":"payable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"address[]",
+ "name":"valAddrs",
+ "type":"address[]"
+ },
+ {
+ "internalType":"uint256[]",
+ "name":"weights",
+ "type":"uint256[]"
+ }
+ ],
+ "name":"distributeFinalityReward",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"enterMaintenance",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"exitMaintenance",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"expireTimeSecondGap",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ }
+ ],
+ "name":"felony",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"finalityRewardRatio",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"address",
+ "name":"_validator",
+ "type":"address"
+ }
+ ],
+ "name":"getCurrentValidatorIndex",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ }
+ ],
+ "name":"getIncoming",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"getLivingValidators",
+ "outputs":[
+ {
+ "internalType":"address[]",
+ "name":"",
+ "type":"address[]"
+ },
+ {
+ "internalType":"bytes[]",
+ "name":"",
+ "type":"bytes[]"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"getMiningValidators",
+ "outputs":[
+ {
+ "internalType":"address[]",
+ "name":"",
+ "type":"address[]"
+ },
+ {
+ "internalType":"bytes[]",
+ "name":"",
+ "type":"bytes[]"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"getValidators",
+ "outputs":[
+ {
+ "internalType":"address[]",
+ "name":"",
+ "type":"address[]"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"getWorkingValidatorCount",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"workingValidatorCount",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"uint8",
+ "name":"channelId",
+ "type":"uint8"
+ },
+ {
+ "internalType":"bytes",
+ "name":"msgBytes",
+ "type":"bytes"
+ }
+ ],
+ "name":"handleAckPackage",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"uint8",
+ "name":"channelId",
+ "type":"uint8"
+ },
+ {
+ "internalType":"bytes",
+ "name":"msgBytes",
+ "type":"bytes"
+ }
+ ],
+ "name":"handleFailAckPackage",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"uint8",
+ "name":"",
+ "type":"uint8"
+ },
+ {
+ "internalType":"bytes",
+ "name":"msgBytes",
+ "type":"bytes"
+ }
+ ],
+ "name":"handleSynPackage",
+ "outputs":[
+ {
+ "internalType":"bytes",
+ "name":"responsePayload",
+ "type":"bytes"
+ }
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"init",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ }
+ ],
+ "name":"isCurrentValidator",
+ "outputs":[
+ {
+ "internalType":"bool",
+ "name":"",
+ "type":"bool"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"uint256",
+ "name":"index",
+ "type":"uint256"
+ }
+ ],
+ "name":"isWorkingValidator",
+ "outputs":[
+ {
+ "internalType":"bool",
+ "name":"",
+ "type":"bool"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"maintainSlashScale",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"maxNumOfCandidates",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"maxNumOfMaintaining",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"maxNumOfWorkingCandidates",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"address",
+ "name":"validator",
+ "type":"address"
+ }
+ ],
+ "name":"misdemeanor",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"numOfCabinets",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"numOfJailed",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"numOfMaintaining",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"previousHeight",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+
+ ],
+ "name":"totalInComing",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"string",
+ "name":"key",
+ "type":"string"
+ },
+ {
+ "internalType":"bytes",
+ "name":"value",
+ "type":"bytes"
+ }
+ ],
+ "name":"updateParam",
+ "outputs":[
+
+ ],
+ "stateMutability":"nonpayable",
+ "type":"function"
+ },
+ {
+ "inputs":[
+ {
+ "internalType":"uint256",
+ "name":"",
+ "type":"uint256"
+ }
+ ],
+ "name":"validatorExtraSet",
+ "outputs":[
+ {
+ "internalType":"uint256",
+ "name":"enterMaintenanceHeight",
+ "type":"uint256"
+ },
+ {
+ "internalType":"bool",
+ "name":"isMaintaining",
+ "type":"bool"
+ },
+ {
+ "internalType":"bytes",
+ "name":"voteAddress",
+ "type":"bytes"
+ }
+ ],
+ "stateMutability":"view",
+ "type":"function"
+ },
+ {
+ "stateMutability":"payable",
+ "type":"receive"
+ }
+]
`
const slashABI = `
diff --git a/consensus/parlia/bonehFork.go b/consensus/parlia/bonehFork.go
new file mode 100644
index 0000000000..f8a262b406
--- /dev/null
+++ b/consensus/parlia/bonehFork.go
@@ -0,0 +1,49 @@
+package parlia
+
+import (
+ "context"
+ "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/systemcontracts"
+ "github.com/ethereum/go-ethereum/internal/ethapi"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/rpc"
+)
+
+func (p *Parlia) getCurrentValidatorsBeforeBoneh(blockHash common.Hash, blockNumber *big.Int) ([]common.Address, error) {
+ blockNr := rpc.BlockNumberOrHashWithHash(blockHash, false)
+
+ // prepare different method
+ method := "getValidators"
+ if p.chainConfig.IsEuler(blockNumber) {
+ method = "getMiningValidators"
+ }
+
+ ctx, cancel := context.WithCancel(context.Background())
+ // cancel when we are finished consuming integers
+ defer cancel()
+ data, err := p.validatorSetABIBeforeBoneh.Pack(method)
+ if err != nil {
+ log.Error("Unable to pack tx for getValidators", "error", err)
+ return nil, err
+ }
+ // do smart contract call
+ msgData := (hexutil.Bytes)(data)
+ toAddress := common.HexToAddress(systemcontracts.ValidatorContract)
+ gas := (hexutil.Uint64)(uint64(math.MaxUint64 / 2))
+ result, err := p.ethAPI.Call(ctx, ethapi.TransactionArgs{
+ Gas: &gas,
+ To: &toAddress,
+ Data: &msgData,
+ }, blockNr, nil)
+ if err != nil {
+ return nil, err
+ }
+
+ var valSet []common.Address
+ err = p.validatorSetABIBeforeBoneh.UnpackIntoInterface(&valSet, method, result)
+ return valSet, err
+}
diff --git a/consensus/parlia/parlia.go b/consensus/parlia/parlia.go
index 7a483a8fb4..aaa2f32cb1 100644
--- a/consensus/parlia/parlia.go
+++ b/consensus/parlia/parlia.go
@@ -16,6 +16,8 @@ import (
"time"
lru "github.com/hashicorp/golang-lru"
+ "github.com/prysmaticlabs/prysm/v3/crypto/bls"
+ "github.com/willf/bitset"
"golang.org/x/crypto/sha3"
"github.com/ethereum/go-ethereum"
@@ -24,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/gopool"
"github.com/ethereum/go-ethereum/common/hexutil"
+ cmath "github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/consensus/misc"
"github.com/ethereum/go-ethereum/core"
@@ -53,13 +56,17 @@ const (
extraSeal = 65 // Fixed number of extra-data suffix bytes reserved for signer seal
nextForkHashSize = 4 // Fixed number of extra-data suffix bytes reserved for nextForkHash.
- validatorBytesLength = common.AddressLength
- wiggleTime = uint64(1) // second, Random delay (per signer) to allow concurrent signers
- initialBackOffTime = uint64(1) // second
- processBackOffTime = uint64(1) // second
+ validatorBytesLengthBeforeBoneh = common.AddressLength
+ validatorBytesLength = common.AddressLength + types.BLSPublicKeyLength
+ validatorNumberSize = 1 // Fixed number of extra prefix bytes reserved for validator number after Boneh
+
+ wiggleTime = uint64(1) // second, Random delay (per signer) to allow concurrent signers
+ initialBackOffTime = uint64(1) // second
+ processBackOffTime = uint64(1) // second
systemRewardPercent = 4 // it means 1/2^4 = 1/16 percentage of gas fee incoming will be distributed to system
+ collectAdditionalVotesRewardRatio = float64(1) // ratio of additional reward for collecting more votes than needed
)
var (
@@ -208,9 +215,11 @@ type Parlia struct {
lock sync.RWMutex // Protects the signer fields
- ethAPI *ethapi.PublicBlockChainAPI
- validatorSetABI abi.ABI
- slashABI abi.ABI
+ ethAPI *ethapi.PublicBlockChainAPI
+ VotePool consensus.VotePool
+ validatorSetABIBeforeBoneh abi.ABI
+ validatorSetABI abi.ABI
+ slashABI abi.ABI
// The fields below are for testing only
fakeDiff bool // Skip difficulty verifications
@@ -240,6 +249,10 @@ func New(
if err != nil {
panic(err)
}
+ vABIBeforeBoneh, err := abi.JSON(strings.NewReader(validatorSetABIBeforeBoneh))
+ if err != nil {
+ panic(err)
+ }
vABI, err := abi.JSON(strings.NewReader(validatorSetABI))
if err != nil {
panic(err)
@@ -249,16 +262,17 @@ func New(
panic(err)
}
c := &Parlia{
- chainConfig: chainConfig,
- config: parliaConfig,
- genesisHash: genesisHash,
- db: db,
- ethAPI: ethAPI,
- recentSnaps: recentSnaps,
- signatures: signatures,
- validatorSetABI: vABI,
- slashABI: sABI,
- signer: types.NewEIP155Signer(chainConfig.ChainID),
+ chainConfig: chainConfig,
+ config: parliaConfig,
+ genesisHash: genesisHash,
+ db: db,
+ ethAPI: ethAPI,
+ recentSnaps: recentSnaps,
+ signatures: signatures,
+ validatorSetABIBeforeBoneh: vABIBeforeBoneh,
+ validatorSetABI: vABI,
+ slashABI: sABI,
+ signer: types.NewEIP155Signer(chainConfig.ChainID),
}
return c
@@ -317,6 +331,160 @@ func (p *Parlia) VerifyHeaders(chain consensus.ChainHeaderReader, headers []*typ
return abort, results
}
+// getValidatorBytesFromHeader returns the validators bytes extracted from the header's extra field if exists.
+// The validators bytes would be contained only in the epoch block's header, and its each validator bytes length is fixed.
+// On boneh fork, we introduce vote attestation into the header's extra field, so extra format is different from before.
+// Before boneh fork: |---Extra Vanity---|---Validators Bytes (or Empty)---|---Extra Seal---|
+// After boneh fork: |---Extra Vanity---|---Validators Number and Validators Bytes (or Empty)---|---Vote Attestation (or Empty)---|---Extra Seal---|
+func getValidatorBytesFromHeader(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) []byte {
+ if len(header.Extra) <= extraVanity+extraSeal {
+ return nil
+ }
+
+ if !chainConfig.IsBoneh(header.Number) {
+ if header.Number.Uint64()%parliaConfig.Epoch == 0 && (len(header.Extra)-extraSeal-extraVanity)%validatorBytesLengthBeforeBoneh != 0 {
+ return nil
+ }
+ return header.Extra[extraVanity : len(header.Extra)-extraSeal]
+ }
+
+ if header.Number.Uint64()%parliaConfig.Epoch != 0 {
+ return nil
+ }
+ num := int(header.Extra[extraVanity])
+ if num == 0 || len(header.Extra) <= extraVanity+extraSeal+num*validatorBytesLength {
+ return nil
+ }
+ start := extraVanity + validatorNumberSize
+ end := start + num*validatorBytesLength
+ return header.Extra[start:end]
+}
+
+// getVoteAttestationFromHeader returns the vote attestation extracted from the header's extra field if exists.
+func getVoteAttestationFromHeader(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) (*types.VoteAttestation, error) {
+ if len(header.Extra) <= extraVanity+extraSeal {
+ return nil, nil
+ }
+
+ if !chainConfig.IsBoneh(header.Number) {
+ return nil, nil
+ }
+
+ var attestationBytes []byte
+ if header.Number.Uint64()%parliaConfig.Epoch != 0 {
+ attestationBytes = header.Extra[extraVanity : len(header.Extra)-extraSeal]
+ } else {
+ num := int(header.Extra[extraVanity])
+ if len(header.Extra) <= extraVanity+extraSeal+validatorNumberSize+num*validatorBytesLength {
+ return nil, nil
+ }
+ start := extraVanity + validatorNumberSize + num*validatorBytesLength
+ end := len(header.Extra) - extraSeal
+ attestationBytes = header.Extra[start:end]
+ }
+
+ var attestation types.VoteAttestation
+ if err := rlp.Decode(bytes.NewReader(attestationBytes), &attestation); err != nil {
+ return nil, fmt.Errorf("block %d has vote attestation info, decode err: %s", header.Number.Uint64(), err)
+ }
+ return &attestation, nil
+}
+
+// verifyVoteAttestation checks whether the vote attestation in the header is valid.
+func (p *Parlia) verifyVoteAttestation(chain consensus.ChainHeaderReader, header *types.Header, parents []*types.Header) error {
+ attestation, err := getVoteAttestationFromHeader(header, p.chainConfig, p.config)
+ if err != nil {
+ return err
+ }
+ if attestation == nil {
+ return nil
+ }
+ if attestation.Data == nil {
+ return fmt.Errorf("invalid attestation, vote data is nil")
+ }
+ if len(attestation.Extra) > types.MaxAttestationExtraLength {
+ return fmt.Errorf("invalid attestation, too large extra length: %d", len(attestation.Extra))
+ }
+
+ // Get parent block
+ number := header.Number.Uint64()
+ var parent *types.Header
+ if len(parents) > 0 {
+ parent = parents[len(parents)-1]
+ } else {
+ parent = chain.GetHeader(header.ParentHash, number-1)
+ }
+ if parent == nil || parent.Hash() != header.ParentHash {
+ return consensus.ErrUnknownAncestor
+ }
+
+ // The target block should be direct parent.
+ targetNumber := attestation.Data.TargetNumber
+ targetHash := attestation.Data.TargetHash
+ if targetNumber != parent.Number.Uint64() || targetHash != parent.Hash() {
+ return fmt.Errorf("invalid attestation, target mismatch, expected block: %d, hash: %s; real block: %d, hash: %s",
+ parent.Number.Uint64(), parent.Hash(), targetNumber, targetHash)
+ }
+
+ // The source block should be the highest justified block.
+ sourceNumber := attestation.Data.SourceNumber
+ sourceHash := attestation.Data.SourceHash
+ justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent)
+ if err != nil {
+ return fmt.Errorf("unexpected error when getting the highest justified number and hash")
+ }
+ if sourceNumber != justifiedBlockNumber || sourceHash != justifiedBlockHash {
+ return fmt.Errorf("invalid attestation, source mismatch, expected block: %d, hash: %s; real block: %d, hash: %s",
+ justifiedBlockNumber, justifiedBlockHash, sourceNumber, sourceHash)
+ }
+
+ // The snapshot should be the targetNumber-1 block's snapshot.
+ if len(parents) > 1 {
+ parents = parents[:len(parents)-1]
+ } else {
+ parents = nil
+ }
+ snap, err := p.snapshot(chain, parent.Number.Uint64()-1, parent.ParentHash, parents)
+ if err != nil {
+ return err
+ }
+
+ // Filter out valid validator from attestation.
+ validators := snap.validators()
+ validatorsBitSet := bitset.From([]uint64{uint64(attestation.VoteAddressSet)})
+ if validatorsBitSet.Count() > uint(len(validators)) {
+ return fmt.Errorf("invalid attestation, vote number larger than validators number")
+ }
+ votedAddrs := make([]bls.PublicKey, 0, validatorsBitSet.Count())
+ for index, val := range validators {
+ if !validatorsBitSet.Test(uint(index)) {
+ continue
+ }
+
+ voteAddr, err := bls.PublicKeyFromBytes(snap.Validators[val].VoteAddress[:])
+ if err != nil {
+ return fmt.Errorf("BLS public key converts failed: %v", err)
+ }
+ votedAddrs = append(votedAddrs, voteAddr)
+ }
+
+ // The valid voted validators should be no less than 2/3 validators.
+ if len(votedAddrs) < cmath.CeilDiv(len(snap.Validators)*2, 3) {
+ return fmt.Errorf("invalid attestation, not enough validators voted")
+ }
+
+ // Verify the aggregated signature.
+ aggSig, err := bls.SignatureFromBytes(attestation.AggSignature[:])
+ if err != nil {
+ return fmt.Errorf("BLS signature converts failed: %v", err)
+ }
+ if !aggSig.FastAggregateVerify(votedAddrs, attestation.Data.Hash()) {
+ return fmt.Errorf("invalid attestation, signature verify failed")
+ }
+
+ return nil
+}
+
// verifyHeader checks whether a header conforms to the consensus rules.The
// caller may optionally pass in a batch of parents (ascending order) to avoid
// looking those up from the database. This is useful for concurrently verifying
@@ -325,7 +493,6 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
if header.Number == nil {
return errUnknownBlock
}
- number := header.Number.Uint64()
// Don't waste time checking blocks from the future
if header.Time > uint64(time.Now().Unix()) {
@@ -338,16 +505,17 @@ func (p *Parlia) verifyHeader(chain consensus.ChainHeaderReader, header *types.H
if len(header.Extra) < extraVanity+extraSeal {
return errMissingSignature
}
+
// check extra data
+ number := header.Number.Uint64()
isEpoch := number%p.config.Epoch == 0
// Ensure that the extra-data contains a signer list on checkpoint, but none otherwise
- signersBytes := len(header.Extra) - extraVanity - extraSeal
- if !isEpoch && signersBytes != 0 {
+ signersBytes := getValidatorBytesFromHeader(header, p.chainConfig, p.config)
+ if !isEpoch && len(signersBytes) != 0 {
return errExtraValidators
}
-
- if isEpoch && signersBytes%validatorBytesLength != 0 {
+ if isEpoch && len(signersBytes) == 0 {
return errInvalidSpanValidators
}
@@ -426,11 +594,23 @@ func (p *Parlia) verifyCascadingFields(chain consensus.ChainHeaderReader, header
return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
}
+ // Verify vote attestation for fast finality.
+ if err := p.verifyVoteAttestation(chain, header, parents); err != nil {
+ if chain.Config().IsLynn(header.Number) {
+ return err
+ }
+ log.Warn("Verify vote attestation failed", "error", err, "hash", header.Hash(), "number", header.Number,
+ "parent", header.ParentHash, "coinbase", header.Coinbase, "extra", common.Bytes2Hex(header.Extra))
+ }
+
// All basic checks passed, verify the seal and return
return p.verifySeal(chain, header, parents)
}
// snapshot retrieves the authorization snapshot at a given point in time.
+// !!! be careful
+// the block with `number` and `hash` is just the last element of `parents`,
+// unlike other interfaces such as verifyCascadingFields, `parents` are real parents
func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash common.Hash, parents []*types.Header) (*Snapshot, error) {
// Search for a snapshot in memory or on disk for checkpoints
var (
@@ -463,18 +643,14 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
// get checkpoint data
hash := checkpoint.Hash()
- if len(checkpoint.Extra) <= extraVanity+extraSeal {
- return nil, errors.New("invalid extra-data for genesis block, check the genesis.json file")
- }
- validatorBytes := checkpoint.Extra[extraVanity : len(checkpoint.Extra)-extraSeal]
// get validators from headers
- validators, err := ParseValidators(validatorBytes)
+ validators, voteAddrs, err := parseValidators(checkpoint, p.chainConfig, p.config)
if err != nil {
return nil, err
}
- // new snap shot
- snap = newSnapshot(p.config, p.signatures, number, hash, validators, p.ethAPI)
+ // new snapshot
+ snap = newSnapshot(p.config, p.signatures, number, hash, validators, voteAddrs, p.ethAPI)
if err := snap.store(p.db); err != nil {
return nil, err
}
@@ -513,7 +689,15 @@ func (p *Parlia) snapshot(chain consensus.ChainHeaderReader, number uint64, hash
headers[i], headers[len(headers)-1-i] = headers[len(headers)-1-i], headers[i]
}
- snap, err := snap.apply(headers, chain, parents, p.chainConfig.ChainID)
+ verifiedAttestations := make(map[common.Hash]struct{}, len(headers))
+ for index, header := range headers {
+ // vote attestation should be checked here to decide whether to update attestation of snapshot between [Boneh,Lynn)
+ // because err of verifyVoteAttestation is ignored when importing blocks and headers before Lynn.
+ if p.chainConfig.IsBoneh(header.Number) && !p.chainConfig.IsLynn(header.Number) && p.verifyVoteAttestation(chain, header, headers[:index]) == nil {
+ verifiedAttestations[header.Hash()] = struct{}{}
+ }
+ }
+ snap, err := snap.apply(headers, chain, parents, p.chainConfig, verifiedAttestations)
if err != nil {
return nil, err
}
@@ -597,6 +781,109 @@ func (p *Parlia) verifySeal(chain consensus.ChainHeaderReader, header *types.Hea
return nil
}
+func (p *Parlia) prepareValidators(header *types.Header) error {
+ if header.Number.Uint64()%p.config.Epoch != 0 {
+ return nil
+ }
+
+ newValidators, voteAddressMap, err := p.getCurrentValidators(header.ParentHash, new(big.Int).Sub(header.Number, big.NewInt(1)))
+ if err != nil {
+ return err
+ }
+ // sort validator by address
+ sort.Sort(validatorsAscending(newValidators))
+ if !p.chainConfig.IsBoneh(header.Number) {
+ for _, validator := range newValidators {
+ header.Extra = append(header.Extra, validator.Bytes()...)
+ }
+ } else {
+ header.Extra = append(header.Extra, byte(len(newValidators)))
+ for _, validator := range newValidators {
+ header.Extra = append(header.Extra, validator.Bytes()...)
+ header.Extra = append(header.Extra, voteAddressMap[validator].Bytes()...)
+ }
+ }
+ return nil
+}
+
+func (p *Parlia) assembleVoteAttestation(chain consensus.ChainHeaderReader, header *types.Header) error {
+ if !p.chainConfig.IsBoneh(header.Number) || header.Number.Uint64() < 2 {
+ return nil
+ }
+
+ if p.VotePool == nil {
+ return errors.New("vote pool is nil")
+ }
+
+ // Fetch direct parent's votes
+ parent := chain.GetHeaderByHash(header.ParentHash)
+ if parent == nil {
+ return errors.New("parent not found")
+ }
+ snap, err := p.snapshot(chain, parent.Number.Uint64()-1, parent.ParentHash, nil)
+ if err != nil {
+ return err
+ }
+ votes := p.VotePool.FetchVoteByBlockHash(parent.Hash())
+ if len(votes) < cmath.CeilDiv(len(snap.Validators)*2, 3) {
+ return nil
+ }
+
+ // Prepare vote attestation
+ // Prepare vote data
+ justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, parent)
+ if err != nil {
+ return fmt.Errorf("unexpected error when getting the highest justified number and hash")
+ }
+ attestation := &types.VoteAttestation{
+ Data: &types.VoteData{
+ SourceNumber: justifiedBlockNumber,
+ SourceHash: justifiedBlockHash,
+ TargetNumber: parent.Number.Uint64(),
+ TargetHash: parent.Hash(),
+ },
+ }
+ // Check vote data from votes
+ for _, vote := range votes {
+ if vote.Data.Hash() != attestation.Data.Hash() {
+ return fmt.Errorf("vote check error, expected: %v, real: %v", attestation.Data, vote)
+ }
+ }
+ // Prepare aggregated vote signature
+ voteAddrSet := make(map[types.BLSPublicKey]struct{}, len(votes))
+ signatures := make([][]byte, 0, len(votes))
+ for _, vote := range votes {
+ voteAddrSet[vote.VoteAddress] = struct{}{}
+ signatures = append(signatures, vote.Signature[:])
+ }
+ sigs, err := bls.MultipleSignaturesFromBytes(signatures)
+ if err != nil {
+ return err
+ }
+ copy(attestation.AggSignature[:], bls.AggregateSignatures(sigs).Marshal())
+ // Prepare vote address bitset.
+ for _, valInfo := range snap.Validators {
+ if _, ok := voteAddrSet[valInfo.VoteAddress]; ok {
+ attestation.VoteAddressSet |= 1 << (valInfo.Index - 1) //Index is offset by 1
+ }
+ }
+
+ // Append attestation to header extra field.
+ buf := new(bytes.Buffer)
+ err = rlp.Encode(buf, attestation)
+ if err != nil {
+ return err
+ }
+
+ // Insert vote attestation into header extra ahead extra seal.
+ extraSealStart := len(header.Extra) - extraSeal
+ extraSealBytes := header.Extra[extraSealStart:]
+ header.Extra = append(header.Extra[0:extraSealStart], buf.Bytes()...)
+ header.Extra = append(header.Extra, extraSealBytes...)
+
+ return nil
+}
+
// Prepare implements consensus.Engine, preparing all the consensus fields of the
// header for running the transactions on top.
func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header) error {
@@ -620,16 +907,8 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header
nextForkHash := forkid.NextForkHash(p.chainConfig, p.genesisHash, number)
header.Extra = append(header.Extra, nextForkHash[:]...)
- if number%p.config.Epoch == 0 {
- newValidators, err := p.getCurrentValidators(header.ParentHash, new(big.Int).Sub(header.Number, common.Big1))
- if err != nil {
- return err
- }
- // sort validator by address
- sort.Sort(validatorsAscending(newValidators))
- for _, validator := range newValidators {
- header.Extra = append(header.Extra, validator.Bytes()...)
- }
+ if err := p.prepareValidators(header); err != nil {
+ return err
}
// add extra seal space
@@ -650,6 +929,114 @@ func (p *Parlia) Prepare(chain consensus.ChainHeaderReader, header *types.Header
return nil
}
+func (p *Parlia) verifyValidators(header *types.Header) error {
+ if header.Number.Uint64()%p.config.Epoch != 0 {
+ return nil
+ }
+
+ newValidators, voteAddressMap, err := p.getCurrentValidators(header.ParentHash, new(big.Int).Sub(header.Number, big.NewInt(1)))
+ if err != nil {
+ return err
+ }
+ // sort validator by address
+ sort.Sort(validatorsAscending(newValidators))
+ var validatorsBytes []byte
+ validatorsNumber := len(newValidators)
+ if !p.chainConfig.IsBoneh(header.Number) {
+ validatorsBytes = make([]byte, validatorsNumber*validatorBytesLengthBeforeBoneh)
+ for i, validator := range newValidators {
+ copy(validatorsBytes[i*validatorBytesLengthBeforeBoneh:], validator.Bytes())
+ }
+ } else {
+ if uint8(validatorsNumber) != header.Extra[extraVanity] {
+ return errMismatchingEpochValidators
+ }
+ validatorsBytes = make([]byte, validatorsNumber*validatorBytesLength)
+ for i, validator := range newValidators {
+ copy(validatorsBytes[i*validatorBytesLength:], validator.Bytes())
+ copy(validatorsBytes[i*validatorBytesLength+common.AddressLength:], voteAddressMap[validator].Bytes())
+ }
+ }
+ if !bytes.Equal(getValidatorBytesFromHeader(header, p.chainConfig, p.config), validatorsBytes) {
+ return errMismatchingEpochValidators
+ }
+ return nil
+}
+
+func (p *Parlia) distributeFinalityReward(chain consensus.ChainHeaderReader, state *state.StateDB, header *types.Header,
+ cx core.ChainContext, txs *[]*types.Transaction, receipts *[]*types.Receipt, systemTxs *[]*types.Transaction,
+ usedGas *uint64, mining bool) error {
+ currentHeight := header.Number.Uint64()
+ epoch := p.config.Epoch
+ chainConfig := chain.Config()
+ if currentHeight%epoch != 0 {
+ return nil
+ }
+
+ head := header
+ accumulatedWeights := make(map[common.Address]uint64)
+ for height := currentHeight - 1; height+epoch >= currentHeight && height >= 1; height-- {
+ head = chain.GetHeaderByHash(head.ParentHash)
+ if head == nil {
+ return fmt.Errorf("header is nil at height %d", height)
+ }
+ voteAttestation, err := getVoteAttestationFromHeader(head, chainConfig, p.config)
+ if err != nil {
+ return err
+ }
+ if voteAttestation == nil {
+ continue
+ }
+ justifiedBlock := chain.GetHeaderByHash(voteAttestation.Data.TargetHash)
+ if justifiedBlock == nil {
+ log.Warn("justifiedBlock is nil at height %d", voteAttestation.Data.TargetNumber)
+ continue
+ }
+
+ snap, err := p.snapshot(chain, justifiedBlock.Number.Uint64()-1, justifiedBlock.ParentHash, nil)
+ if err != nil {
+ return err
+ }
+ validators := snap.validators()
+ validatorsBitSet := bitset.From([]uint64{uint64(voteAttestation.VoteAddressSet)})
+ if validatorsBitSet.Count() > uint(len(validators)) {
+ log.Error("invalid attestation, vote number larger than validators number")
+ continue
+ }
+ validVoteCount := 0
+ for index, val := range validators {
+ if validatorsBitSet.Test(uint(index)) {
+ accumulatedWeights[val] += 1
+ validVoteCount += 1
+ }
+ }
+ quorum := cmath.CeilDiv(len(snap.Validators)*2, 3)
+ if validVoteCount > quorum {
+ accumulatedWeights[head.Coinbase] += uint64(float64(validVoteCount-quorum) * collectAdditionalVotesRewardRatio)
+ }
+ }
+
+ validators := make([]common.Address, 0, len(accumulatedWeights))
+ weights := make([]*big.Int, 0, len(accumulatedWeights))
+ for val := range accumulatedWeights {
+ validators = append(validators, val)
+ }
+ sort.Sort(validatorsAscending(validators))
+ for _, val := range validators {
+ weights = append(weights, big.NewInt(int64(accumulatedWeights[val])))
+ }
+
+ // generate system transaction
+ method := "distributeFinalityReward"
+ data, err := p.validatorSetABI.Pack(method, validators, weights)
+ if err != nil {
+ log.Error("Unable to pack tx for distributeFinalityReward", "error", err)
+ return err
+ }
+ msg := p.getSystemMessage(header.Coinbase, common.HexToAddress(systemcontracts.ValidatorContract), data, common.Big0)
+ return p.applyTransaction(msg, state, header, cx, txs, receipts, systemTxs, usedGas, mining)
+}
+
// Finalize implements consensus.Engine, ensuring no uncles are set, nor block
// rewards given.
func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Header, state *state.StateDB, txs *[]*types.Transaction,
@@ -664,27 +1051,15 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
if !snap.isMajorityFork(hex.EncodeToString(nextForkHash[:])) {
log.Debug("there is a possible fork, and your client is not the majority. Please check...", "nextForkHash", hex.EncodeToString(nextForkHash[:]))
}
- // If the block is a epoch end block, verify the validator list
+ // If the block is an epoch end block, verify the validator list
// The verification can only be done when the state is ready, it can't be done in VerifyHeader.
- if header.Number.Uint64()%p.config.Epoch == 0 {
- newValidators, err := p.getCurrentValidators(header.ParentHash, new(big.Int).Sub(header.Number, common.Big1))
- if err != nil {
- return err
- }
- // sort validator by address
- sort.Sort(validatorsAscending(newValidators))
- validatorsBytes := make([]byte, len(newValidators)*validatorBytesLength)
- for i, validator := range newValidators {
- copy(validatorsBytes[i*validatorBytesLength:], validator.Bytes())
- }
-
- extraSuffix := len(header.Extra) - extraSeal
- if !bytes.Equal(header.Extra[extraVanity:extraSuffix], validatorsBytes) {
- return errMismatchingEpochValidators
- }
+ if err := p.verifyValidators(header); err != nil {
+ return err
}
- // No block rewards in PoA, so the state remains as is and uncles are dropped
+
cx := chainContext{Chain: chain, parlia: p}
+
+ // No block rewards in PoA, so the state remains as is and uncles are dropped
if header.Number.Cmp(common.Big1) == 0 {
err := p.initContract(state, header, cx, txs, receipts, systemTxs, usedGas, false)
if err != nil {
@@ -714,6 +1089,12 @@ func (p *Parlia) Finalize(chain consensus.ChainHeaderReader, header *types.Heade
if err != nil {
return err
}
+
+ if p.chainConfig.IsLynn(header.Number) {
+ if err := p.distributeFinalityReward(chain, state, header, cx, txs, receipts, systemTxs, usedGas, false); err != nil {
+ return err
+ }
+ }
if len(*systemTxs) > 0 {
return errors.New("the length of systemTxs do not match")
}
@@ -760,10 +1141,18 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
}
}
}
+
err := p.distributeIncoming(p.val, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true)
if err != nil {
return nil, nil, err
}
+
+ if p.chainConfig.IsLynn(header.Number) {
+ if err := p.distributeFinalityReward(chain, state, header, cx, &txs, &receipts, nil, &header.GasUsed, true); err != nil {
+ return nil, nil, err
+ }
+ }
+
// should not happen. Once happen, stop the node is better than broadcast the block
if header.GasLimit < header.GasUsed {
return nil, nil, errors.New("gas consumption of system txs exceed the gas limit")
@@ -787,6 +1176,59 @@ func (p *Parlia) FinalizeAndAssemble(chain consensus.ChainHeaderReader, header *
return blk, receipts, nil
}
+func (p *Parlia) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
+ number := header.Number.Uint64()
+ snap, err := p.snapshot(chain, number-1, header.ParentHash, nil)
+ if err != nil {
+ log.Error("failed to get the snapshot from consensus", "error", err)
+ return false
+ }
+ validators := snap.Validators
+ _, ok := validators[p.val]
+ return ok
+}
+
+// VerifyVote will verify: 1. If the vote comes from valid validators 2. If the vote's sourceNumber and sourceHash are correct
+func (p *Parlia) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteEnvelope) error {
+ targetNumber := vote.Data.TargetNumber
+ targetHash := vote.Data.TargetHash
+ header := chain.GetHeaderByHash(targetHash)
+ if header == nil {
+ log.Warn("BlockHeader at current voteBlockNumber is nil", "targetNumber", targetNumber, "targetHash", targetHash)
+ return fmt.Errorf("BlockHeader at current voteBlockNumber is nil")
+ }
+ if header.Number.Uint64() != targetNumber {
+ log.Warn("unexpected target number", "expect", header.Number.Uint64(), "real", targetNumber)
+ return fmt.Errorf("target number mismatch")
+ }
+
+ justifiedBlockNumber, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(chain, header)
+ if err != nil {
+ log.Error("failed to get the highest justified number and hash", "headerNumber", header.Number, "headerHash", header.Hash())
+ return fmt.Errorf("unexpected error when getting the highest justified number and hash")
+ }
+ if vote.Data.SourceNumber != justifiedBlockNumber || vote.Data.SourceHash != justifiedBlockHash {
+ return fmt.Errorf("vote source block mismatch")
+ }
+
+ number := header.Number.Uint64()
+ snap, err := p.snapshot(chain, number-1, header.ParentHash, nil)
+ if err != nil {
+ log.Error("failed to get the snapshot from consensus", "error", err)
+ return fmt.Errorf("failed to get the snapshot from consensus")
+ }
+
+ validators := snap.Validators
+ voteAddress := vote.VoteAddress
+ for _, validator := range validators {
+ if validator.VoteAddress == voteAddress {
+ return nil
+ }
+ }
+
+ return fmt.Errorf("vote verification failed")
+}
+
// Authorize injects a private key into the consensus engine to mint new blocks
// with.
func (p *Parlia) Authorize(val common.Address, signFn SignerFn, signTxFn SignerTxFn) {
@@ -871,13 +1313,6 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res
log.Info("Sealing block with", "number", number, "delay", delay, "headerDifficulty", header.Difficulty, "val", val.Hex())
- // Sign all the things!
- sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, ParliaRLP(header, p.chainConfig.ChainID))
- if err != nil {
- return err
- }
- copy(header.Extra[len(header.Extra)-extraSeal:], sig)
-
// Wait until sealing is terminated or delay timeout.
log.Trace("Waiting for slot to sign and propagate", "delay", common.PrettyDuration(delay))
go func() {
@@ -886,6 +1321,22 @@ func (p *Parlia) Seal(chain consensus.ChainHeaderReader, block *types.Block, res
return
case <-time.After(delay):
}
+
+ err := p.assembleVoteAttestation(chain, header)
+ if err != nil {
+ /* If the vote attestation can't be assembled successfully, the blockchain won't get
+ fast finalized, but it can be tolerated, so just report this error here. */
+ log.Error("Assemble vote attestation failed when sealing", "err", err)
+ }
+
+ // Sign all the things!
+ sig, err := signFn(accounts.Account{Address: val}, accounts.MimetypeParlia, ParliaRLP(header, p.chainConfig.ChainID))
+ if err != nil {
+ log.Error("Sign for the block header failed when sealing", "err", err)
+ return
+ }
+ copy(header.Extra[len(header.Extra)-extraSeal:], sig)
+
if p.shouldWaitForCurrentBlockProcess(chain, header, snap) {
log.Info("Waiting for received in turn block to process")
select {
@@ -964,11 +1415,13 @@ func (p *Parlia) SignRecently(chain consensus.ChainReader, parent *types.Block)
// If we're amongst the recent signers, wait for the next block
number := parent.NumberU64() + 1
for seen, recent := range snap.Recents {
- if recent == p.val {
- // Signer is among recents, only wait if the current block doesn't shift it out
- if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit {
- return true, nil
- }
+ if recent != p.val {
+ continue
+ }
+
+ // Signer is among recents, only wait if the current block doesn't shift it out
+ if limit := uint64(len(snap.Validators)/2 + 1); number < limit || seen > number-limit {
+ return true, nil
}
}
return false, nil
@@ -995,9 +1448,13 @@ func CalcDifficulty(snap *Snapshot, signer common.Address) *big.Int {
return new(big.Int).Set(diffNoTurn)
}
-// SealHash returns the hash of a block prior to it being sealed.
-func (p *Parlia) SealHash(header *types.Header) common.Hash {
- return SealHash(header, p.chainConfig.ChainID)
+// SealHash returns the hash of a block without vote attestation prior to it being sealed.
+// So it's not the real hash of a block, just used as unique id to distinguish task
+func (p *Parlia) SealHash(header *types.Header) (hash common.Hash) {
+ hasher := sha3.NewLegacyKeccak256()
+ encodeSigHeaderWithoutVoteAttestation(hasher, header, p.chainConfig.ChainID)
+ hasher.Sum(hash[:0])
+ return hash
}
// APIs implements consensus.Engine, returning the user facing RPC API to query snapshot.
@@ -1018,23 +1475,25 @@ func (p *Parlia) Close() error {
// ========================== interaction with contract/account =========
// getCurrentValidators get current validators
-func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNumber *big.Int) ([]common.Address, error) {
+func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNum *big.Int) ([]common.Address, map[common.Address]*types.BLSPublicKey, error) {
// block
blockNr := rpc.BlockNumberOrHashWithHash(blockHash, false)
- // method
- method := "getValidators"
- if p.chainConfig.IsEuler(blockNumber) {
- method = "getMiningValidators"
+ if !p.chainConfig.IsBoneh(blockNum) {
+ validators, err := p.getCurrentValidatorsBeforeBoneh(blockHash, blockNum)
+ return validators, nil, err
}
+ // method
+ method := "getMiningValidators"
+
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // cancel when we are finished consuming integers
data, err := p.validatorSetABI.Pack(method)
if err != nil {
- log.Error("Unable to pack tx for getValidators", "error", err)
- return nil, err
+ log.Error("Unable to pack tx for getMiningValidators", "error", err)
+ return nil, nil, err
}
// call
msgData := (hexutil.Bytes)(data)
@@ -1046,24 +1505,21 @@ func (p *Parlia) getCurrentValidators(blockHash common.Hash, blockNumber *big.In
Data: &msgData,
}, blockNr, nil)
if err != nil {
- return nil, err
+ return nil, nil, err
}
- var (
- ret0 = new([]common.Address)
- )
- out := ret0
+ var valSet []common.Address
+ var voteAddrSet []types.BLSPublicKey
- if err := p.validatorSetABI.UnpackIntoInterface(out, method, result); err != nil {
- return nil, err
+ if err := p.validatorSetABI.UnpackIntoInterface(&[]interface{}{&valSet, &voteAddrSet}, method, result); err != nil {
+ return nil, nil, err
}
- valz := make([]common.Address, len(*ret0))
- // nolint: gosimple
- for i, a := range *ret0 {
- valz[i] = a
+ voteAddrmap := make(map[common.Address]*types.BLSPublicKey, len(valSet))
+ for i := 0; i < len(valSet); i++ {
+ voteAddrmap[valSet[i]] = &(voteAddrSet)[i]
}
- return valz, nil
+ return valSet, voteAddrmap, nil
}
// slash spoiled validators
@@ -1254,6 +1710,65 @@ func (p *Parlia) applyTransaction(
return nil
}
+// GetJustifiedNumberAndHash returns the highest justified block's number and hash on the branch including and before `header`
+func (p *Parlia) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) {
+ if chain == nil || header == nil {
+ return 0, common.Hash{}, fmt.Errorf("illegal chain or header")
+ }
+ snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil)
+ if err != nil {
+ log.Error("Unexpected error when getting snapshot",
+ "error", err, "blockNumber", header.Number.Uint64(), "blockHash", header.Hash())
+ return 0, common.Hash{}, err
+ }
+
+ if snap.Attestation == nil {
+ if p.chainConfig.IsBoneh(header.Number) {
+ log.Debug("once one attestation generated, attestation of snap would not be nil forever basically")
+ }
+ return 0, chain.GetHeaderByNumber(0).Hash(), nil
+ }
+ return snap.Attestation.TargetNumber, snap.Attestation.TargetHash, nil
+}
+
+// GetFinalizedHeader returns highest finalized block header.
+// It will find vote finalized block within NaturallyFinalizedDist blocks firstly,
+// If the vote finalized block not found, return its naturally finalized block.
+func (p *Parlia) GetFinalizedHeader(chain consensus.ChainHeaderReader, header *types.Header) *types.Header {
+ backward := uint64(types.NaturallyFinalizedDist)
+ if chain == nil || header == nil {
+ return nil
+ }
+ if !chain.Config().IsLynn(header.Number) {
+ return chain.GetHeaderByNumber(0)
+ }
+ if header.Number.Uint64() < backward {
+ backward = header.Number.Uint64()
+ }
+
+ snap, err := p.snapshot(chain, header.Number.Uint64(), header.Hash(), nil)
+ if err != nil {
+ log.Error("Unexpected error when getting snapshot",
+ "error", err, "blockNumber", header.Number.Uint64(), "blockHash", header.Hash())
+ return nil
+ }
+
+ for snap.Attestation != nil && snap.Attestation.SourceNumber >= header.Number.Uint64()-backward {
+ if snap.Attestation.TargetNumber == snap.Attestation.SourceNumber+1 {
+ return chain.GetHeaderByHash(snap.Attestation.SourceHash)
+ }
+
+ snap, err = p.snapshot(chain, snap.Attestation.SourceNumber, snap.Attestation.SourceHash, nil)
+ if err != nil {
+ log.Error("Unexpected error when getting snapshot",
+ "error", err, "blockNumber", snap.Attestation.SourceNumber, "blockHash", snap.Attestation.SourceHash)
+ return nil
+ }
+ }
+
+ return FindAncientHeader(header, backward, chain, nil)
+}
+
// =========================== utility function ==========================
// SealHash returns the hash of a block prior to it being sealed.
func SealHash(header *types.Header, chainId *big.Int) (hash common.Hash) {
@@ -1287,6 +1802,30 @@ func encodeSigHeader(w io.Writer, header *types.Header, chainId *big.Int) {
}
}
+func encodeSigHeaderWithoutVoteAttestation(w io.Writer, header *types.Header, chainId *big.Int) {
+ err := rlp.Encode(w, []interface{}{
+ chainId,
+ header.ParentHash,
+ header.UncleHash,
+ header.Coinbase,
+ header.Root,
+ header.TxHash,
+ header.ReceiptHash,
+ header.Bloom,
+ header.Difficulty,
+ header.Number,
+ header.GasLimit,
+ header.GasUsed,
+ header.Time,
+ header.Extra[:extraVanity], // this will panic if extra is too short, should check before calling encodeSigHeaderWithoutVoteAttestation
+ header.MixDigest,
+ header.Nonce,
+ })
+ if err != nil {
+ panic("can't encode: " + err.Error())
+ }
+}
+
func (p *Parlia) backOffTime(snap *Snapshot, header *types.Header, val common.Address) uint64 {
if snap.inturn(val) {
return 0
diff --git a/consensus/parlia/parlia_test.go b/consensus/parlia/parlia_test.go
index fc05013e92..6442f16466 100644
--- a/consensus/parlia/parlia_test.go
+++ b/consensus/parlia/parlia_test.go
@@ -5,7 +5,16 @@ import (
"math/rand"
"testing"
+ "golang.org/x/crypto/sha3"
+
"github.com/ethereum/go-ethereum/common"
+ cmath "github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+const (
+ upperLimitOfVoteBlockNumber = 11
)
func TestImpactOfValidatorOutOfService(t *testing.T) {
@@ -144,3 +153,449 @@ func randomAddress() common.Address {
rand.Read(addrBytes)
return common.BytesToAddress(addrBytes)
}
+
+// =========================================================================
+// ======= Simulator P2P network to verify fast finality ============
+// =========================================================================
+
+type MockBlock struct {
+ parent *MockBlock
+
+ blockNumber uint64
+ blockHash common.Hash
+ coinbase *MockValidator
+ td uint64 // Total difficulty from genesis block to current block
+ attestation uint64 // Vote attestation for parent block, zero means no attestation
+}
+
+var GenesisBlock = &MockBlock{
+ parent: nil,
+ blockNumber: 0,
+ blockHash: common.Hash{},
+ coinbase: nil,
+ td: diffInTurn.Uint64(),
+ attestation: 0,
+}
+
+func (b *MockBlock) Hash() (hash common.Hash) {
+ hasher := sha3.NewLegacyKeccak256()
+ rlp.Encode(hasher, []interface{}{
+ b.parent,
+ b.blockNumber,
+ b.coinbase,
+ b.td,
+ b.attestation,
+ })
+ hasher.Sum(hash[:0])
+ return hash
+}
+
+func (b *MockBlock) IsConflicted(a *MockBlock) bool {
+ if a.blockNumber > b.blockNumber {
+ p := a.parent
+ for ; p.blockNumber > b.blockNumber; p = p.parent {
+ }
+
+ return p.blockHash != b.blockHash
+ }
+
+ if a.blockNumber < b.blockNumber {
+ p := b.parent
+ for ; p.blockNumber > a.blockNumber; p = p.parent {
+ }
+
+ return p.blockHash != a.blockHash
+ }
+
+ return a.blockHash != b.blockHash
+}
+
+// GetJustifiedNumberAndHash returns number and hash of the highest justified block,
+// keep same func signature with consensus even if `error` will be nil definitely
+func (b *MockBlock) GetJustifiedNumberAndHash() (uint64, common.Hash, error) {
+ justifiedBlock := GenesisBlock
+ for curBlock := b; curBlock.blockNumber > 1; curBlock = curBlock.parent {
+ // justified
+ if curBlock.attestation != 0 {
+ justifiedBlock = curBlock.parent
+ break
+ }
+
+ }
+
+ return justifiedBlock.blockNumber, justifiedBlock.blockHash, nil
+}
+
+func (b *MockBlock) GetJustifiedNumber() uint64 {
+ justifiedBlockNumber, _, _ := b.GetJustifiedNumberAndHash()
+ return justifiedBlockNumber
+}
+
+// GetFinalizedBlock returns highest finalized block,
+// include current block's attestation.
+func (b *MockBlock) GetFinalizedBlock() *MockBlock {
+ if b.blockNumber < 3 {
+ return GenesisBlock
+ }
+
+ if b.attestation != 0 && b.parent.attestation != 0 {
+ return b.parent.parent
+ }
+
+ return b.parent.GetFinalizedBlock()
+}
+
+type MockValidator struct {
+ index int
+ validatorSet int // validators number
+ head *MockBlock
+ voteRecords map[uint64]*types.VoteData
+}
+
+func NewMockValidator(index int, validatorSet int) *MockValidator {
+ v := &MockValidator{
+ index: index,
+ validatorSet: validatorSet,
+ head: GenesisBlock,
+ voteRecords: make(map[uint64]*types.VoteData),
+ }
+ return v
+}
+
+func (v *MockValidator) SignRecently() bool {
+ parent := v.head
+ for i := 0; i < v.validatorSet*1/2; i++ {
+ if parent.blockNumber == 0 {
+ return false
+ }
+
+ if parent.coinbase == v {
+ return true
+ }
+
+ parent = parent.parent
+ }
+
+ return false
+}
+
+func (v *MockValidator) Produce(attestation uint64) (*MockBlock, error) {
+ if v.SignRecently() {
+ return nil, fmt.Errorf("v %d sign recently", v.index)
+ }
+
+ block := &MockBlock{
+ parent: v.head,
+ blockNumber: v.head.blockNumber + 1,
+ coinbase: v,
+ td: v.head.td + 1,
+ attestation: attestation,
+ }
+
+ if (block.blockNumber-1)%uint64(v.validatorSet) == uint64(v.index) {
+ block.td = v.head.td + 2
+ }
+
+ block.blockHash = block.Hash()
+ return block, nil
+}
+
+func (v *MockValidator) Vote(block *MockBlock) bool {
+ // Rule 3: The block should be the latest block of canonical chain
+ if block != v.head {
+ return false
+ }
+
+ // Rule 1: No double vote
+ if _, ok := v.voteRecords[block.blockNumber]; ok {
+ return false
+ }
+
+ // Rule 2: No surround vote
+ justifiedBlockNumber, justifiedBlockHash, _ := block.GetJustifiedNumberAndHash()
+ for targetNumber := justifiedBlockNumber + 1; targetNumber < block.blockNumber; targetNumber++ {
+ if vote, ok := v.voteRecords[targetNumber]; ok {
+ if vote.SourceNumber > justifiedBlockNumber {
+ return false
+ }
+ }
+ }
+ for targetNumber := block.blockNumber; targetNumber <= block.blockNumber+upperLimitOfVoteBlockNumber; targetNumber++ {
+ if vote, ok := v.voteRecords[targetNumber]; ok {
+ if vote.SourceNumber < justifiedBlockNumber {
+ return false
+ }
+ }
+ }
+
+ v.voteRecords[block.blockNumber] = &types.VoteData{
+ SourceNumber: justifiedBlockNumber,
+ SourceHash: justifiedBlockHash,
+ TargetNumber: block.blockNumber,
+ TargetHash: block.blockHash,
+ }
+ return true
+}
+
+func (v *MockValidator) InsertBlock(block *MockBlock) {
+ // Reject block too old.
+ if block.blockNumber+13 < v.head.blockNumber {
+ return
+ }
+
+ // The higher justified block is the longest chain.
+ if block.GetJustifiedNumber() < v.head.GetJustifiedNumber() {
+ return
+ }
+ if block.GetJustifiedNumber() > v.head.GetJustifiedNumber() {
+ v.head = block
+ return
+ }
+
+ // The same finalized number, the larger difficulty is the longest chain.
+ if block.td > v.head.td {
+ v.head = block
+ }
+}
+
+type BlockSimulator struct {
+ blockNumber uint64
+ coinbaseIndex int
+ voteMap uint64
+ insertMap uint64
+}
+
+type ChainSimulator []*BlockSimulator
+
+func (s ChainSimulator) Valid() bool {
+ var pre *BlockSimulator
+ for index, bs := range s {
+ if index == 0 {
+ if bs.blockNumber != 1 {
+ return false
+ }
+ } else {
+ if bs.blockNumber != pre.blockNumber+1 {
+ return false
+ }
+ }
+
+ pre = bs
+ }
+ return true
+}
+
+type Coordinator struct {
+ validators []*MockValidator
+ attestations map[common.Hash]uint64
+}
+
+func NewCoordinator(validatorsNumber int) *Coordinator {
+ validators := make([]*MockValidator, validatorsNumber)
+ for i := 0; i < validatorsNumber; i++ {
+ validators[i] = NewMockValidator(i, validatorsNumber)
+ }
+
+ return &Coordinator{
+ validators: validators,
+ attestations: make(map[common.Hash]uint64),
+ }
+}
+
+// SimulateP2P simulate a P2P network
+func (c *Coordinator) SimulateP2P(cs ChainSimulator) error {
+ for _, bs := range cs {
+ parent := c.validators[bs.coinbaseIndex].head
+ if bs.blockNumber != parent.blockNumber+1 {
+ return fmt.Errorf("can't produce discontinuous block, head block: %d, expect produce: %d", parent.blockNumber, bs.blockNumber)
+ }
+ attestation := c.attestations[parent.blockHash]
+ block, err := c.validators[bs.coinbaseIndex].Produce(attestation)
+ if err != nil {
+ return fmt.Errorf("produce block %v error %v", bs, err)
+ }
+
+ c.PropagateBlock(bs, block)
+ err = c.AggregateVotes(bs, block)
+ if err != nil {
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (c *Coordinator) AggregateVotes(bs *BlockSimulator, block *MockBlock) error {
+ var attestation uint64
+ count := 0
+ for index, voteMap := 0, bs.voteMap; voteMap > 0; index, voteMap = index+1, voteMap>>1 {
+ if voteMap&0x1 == 0 {
+ continue
+ }
+
+ if !c.validators[index].Vote(block) {
+ return fmt.Errorf("validator(%d) couldn't vote for block %d produced by validator(%d)", index, block.blockNumber, block.coinbase.index)
+ }
+ attestation |= 1 << index
+ count++
+ }
+
+ if count >= cmath.CeilDiv(len(c.validators)*2, 3) {
+ c.attestations[block.blockHash] = attestation
+ }
+
+ return nil
+}
+
+func (c *Coordinator) PropagateBlock(bs *BlockSimulator, block *MockBlock) {
+ for index, insertMap := 0, bs.insertMap; insertMap > 0; index, insertMap = index+1, insertMap>>1 {
+ if insertMap&0x1 == 0 {
+ continue
+ }
+
+ c.validators[index].InsertBlock(block)
+ }
+}
+
+func (c *Coordinator) CheckChain() bool {
+ // All validators highest finalized block should not be conflicted
+ finalizedBlocks := make([]*MockBlock, len(c.validators))
+ for index, val := range c.validators {
+ finalizedBlocks[index] = val.head.GetFinalizedBlock()
+ }
+
+ for i := 0; i < len(finalizedBlocks)-1; i++ {
+ for j := i + 1; j < len(finalizedBlocks); j++ {
+ if finalizedBlocks[i].IsConflicted(finalizedBlocks[j]) {
+ return false
+ }
+ }
+ }
+
+ return true
+}
+
+type TestSimulatorParam struct {
+ validatorsNumber int
+ cs ChainSimulator
+}
+
+var simulatorTestcases = []*TestSimulatorParam{
+ {
+ // 3 validators, all active
+ validatorsNumber: 3,
+ cs: []*BlockSimulator{
+ {1, 0, 0x7, 0x7},
+ {2, 1, 0x7, 0x7},
+ {3, 2, 0x7, 0x7},
+ {4, 0, 0x7, 0x7},
+ {5, 1, 0x7, 0x7},
+ },
+ },
+ {
+ // 5 validators, 4 active, 1 down
+ validatorsNumber: 5,
+ cs: []*BlockSimulator{
+ {1, 0, 0x1f, 0x1f},
+ {2, 1, 0x1f, 0x1f},
+ {3, 2, 0x1f, 0x1f},
+ {4, 3, 0x1f, 0x1f},
+ {5, 0, 0x1f, 0x1f},
+ {6, 1, 0x1f, 0x1f},
+ {7, 2, 0x1f, 0x1f},
+ },
+ },
+ {
+ // 21 validators, all active
+ validatorsNumber: 21,
+ cs: []*BlockSimulator{
+ {1, 0, 0x1fffff, 0x1fffff},
+ {2, 1, 0x1fffff, 0x1fffff},
+ {3, 2, 0x1fffff, 0x1fffff},
+ {4, 3, 0x1fffff, 0x1fffff},
+ {5, 4, 0x1fffff, 0x1fffff},
+ {6, 5, 0x1fffff, 0x1fffff},
+ {7, 6, 0x1fffff, 0x1fffff},
+ {8, 7, 0x1fffff, 0x1fffff},
+ {9, 8, 0x1fffff, 0x1fffff},
+ {10, 9, 0x1fffff, 0x1fffff},
+ {11, 10, 0x1fffff, 0x1fffff},
+ {12, 11, 0x1fffff, 0x1fffff},
+ {13, 12, 0x1fffff, 0x1fffff},
+ {14, 13, 0x1fffff, 0x1fffff},
+ {15, 14, 0x1fffff, 0x1fffff},
+ {16, 0, 0x1fffff, 0x1fffff},
+ {17, 1, 0x1fffff, 0x1fffff},
+ {18, 2, 0x1fffff, 0x1fffff},
+ },
+ },
+ {
+ // 21 validators, all active, the finalized fork can keep grow
+ validatorsNumber: 21,
+ cs: []*BlockSimulator{
+ {1, 1, 0x00fffe, 0x00fffe},
+ {2, 2, 0x00fffe, 0x00fffe},
+ {1, 0, 0x1f0001, 0x1fffff},
+ {2, 16, 0x1f0001, 0x1ffff1},
+ {3, 17, 0x1f0001, 0x1ffff1},
+ {4, 18, 0x1f0001, 0x1ffff1},
+ {5, 19, 0x1f0001, 0x1ffff1},
+ {3, 3, 0x00fffe, 0x00fffe}, // justify block 2 and finalize block 1
+ {6, 20, 0x1f0001, 0x1fffff},
+ {4, 4, 0x00fffe, 0x1fffff},
+ {5, 5, 0x00fffe, 0x1fffff},
+ {6, 6, 0x00fffe, 0x1fffff},
+ {7, 7, 0x1fffff, 0x1fffff},
+ {8, 8, 0x1fffff, 0x1fffff},
+ },
+ },
+ {
+ // 21 validators, all active, the finalized fork can keep grow
+ validatorsNumber: 21,
+ cs: []*BlockSimulator{
+ {1, 14, 0x00fffe, 0x00fffe},
+ {2, 15, 0x00fffe, 0x00fffe}, // The block 3 will never produce
+ {1, 0, 0x1f0001, 0x1fffff},
+ {2, 16, 0x1f0001, 0x1fffff},
+ {3, 1, 0x1f0001, 0x1fffff}, // based block produced by 15
+ {4, 2, 0x1f0001, 0x1fffff},
+ {5, 3, 0x1f0001, 0x1fffff},
+ {6, 4, 0x1f0001, 0x1fffff},
+ {7, 5, 0x1f0001, 0x1fffff},
+ {8, 6, 0x1f0001, 0x1fffff},
+ {9, 7, 0x1f0001, 0x1fffff},
+ {10, 8, 0x1f0001, 0x1fffff},
+ {11, 9, 0x1f0001, 0x1fffff},
+ {12, 10, 0x1f0001, 0x1fffff},
+ {13, 11, 0x1f0001, 0x1fffff},
+ {14, 12, 0x1f0001, 0x1fffff},
+ {15, 13, 0x1f0001, 0x1fffff},
+ {16, 14, 0x1f0001, 0x1fffff},
+ {17, 15, 0x1fffff, 0x1fffff}, // begin new round vote
+ {18, 16, 0x1fffff, 0x1fffff}, // attestation for block 17
+ {19, 17, 0x1fffff, 0x1fffff}, // attestation for block 18
+ },
+ },
+}
+
+func TestSimulateP2P(t *testing.T) {
+ for index, testcase := range simulatorTestcases {
+ c := NewCoordinator(testcase.validatorsNumber)
+ err := c.SimulateP2P(testcase.cs)
+ if err != nil {
+ t.Fatalf("[Testcase %d] simulate P2P error: %v", index, err)
+ }
+ for _, val := range c.validators {
+ t.Logf("[Testcase %d] validator(%d) head block: %d",
+ index, val.index, val.head.blockNumber)
+ t.Logf("[Testcase %d] validator(%d) highest justified block: %d",
+ index, val.index, val.head.GetJustifiedNumber())
+ t.Logf("[Testcase %d] validator(%d) highest finalized block: %d",
+ index, val.index, val.head.GetFinalizedBlock().blockNumber)
+ }
+
+ if c.CheckChain() == false {
+ t.Fatalf("[Testcase %d] chain not works as expected", index)
+ }
+ }
+}
diff --git a/consensus/parlia/snapshot.go b/consensus/parlia/snapshot.go
index 95aaf861de..7be414421c 100644
--- a/consensus/parlia/snapshot.go
+++ b/consensus/parlia/snapshot.go
@@ -21,7 +21,6 @@ import (
"encoding/hex"
"encoding/json"
"errors"
- "math/big"
"sort"
"github.com/ethereum/go-ethereum/common"
@@ -39,11 +38,17 @@ type Snapshot struct {
ethAPI *ethapi.PublicBlockChainAPI
sigCache *lru.ARCCache // Cache of recent block signatures to speed up ecrecover
- Number uint64 `json:"number"` // Block number where the snapshot was created
- Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
- Validators map[common.Address]struct{} `json:"validators"` // Set of authorized validators at this moment
- Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections
- RecentForkHashes map[uint64]string `json:"recent_fork_hashes"` // Set of recent forkHash
+ Number uint64 `json:"number"` // Block number where the snapshot was created
+ Hash common.Hash `json:"hash"` // Block hash where the snapshot was created
+ Validators map[common.Address]*ValidatorInfo `json:"validators"` // Set of authorized validators at this moment
+ Recents map[uint64]common.Address `json:"recents"` // Set of recent validators for spam protections
+ RecentForkHashes map[uint64]string `json:"recent_fork_hashes"` // Set of recent forkHash
+ Attestation *types.VoteData `json:"attestation:omitempty"` // Attestation for fast finality
+}
+
+type ValidatorInfo struct {
+ Index int `json:"index:omitempty"` // The index should offset by 1
+ VoteAddress types.BLSPublicKey `json:"vote_address,omitempty"`
}
// newSnapshot creates a new snapshot with the specified startup parameters. This
@@ -55,6 +60,7 @@ func newSnapshot(
number uint64,
hash common.Hash,
validators []common.Address,
+ voteAddrs []types.BLSPublicKey,
ethAPI *ethapi.PublicBlockChainAPI,
) *Snapshot {
snap := &Snapshot{
@@ -65,10 +71,25 @@ func newSnapshot(
Hash: hash,
Recents: make(map[uint64]common.Address),
RecentForkHashes: make(map[uint64]string),
- Validators: make(map[common.Address]struct{}),
+ Validators: make(map[common.Address]*ValidatorInfo),
}
- for _, v := range validators {
- snap.Validators[v] = struct{}{}
+ for idx, v := range validators {
+ // The boneh fork from the genesis block
+ if len(voteAddrs) == len(validators) {
+ snap.Validators[v] = &ValidatorInfo{
+ VoteAddress: voteAddrs[idx],
+ }
+ } else {
+ snap.Validators[v] = &ValidatorInfo{}
+ }
+ }
+
+ // The boneh fork from the genesis block
+ if len(voteAddrs) == len(validators) {
+ validators := snap.validators()
+ for idx, v := range validators {
+ snap.Validators[v].Index = idx + 1 // offset by 1
+ }
}
return snap
}
@@ -114,13 +135,16 @@ func (s *Snapshot) copy() *Snapshot {
sigCache: s.sigCache,
Number: s.Number,
Hash: s.Hash,
- Validators: make(map[common.Address]struct{}),
+ Validators: make(map[common.Address]*ValidatorInfo),
Recents: make(map[uint64]common.Address),
RecentForkHashes: make(map[uint64]string),
}
for v := range s.Validators {
- cpy.Validators[v] = struct{}{}
+ cpy.Validators[v] = &ValidatorInfo{
+ Index: s.Validators[v].Index,
+ VoteAddress: s.Validators[v].VoteAddress,
+ }
}
for block, v := range s.Recents {
cpy.Recents[block] = v
@@ -128,6 +152,14 @@ func (s *Snapshot) copy() *Snapshot {
for block, id := range s.RecentForkHashes {
cpy.RecentForkHashes[block] = id
}
+ if s.Attestation != nil {
+ cpy.Attestation = &types.VoteData{
+ SourceNumber: s.Attestation.SourceNumber,
+ SourceHash: s.Attestation.SourceHash,
+ TargetNumber: s.Attestation.TargetNumber,
+ TargetHash: s.Attestation.TargetHash,
+ }
+ }
return cpy
}
@@ -141,7 +173,23 @@ func (s *Snapshot) isMajorityFork(forkHash string) bool {
return ally > len(s.RecentForkHashes)/2
}
-func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainId *big.Int) (*Snapshot, error) {
+func (s *Snapshot) updateAttestation(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) {
+ // The attestation should have been checked in verify header, update directly
+ attestation, _ := getVoteAttestationFromHeader(header, chainConfig, parliaConfig)
+ if attestation == nil {
+ return
+ }
+
+ // Update attestation
+ s.Attestation = &types.VoteData{
+ SourceNumber: attestation.Data.SourceNumber,
+ SourceHash: attestation.Data.SourceHash,
+ TargetNumber: attestation.Data.TargetNumber,
+ TargetHash: attestation.Data.TargetHash,
+ }
+}
+
+func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderReader, parents []*types.Header, chainConfig *params.ChainConfig, verifiedAttestations map[common.Hash]struct{}) (*Snapshot, error) {
// Allow passing in no headers for cleaner code
if len(headers) == 0 {
return s, nil
@@ -174,7 +222,7 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
delete(snap.RecentForkHashes, number-limit)
}
// Resolve the authorization key and check against signers
- validator, err := ecrecover(header, s.sigCache, chainId)
+ validator, err := ecrecover(header, s.sigCache, chainConfig.ChainID)
if err != nil {
return nil, err
}
@@ -194,15 +242,20 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
return nil, consensus.ErrUnknownAncestor
}
- validatorBytes := checkpointHeader.Extra[extraVanity : len(checkpointHeader.Extra)-extraSeal]
// get validators from headers and use that for new validator set
- newValArr, err := ParseValidators(validatorBytes)
+ newValArr, voteAddrs, err := parseValidators(checkpointHeader, chainConfig, s.config)
if err != nil {
return nil, err
}
- newVals := make(map[common.Address]struct{}, len(newValArr))
- for _, val := range newValArr {
- newVals[val] = struct{}{}
+ newVals := make(map[common.Address]*ValidatorInfo, len(newValArr))
+ for idx, val := range newValArr {
+ if !chainConfig.IsBoneh(header.Number) {
+ newVals[val] = &ValidatorInfo{}
+ } else {
+ newVals[val] = &ValidatorInfo{
+ VoteAddress: voteAddrs[idx],
+ }
+ }
}
oldLimit := len(snap.Validators)/2 + 1
newLimit := len(newVals)/2 + 1
@@ -219,7 +272,19 @@ func (s *Snapshot) apply(headers []*types.Header, chain consensus.ChainHeaderRea
}
}
snap.Validators = newVals
+ if chainConfig.IsBoneh(header.Number) {
+ validators := snap.validators()
+ for idx, val := range validators {
+ snap.Validators[val].Index = idx + 1 // offset by 1
+ }
+ }
}
+
+ _, voteAssestationNoErr := verifiedAttestations[header.Hash()]
+ if chainConfig.IsLynn(header.Number) || (chainConfig.IsBoneh(header.Number) && voteAssestationNoErr) {
+ snap.updateAttestation(header, chainConfig, s.config)
+ }
+
snap.RecentForkHashes[number] = hex.EncodeToString(header.Extra[extraVanity-nextForkHashSize : extraVanity])
}
snap.Number += uint64(len(headers))
@@ -265,6 +330,10 @@ func (s *Snapshot) enoughDistance(validator common.Address, header *types.Header
}
func (s *Snapshot) indexOfVal(validator common.Address) int {
+ if validator, ok := s.Validators[validator]; ok && validator.Index > 0 {
+ return validator.Index - 1 // Index is offset by 1
+ }
+
validators := s.validators()
for idx, val := range validators {
if val == validator {
@@ -280,18 +349,29 @@ func (s *Snapshot) supposeValidator() common.Address {
return validators[index]
}
-func ParseValidators(validatorsBytes []byte) ([]common.Address, error) {
- if len(validatorsBytes)%validatorBytesLength != 0 {
- return nil, errors.New("invalid validators bytes")
+func parseValidators(header *types.Header, chainConfig *params.ChainConfig, parliaConfig *params.ParliaConfig) ([]common.Address, []types.BLSPublicKey, error) {
+ validatorsBytes := getValidatorBytesFromHeader(header, chainConfig, parliaConfig)
+ if len(validatorsBytes) == 0 {
+ return nil, nil, errors.New("invalid validators bytes")
+ }
+
+ if !chainConfig.IsBoneh(header.Number) {
+ n := len(validatorsBytes) / validatorBytesLengthBeforeBoneh
+ result := make([]common.Address, n)
+ for i := 0; i < n; i++ {
+ result[i] = common.BytesToAddress(validatorsBytes[i*validatorBytesLengthBeforeBoneh : (i+1)*validatorBytesLengthBeforeBoneh])
+ }
+ return result, nil, nil
}
+
n := len(validatorsBytes) / validatorBytesLength
- result := make([]common.Address, n)
+ cnsAddrs := make([]common.Address, n)
+ voteAddrs := make([]types.BLSPublicKey, n)
for i := 0; i < n; i++ {
- address := make([]byte, validatorBytesLength)
- copy(address, validatorsBytes[i*validatorBytesLength:(i+1)*validatorBytesLength])
- result[i] = common.BytesToAddress(address)
+ cnsAddrs[i] = common.BytesToAddress(validatorsBytes[i*validatorBytesLength : i*validatorBytesLength+common.AddressLength])
+ copy(voteAddrs[i][:], validatorsBytes[i*validatorBytesLength+common.AddressLength:(i+1)*validatorBytesLength])
}
- return result, nil
+ return cnsAddrs, voteAddrs, nil
}
func FindAncientHeader(header *types.Header, ite uint64, chain consensus.ChainHeaderReader, candidateParents []*types.Header) *types.Header {
diff --git a/core/blockchain.go b/core/blockchain.go
index b7838a7719..43d899d77e 100644
--- a/core/blockchain.go
+++ b/core/blockchain.go
@@ -55,6 +55,9 @@ var (
headHeaderGauge = metrics.NewRegisteredGauge("chain/head/header", nil)
headFastBlockGauge = metrics.NewRegisteredGauge("chain/head/receipt", nil)
+ justifiedBlockGauge = metrics.NewRegisteredGauge("chain/head/justified", nil)
+ finalizedBlockGauge = metrics.NewRegisteredGauge("chain/head/finalized", nil)
+
accountReadTimer = metrics.NewRegisteredTimer("chain/account/reads", nil)
accountHashTimer = metrics.NewRegisteredTimer("chain/account/hashes", nil)
accountUpdateTimer = metrics.NewRegisteredTimer("chain/account/updates", nil)
@@ -200,16 +203,17 @@ type BlockChain struct {
txLookupLimit uint64
triesInMemory uint64
- hc *HeaderChain
- rmLogsFeed event.Feed
- chainFeed event.Feed
- chainSideFeed event.Feed
- chainHeadFeed event.Feed
- chainBlockFeed event.Feed
- logsFeed event.Feed
- blockProcFeed event.Feed
- scope event.SubscriptionScope
- genesisBlock *types.Block
+ hc *HeaderChain
+ rmLogsFeed event.Feed
+ chainFeed event.Feed
+ chainSideFeed event.Feed
+ chainHeadFeed event.Feed
+ chainBlockFeed event.Feed
+ logsFeed event.Feed
+ blockProcFeed event.Feed
+ finalizedHeaderFeed event.Feed
+ scope event.SubscriptionScope
+ genesisBlock *types.Block
// This mutex synchronizes chain write operations.
// Readers don't need to take it, they can just read the database.
@@ -590,6 +594,30 @@ func (bc *BlockChain) empty() bool {
return true
}
+// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
+func (bc *BlockChain) GetJustifiedNumber(header *types.Header) uint64 {
+ if p, ok := bc.engine.(consensus.PoSA); ok {
+ justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(bc, header)
+ if err == nil {
+ return justifiedBlockNumber
+ }
+ }
+ // return 0 when err!=nil
+ // so the input `header` will at a disadvantage during reorg
+ return 0
+}
+
+// getFinalizedNumber returns the highest finalized number before the specific block.
+func (bc *BlockChain) getFinalizedNumber(header *types.Header) uint64 {
+ if p, ok := bc.engine.(consensus.PoSA); ok {
+ if finalizedHeader := p.GetFinalizedHeader(bc, header); finalizedHeader != nil {
+ return finalizedHeader.Number.Uint64()
+ }
+ }
+
+ return 0
+}
+
// loadLastState loads the last known chain state from the database. This method
// assumes that the chain manager mutex is held.
func (bc *BlockChain) loadLastState() error {
@@ -611,6 +639,8 @@ func (bc *BlockChain) loadLastState() error {
// Everything seems to be fine, set as the head block
bc.currentBlock.Store(currentBlock)
headBlockGauge.Update(int64(currentBlock.NumberU64()))
+ justifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(currentBlock.Header())))
+ finalizedBlockGauge.Update(int64(bc.getFinalizedNumber(currentBlock.Header())))
// Restore the last known head header
currentHeader := currentBlock.Header()
@@ -759,6 +789,8 @@ func (bc *BlockChain) setHeadBeyondRoot(head uint64, root common.Hash, repair bo
// to low, so it's safe to update in-memory markers directly.
bc.currentBlock.Store(newHeadBlock)
headBlockGauge.Update(int64(newHeadBlock.NumberU64()))
+ justifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(newHeadBlock.Header())))
+ finalizedBlockGauge.Update(int64(bc.getFinalizedNumber(newHeadBlock.Header())))
}
// Rewind the fast block in a simpleton way to the target head
if currentFastBlock := bc.CurrentFastBlock(); currentFastBlock != nil && header.Number.Uint64() < currentFastBlock.NumberU64() {
@@ -849,6 +881,8 @@ func (bc *BlockChain) SnapSyncCommitHead(hash common.Hash) error {
}
bc.currentBlock.Store(block)
headBlockGauge.Update(int64(block.NumberU64()))
+ justifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(block.Header())))
+ finalizedBlockGauge.Update(int64(bc.getFinalizedNumber(block.Header())))
bc.chainmu.Unlock()
// Destroy any existing state snapshot and regenerate it in the background,
@@ -895,6 +929,8 @@ func (bc *BlockChain) ResetWithGenesisBlock(genesis *types.Block) error {
bc.genesisBlock = genesis
bc.currentBlock.Store(bc.genesisBlock)
headBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
+ justifiedBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
+ finalizedBlockGauge.Update(int64(bc.genesisBlock.NumberU64()))
bc.hc.SetGenesis(bc.genesisBlock.Header())
bc.hc.SetCurrentHeader(bc.genesisBlock.Header())
bc.currentFastBlock.Store(bc.genesisBlock)
@@ -966,6 +1002,8 @@ func (bc *BlockChain) writeHeadBlock(block *types.Block) {
bc.currentBlock.Store(block)
headBlockGauge.Update(int64(block.NumberU64()))
+ justifiedBlockGauge.Update(int64(bc.GetJustifiedNumber(block.Header())))
+ finalizedBlockGauge.Update(int64(bc.getFinalizedNumber(block.Header())))
}
// GetDiffLayerRLP retrieves a diff layer in RLP encoding from the cache or database by blockHash
@@ -1203,7 +1241,7 @@ func (bc *BlockChain) InsertReceiptChain(blockChain types.Blocks, receiptChain [
// Rewind may have occurred, skip in that case.
if bc.CurrentHeader().Number.Cmp(head.Number()) >= 0 {
- reorg, err := bc.forker.ReorgNeeded(bc.CurrentFastBlock().Header(), head.Header())
+ reorg, err := bc.forker.ReorgNeededWithFastFinality(bc.CurrentFastBlock().Header(), head.Header())
if err != nil {
log.Warn("Reorg failed", "err", err)
return false
@@ -1605,7 +1643,7 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
return NonStatTy, err
}
currentBlock := bc.CurrentBlock()
- reorg, err := bc.forker.ReorgNeeded(currentBlock.Header(), block.Header())
+ reorg, err := bc.forker.ReorgNeededWithFastFinality(currentBlock.Header(), block.Header())
if err != nil {
return NonStatTy, err
}
@@ -1638,6 +1676,11 @@ func (bc *BlockChain) writeBlockAndSetHead(block *types.Block, receipts []*types
// event here.
if emitHeadEvent {
bc.chainHeadFeed.Send(ChainHeadEvent{Block: block})
+ if posa, ok := bc.Engine().(consensus.PoSA); ok {
+ if finalizedHeader := posa.GetFinalizedHeader(bc, block.Header()); finalizedHeader != nil {
+ bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader})
+ }
+ }
}
} else {
bc.chainSideFeed.Send(ChainSideEvent{Block: block})
@@ -1725,6 +1768,11 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
defer func() {
if lastCanon != nil && bc.CurrentBlock().Hash() == lastCanon.Hash() {
bc.chainHeadFeed.Send(ChainHeadEvent{lastCanon})
+ if posa, ok := bc.Engine().(consensus.PoSA); ok {
+ if finalizedHeader := posa.GetFinalizedHeader(bc, lastCanon.Header()); finalizedHeader != nil {
+ bc.finalizedHeaderFeed.Send(FinalizedHeaderEvent{finalizedHeader})
+ }
+ }
}
}()
// Start the parallel header verifier
@@ -1754,7 +1802,7 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals, setHead bool)
current = bc.CurrentBlock()
)
for block != nil && bc.skipBlock(err, it) {
- reorg, err = bc.forker.ReorgNeeded(current.Header(), block.Header())
+ reorg, err = bc.forker.ReorgNeededWithFastFinality(current.Header(), block.Header())
if err != nil {
return it.index, err
}
@@ -2132,7 +2180,7 @@ func (bc *BlockChain) insertSideChain(block *types.Block, it *insertIterator) (i
//
// If the externTd was larger than our local TD, we now need to reimport the previous
// blocks to regenerate the required state
- reorg, err := bc.forker.ReorgNeeded(current.Header(), lastBlock.Header())
+ reorg, err := bc.forker.ReorgNeededWithFastFinality(current.Header(), lastBlock.Header())
if err != nil {
return it.index, err
}
diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go
index b28661da3e..d4b11aa3f0 100644
--- a/core/blockchain_reader.go
+++ b/core/blockchain_reader.go
@@ -42,6 +42,36 @@ func (bc *BlockChain) CurrentBlock() *types.Block {
return bc.currentBlock.Load().(*types.Block)
}
+// CurrentFinalBlock retrieves the current finalized block of the canonical
+// chain. The block is retrieved from the blockchain's internal cache.
+func (bc *BlockChain) CurrentFinalBlock() *types.Header {
+ if p, ok := bc.engine.(consensus.PoSA); ok {
+ currentHeader := bc.CurrentHeader()
+ if currentHeader == nil {
+ return nil
+ }
+ return p.GetFinalizedHeader(bc, currentHeader)
+ }
+
+ return nil
+}
+
+// CurrentSafeBlock retrieves the current safe block of the canonical
+// chain. The block is retrieved from the blockchain's internal cache.
+func (bc *BlockChain) CurrentSafeBlock() *types.Header {
+ if p, ok := bc.engine.(consensus.PoSA); ok {
+ currentHeader := bc.CurrentHeader()
+ if currentHeader == nil {
+ return nil
+ }
+ _, justifiedBlockHash, err := p.GetJustifiedNumberAndHash(bc, currentHeader)
+ if err == nil {
+ return bc.GetHeaderByHash(justifiedBlockHash)
+ }
+ }
+ return nil
+}
+
// CurrentFastBlock retrieves the current fast-sync head block of the canonical
// chain. The block is retrieved from the blockchain's internal cache.
func (bc *BlockChain) CurrentFastBlock() *types.Block {
@@ -399,3 +429,8 @@ func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscript
func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription {
return bc.scope.Track(bc.blockProcFeed.Subscribe(ch))
}
+
+// SubscribeFinalizedHeaderEvent registers a subscription of FinalizedHeaderEvent.
+func (bc *BlockChain) SubscribeFinalizedHeaderEvent(ch chan<- FinalizedHeaderEvent) event.Subscription {
+ return bc.scope.Track(bc.finalizedHeaderFeed.Subscribe(ch))
+}
diff --git a/core/events.go b/core/events.go
index 5e730a24a7..ce8bcca744 100644
--- a/core/events.go
+++ b/core/events.go
@@ -21,7 +21,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
)
-// NewTxsEvent is posted when a batch of transactions enter the transaction pool.
+// NewTxsEvent is posted when a batch of transactions enters the transaction pool.
type NewTxsEvent struct{ Txs []*types.Transaction }
// ReannoTxsEvent is posted when a batch of local pending transactions exceed a specified duration.
@@ -33,6 +33,12 @@ type NewMinedBlockEvent struct{ Block *types.Block }
// RemovedLogsEvent is posted when a reorg happens
type RemovedLogsEvent struct{ Logs []*types.Log }
+// NewVoteEvent is posted when a batch of votes enters the vote pool.
+type NewVoteEvent struct{ Vote *types.VoteEnvelope }
+
+// FinalizedHeaderEvent is posted when a finalized header is reached.
+type FinalizedHeaderEvent struct{ Header *types.Header }
+
type ChainEvent struct {
Block *types.Block
Hash common.Hash
diff --git a/core/forkchoice.go b/core/forkchoice.go
index b0dbb200ec..da32ccce6c 100644
--- a/core/forkchoice.go
+++ b/core/forkchoice.go
@@ -24,6 +24,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
+ "github.com/ethereum/go-ethereum/consensus"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
@@ -36,6 +37,12 @@ type ChainReader interface {
// Config retrieves the header chain's chain configuration.
Config() *params.ChainConfig
+ // Engine retrieves the blockchain's consensus engine.
+ Engine() consensus.Engine
+
+ // GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`
+ GetJustifiedNumber(header *types.Header) uint64
+
// GetTd returns the total difficulty of a local block.
GetTd(common.Hash, uint64) *big.Int
}
@@ -69,12 +76,12 @@ func NewForkChoice(chainReader ChainReader, preserve func(header *types.Header)
}
}
-// ReorgNeeded returns whether the reorg should be applied
+// reorgNeeded returns whether the reorg should be applied
// based on the given external header and local canonical chain.
// In the td mode, the new head is chosen if the corresponding
// total difficulty is higher. In the extern mode, the trusted
// header is always selected as the head.
-func (f *ForkChoice) ReorgNeeded(current *types.Header, header *types.Header) (bool, error) {
+func (f *ForkChoice) reorgNeeded(current *types.Header, header *types.Header) (bool, error) {
var (
localTD = f.chain.GetTd(current.Hash(), current.Number.Uint64())
externTd = f.chain.GetTd(header.Hash(), header.Number.Uint64())
@@ -106,3 +113,24 @@ func (f *ForkChoice) ReorgNeeded(current *types.Header, header *types.Header) (b
}
return reorg, nil
}
+
+// ReorgNeededWithFastFinality compares justified block numbers firstly, backoff to compare tds when equal
+func (f *ForkChoice) ReorgNeededWithFastFinality(current *types.Header, header *types.Header) (bool, error) {
+ _, ok := f.chain.Engine().(consensus.PoSA)
+ if !ok {
+ return f.reorgNeeded(current, header)
+ }
+
+ justifiedNumber, curJustifiedNumber := uint64(0), uint64(0)
+ if f.chain.Config().IsLynn(header.Number) {
+ justifiedNumber = f.chain.GetJustifiedNumber(header)
+ }
+ if f.chain.Config().IsLynn(current.Number) {
+ curJustifiedNumber = f.chain.GetJustifiedNumber(current)
+ }
+ if justifiedNumber == curJustifiedNumber {
+ return f.reorgNeeded(current, header)
+ }
+
+ return justifiedNumber > curJustifiedNumber, nil
+}
diff --git a/core/headerchain.go b/core/headerchain.go
index c55f7c32c7..88ad7593bd 100644
--- a/core/headerchain.go
+++ b/core/headerchain.go
@@ -109,9 +109,36 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
}
hc.currentHeaderHash = hc.CurrentHeader().Hash()
headHeaderGauge.Update(hc.CurrentHeader().Number.Int64())
+ justifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(hc.CurrentHeader())))
+ finalizedBlockGauge.Update(int64(hc.getFinalizedNumber(hc.CurrentHeader())))
+
return hc, nil
}
+// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`.
+func (hc *HeaderChain) GetJustifiedNumber(header *types.Header) uint64 {
+ if p, ok := hc.engine.(consensus.PoSA); ok {
+ justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(hc, header)
+ if err == nil {
+ return justifiedBlockNumber
+ }
+ }
+ // return 0 when err!=nil
+ // so the input `header` will at a disadvantage during reorg
+ return 0
+}
+
+// getFinalizedNumber returns the highest finalized number before the specific block.
+func (hc *HeaderChain) getFinalizedNumber(header *types.Header) uint64 {
+ if p, ok := hc.engine.(consensus.PoSA); ok {
+ if finalizedHeader := p.GetFinalizedHeader(hc, header); finalizedHeader != nil {
+ return finalizedHeader.Number.Uint64()
+ }
+ }
+
+ return 0
+}
+
// GetBlockNumber retrieves the block number belonging to the given hash
// from the cache or database
func (hc *HeaderChain) GetBlockNumber(hash common.Hash) *uint64 {
@@ -285,7 +312,7 @@ func (hc *HeaderChain) writeHeadersAndSetHead(headers []*types.Header, forker *F
}
)
// Ask the fork choicer if the reorg is necessary
- if reorg, err := forker.ReorgNeeded(hc.CurrentHeader(), lastHeader); err != nil {
+ if reorg, err := forker.ReorgNeededWithFastFinality(hc.CurrentHeader(), lastHeader); err != nil {
return nil, err
} else if !reorg {
if inserted != 0 {
@@ -583,6 +610,8 @@ func (hc *HeaderChain) SetCurrentHeader(head *types.Header) {
hc.currentHeader.Store(head)
hc.currentHeaderHash = head.Hash()
headHeaderGauge.Update(head.Number.Int64())
+ justifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(head)))
+ finalizedBlockGauge.Update(int64(hc.getFinalizedNumber(head)))
}
type (
@@ -638,6 +667,8 @@ func (hc *HeaderChain) SetHead(head uint64, updateFn UpdateHeadBlocksCallback, d
hc.currentHeader.Store(parent)
hc.currentHeaderHash = parentHash
headHeaderGauge.Update(parent.Number.Int64())
+ justifiedBlockGauge.Update(int64(hc.GetJustifiedNumber(parent)))
+ finalizedBlockGauge.Update(int64(hc.getFinalizedNumber(parent)))
// If this is the first iteration, wipe any leftover data upwards too so
// we don't end up with dangling daps in the database
diff --git a/core/state/snapshot/generate.go b/core/state/snapshot/generate.go
index 9d74ca4d9b..98fa40ad2e 100644
--- a/core/state/snapshot/generate.go
+++ b/core/state/snapshot/generate.go
@@ -199,7 +199,7 @@ func journalProgress(db ethdb.KeyValueWriter, marker []byte, stats *generatorSta
default:
logstr = fmt.Sprintf("%#x:%#x", marker[:common.HashLength], marker[common.HashLength:])
}
- log.Debug("Journalled generator progress", "progress", logstr)
+ log.Debug("Journaled generator progress", "progress", logstr)
rawdb.WriteSnapshotGenerator(db, blob)
}
diff --git a/core/systemcontracts/upgrade.go b/core/systemcontracts/upgrade.go
index 3255a4605b..feae2f0133 100644
--- a/core/systemcontracts/upgrade.go
+++ b/core/systemcontracts/upgrade.go
@@ -51,6 +51,8 @@ var (
moranUpgrade = make(map[string]*Upgrade)
planckUpgrade = make(map[string]*Upgrade)
+
+ bonehUpgrade = make(map[string]*Upgrade)
)
func init() {
@@ -551,6 +553,68 @@ func init() {
},
}
+ bonehUpgrade[mainNet] = &Upgrade{
+ UpgradeName: "boneh",
+ Configs: []*UpgradeConfig{
+ {
+ ContractAddr: common.HexToAddress(ValidatorContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/f8bab13f56955e979bfb754425dab1e62e52f151",
+ Code: "60806040526004361061046c5760003560e01c8063862498821161024a578063c6d3394511610139578063e40716a1116100b6578063f9a2bbc71161007a578063f9a2bbc714610b6b578063fc3e590814610b80578063fccc281314610b95578063fd4ad81f14610baa578063fd6a687914610bd957610473565b8063e40716a114610af9578063eb57e20214610b0e578063eda5868c14610b2e578063f340fa0114610b43578063f92eb86b14610b5657610473565b8063d86222d5116100fd578063d86222d514610a90578063daacdb6614610aa5578063dc927faf14610aba578063e086c7b114610acf578063e1c7392a14610ae457610473565b8063c6d3394514610a3c578063c81b166214610a51578063c8509d811461085f578063d04aa99614610a66578063d68fb56a14610a7b57610473565b8063a5422d5c116101c7578063ad3c9da61161018b578063ad3c9da6146109d0578063aef198a9146109f0578063b7ab4db514610a05578063b8cf4ef114610a27578063bf9f49951461062f57610473565b8063a5422d5c1461095c578063a78abc1614610971578063aaf5eb6814610986578063ab51bb961461099b578063ac431751146109b057610473565b806396713da91161020e57806396713da9146108f35780639dc09262146109085780639fe0f8161461091d578063a0dc275814610932578063a1a11bf51461094757610473565b8063862498821461087f57806388b32f11146108945780638b5ad0c9146108a95780638d19a410146108be5780639369d7de146108de57610473565b80634df6e0c3116103665780636e47b482116102e35780637942fd05116102a75780637942fd05146108205780637a84ca2a1461083557806381650b621461084a578063831d65d11461085f578063853230aa1461080b57610473565b80636e47b482146107b757806370fd5bad146107cc578063718a8aa8146107e157806375d47a0a146107f657806378dfed4a1461080b57610473565b8063565c56b31161032a578063565c56b3146107265780635667515a146107465780635d77156c1461075b57806362b72cf5146107705780636969a25c1461078557610473565b80634df6e0c3146106b25780635192c82c146106c757806351e80672146106dc578063549b03f2146106f157806355614fcc1461070657610473565b8063321d398a116103f45780633dffc387116103b85780633dffc3871461062f57806343756e5c1461065157806345cf9daf14610666578063493279b11461067b5780634bf6c8821461069d57610473565b8063321d398a146105975780633365af3a146105b757806335409f7f146105d75780633b071dcc146105f75780633de0f0d81461061a57610473565b80631182b8751161043b5780631182b875146104fe578063152ad3b81461052b5780631ff180691461054d578063219f22d514610562578063300c35671461057757610473565b806304c4fec61461047857806307a568471461048f5780630bee7a67146104ba5780630e2374a5146104dc57610473565b3661047357005b600080fd5b34801561048457600080fd5b5061048d610bee565b005b34801561049b57600080fd5b506104a4610c60565b6040516104b19190616d9d565b60405180910390f35b3480156104c657600080fd5b506104cf610c66565b6040516104b19190616dc7565b3480156104e857600080fd5b506104f1610c6b565b6040516104b191906161a4565b34801561050a57600080fd5b5061051e61051936600461608a565b610c71565b6040516104b1919061631b565b34801561053757600080fd5b50610540610ea9565b6040516104b19190616310565b34801561055957600080fd5b506104a4610eb2565b34801561056e57600080fd5b506104cf610eb8565b34801561058357600080fd5b5061048d610592366004615f53565b610ebd565b3480156105a357600080fd5b506105406105b2366004616037565b611263565b3480156105c357600080fd5b506105406105d2366004616037565b611332565b3480156105e357600080fd5b5061048d6105f2366004615f2c565b6113e3565b34801561060357600080fd5b5061060c61153c565b6040516104b1929190616226565b34801561062657600080fd5b506104a4611818565b34801561063b57600080fd5b5061064461181e565b6040516104b19190616dd8565b34801561065d57600080fd5b506104f1611823565b34801561067257600080fd5b506104a4611829565b34801561068757600080fd5b5061069061182f565b6040516104b19190616d8e565b3480156106a957600080fd5b50610644611834565b3480156106be57600080fd5b5061060c611839565b3480156106d357600080fd5b506104a46119b7565b3480156106e857600080fd5b506104f16119bd565b3480156106fd57600080fd5b506104a46119c3565b34801561071257600080fd5b50610540610721366004615f2c565b6119c9565b34801561073257600080fd5b506104a4610741366004615f2c565b6119fe565b34801561075257600080fd5b50610644611a4f565b34801561076757600080fd5b506104cf611a54565b34801561077c57600080fd5b506104a4611a59565b34801561079157600080fd5b506107a56107a0366004616037565b611a5f565b6040516104b1969594939291906161d1565b3480156107c357600080fd5b506104f1611ac3565b3480156107d857600080fd5b50610644611ac9565b3480156107ed57600080fd5b50610644611ace565b34801561080257600080fd5b506104f1611ad3565b34801561081757600080fd5b506104a4611ad9565b34801561082c57600080fd5b50610644611adf565b34801561084157600080fd5b506104a4611ae4565b34801561085657600080fd5b506104cf611aea565b34801561086b57600080fd5b5061048d61087a36600461608a565b611aef565b34801561088b57600080fd5b506104a4611b50565b3480156108a057600080fd5b506104a4611b56565b3480156108b557600080fd5b506104a4611b5c565b3480156108ca57600080fd5b506104a46108d9366004615f2c565b611b62565b3480156108ea57600080fd5b5061048d611ba2565b3480156108ff57600080fd5b50610644611cb6565b34801561091457600080fd5b506104f1611cbb565b34801561092957600080fd5b506104a4611cc1565b34801561093e57600080fd5b506104a4611cc6565b34801561095357600080fd5b506104f1611ccb565b34801561096857600080fd5b5061051e611cd1565b34801561097d57600080fd5b50610540611cf0565b34801561099257600080fd5b506104a4611cf9565b3480156109a757600080fd5b506104cf611a4f565b3480156109bc57600080fd5b5061048d6109cb366004615fdb565b611d02565b3480156109dc57600080fd5b506104a46109eb366004615f2c565b6125ae565b3480156109fc57600080fd5b506104a46125c0565b348015610a1157600080fd5b50610a1a6125cd565b6040516104b19190616213565b348015610a3357600080fd5b506104a46126b9565b348015610a4857600080fd5b506104a4611ac9565b348015610a5d57600080fd5b506104f16126be565b348015610a7257600080fd5b506104a46126c4565b348015610a8757600080fd5b506104a46126c9565b348015610a9c57600080fd5b506104a4612708565b348015610ab157600080fd5b506104a4612714565b348015610ac657600080fd5b506104f161271a565b348015610adb57600080fd5b506104a4612720565b348015610af057600080fd5b5061048d612725565b348015610b0557600080fd5b506104a46128d4565b348015610b1a57600080fd5b5061048d610b29366004615f2c565b6128da565b348015610b3a57600080fd5b506104cf6129e2565b61048d610b51366004615f2c565b6129e7565b348015610b6257600080fd5b506104a4612c6f565b348015610b7757600080fd5b506104f1612c75565b348015610b8c57600080fd5b50610644611cc1565b348015610ba157600080fd5b506104f1612c7b565b348015610bb657600080fd5b50610bca610bc5366004616037565b612c81565b6040516104b193929190616da6565b348015610be557600080fd5b506104f1612d43565b6000610bf933611b62565b9050600b8181548110610c0857fe5b600091825260209091206001601690920201015460ff16610c445760405162461bcd60e51b8152600401610c3b90616a46565b60405180910390fd5b6000610c4e6126c9565b9050610c5b338383612d49565b505050565b60095481565b606481565b61200181565b60005460609060ff16610c965760405162461bcd60e51b8152600401610c3b906164da565b3361200014610cb75760405162461bcd60e51b8152600401610c3b90616c25565b600b54610d7557610cc6615c18565b60015460005b81811015610d7157600b80546001810182556000919091528351600080516020616e50833981519152601690920291820190815560208086015160008051602061747f8339815191528401805460ff1916911515919091179055604086015180518794610d4d93600080516020616e70833981519152909101920190615c47565b506060820151610d639060038301906013615cc1565b505050806001019050610ccc565b5050505b610d7d615cee565b6000610dbe85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f3592505050565b9150915080610dda57610dd160646130f1565b92505050610ea2565b815160009060ff16610dff57610df883602001518460400151613152565b9050610e6e565b825160ff1660011415610e6a57826020015151600114610e4457600080516020616e30833981519152604051610e349061692d565b60405180910390a1506067610e65565b610df88360200151600081518110610e5857fe5b6020026020010151613da6565b610e6e565b5060655b63ffffffff8116610e935750506040805160008152602081019091529150610ea29050565b610e9c816130f1565b93505050505b9392505050565b60075460ff1681565b60035481565b606881565b334114610edc5760405162461bcd60e51b8152600401610c3b90616c74565b6010544311610efd5760405162461bcd60e51b8152600401610c3b90616636565b60005460ff16610f1f5760405162461bcd60e51b8152600401610c3b906164da565b600f54610f37576032600f5561100231601155611259565b60006110023181610f578268056bc75e2d6310000063ffffffff613f1d16565b1115610f7557610f6e81606463ffffffff613f5f16565b9150610fd1565b6000610f8c60115483613f1d90919063ffffffff16565b1115610fca57610f6e6064610fbe600f54610fb260115486613f1d90919063ffffffff16565b9063ffffffff613fa116565b9063ffffffff613f5f16565b5050611259565b6040516309a99b4f60e41b815261100290639a99b4f090610ff890309086906004016161b8565b602060405180830381600087803b15801561101257600080fd5b505af1158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061604f565b6110023160115591508161105f575050611259565b6000805b8481101561108d5785858281811061107757fe5b9050602002013582019150806001019050611063565b508061109b57505050611259565b6000806000805b8981101561125157848989838181106110b757fe5b905060200201358802816110c757fe5b0493508a8a828181106110d657fe5b90506020020160208101906110eb9190615f2c565b6001600160a01b0381166000908152600460205260409020549093509150811561120757600060018084038154811061112057fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561118d57836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85866040516111809190616d9d565b60405180910390a2611201565b6003546111a0908663ffffffff613fdb16565b60039081558101546111b8908663ffffffff613fdb16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b2906111f8908890616d9d565b60405180910390a25b50611249565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85856040516112409190616d9d565b60405180910390a25b6001016110a2565b505050505050505b5050436010555050565b60015460009082106112775750600061132d565b60006001600160a01b03166001838154811061128f57fe5b60009182526020909120600490910201546001600160a01b031614806112bf575060085415806112bf5750600a54155b806112ce575060085460095410155b806112df57506112dd82611332565b155b8061130857506000600b83815481106112f457fe5b906000526020600020906016020160000154115b8061131c575060016113186125cd565b5111155b156113295750600061132d565b5060015b919050565b60015460009082106113465750600061132d565b600b548210611383576001828154811061135c57fe5b9060005260206000209060040201600201601c9054906101000a900460ff1615905061132d565b6001828154811061139057fe5b9060005260206000209060040201600201601c9054906101000a900460ff161580156113dd5750600b82815481106113c457fe5b600091825260209091206001601690920201015460ff16155b92915050565b33611001146114045760405162461bcd60e51b8152600401610c3b90616d45565b600b546114c257611413615c18565b60015460005b818110156114be57600b80546001810182556000919091528351600080516020616e50833981519152601690920291820190815560208086015160008051602061747f8339815191528401805460ff191691151591909117905560408601518051879461149a93600080516020616e70833981519152909101920190615c47565b5060608201516114b09060038301906013615cc1565b505050806001019050611419565b5050505b6001600160a01b038116600090815260046020526040902054806114e65750611539565b6001810390506000600b82815481106114fb57fe5b600091825260209091206001601690920201015460ff16905061151e8383614000565b80156115275750805b15610c5b576009805460001901905550505b50565b60015460609081906000805b8281101561158f576001818154811061155d57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611587576001909101905b600101611548565b506060816040519080825280602002602001820160405280156115bc578160200160208202803683370190505b5090506060826040519080825280602002602001820160405280156115f557816020015b60608152602001906001900390816115e05790505b50600b54600094509091508414156117705760005b8481101561176a576001818154811061161f57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611762576001818154811061164f57fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061167a57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b81815481106116a757fe5b600091825260209182902060026016909202018101805460408051601f60001961010060018616150201909316949094049182018590048502840185019052808352919290919083018282801561173f5780601f106117145761010080835404028352916020019161173f565b820191906000526020600020905b81548152906001019060200180831161172257829003601f168201915b505050505082858151811061175057fe5b60209081029190910101526001909301925b60010161160a565b5061180c565b60005b8481101561180a576001818154811061178857fe5b9060005260206000209060040201600201601c9054906101000a900460ff1661180257600181815481106117b857fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106117e357fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101611773565b505b909450925050505b9091565b61271081565b600181565b61100181565b60085481565b603881565b600881565b600e54600c5460609182918061184d575060155b60606118576125cd565b90506060611864826143b3565b90508282511161187b579094509250611814915050565b8383835103101561188d578282510393505b83156118c35760c843046118a983838388880360008a8a614521565b6118c18383838888038989038a8b8b8b510301614521565b505b6060836040519080825280602002602001820160405280156118ef578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561192857816020015b60608152602001906001900390816119135790505b50905060005b858110156119a95784818151811061194257fe5b602002602001015183828151811061195657fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083818151811061198257fe5b602002602001015182828151811061199657fe5b602090810291909101015260010161192e565b509096509450505050509091565b60065481565b61200081565b600f5481565b6001600160a01b038116600090815260046020526040812054806119f157600091505061132d565b60001901610ea281611332565b6001600160a01b03811660009081526004602052604081205480611a2657600091505061132d565b600180820381548110611a3557fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b60105481565b60018181548110611a6c57fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b606681565b3361200014611b105760405162461bcd60e51b8152600401610c3b90616c25565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051611b4393929190616de6565b60405180910390a1505050565b60025481565b60115481565b600a5481565b6001600160a01b03811660009081526004602052604081205480611b985760405162461bcd60e51b8152600401610c3b90616bad565b6000190192915050565b600b54611c6057611bb1615c18565b60015460005b81811015611c5c57600b80546001810182556000919091528351600080516020616e50833981519152601690920291820190815560208086015160008051602061747f8339815191528401805460ff1916911515919091179055604086015180518794611c3893600080516020616e70833981519152909101920190615c47565b506060820151611c4e9060038301906013615cc1565b505050806001019050611bb7565b5050505b600854611c6d5760036008555b600a54611c7a576002600a555b6000611c8533611b62565b9050611c9081611263565b611cac5760405162461bcd60e51b8152600401610c3b906168ea565b6115393382614678565b600981565b61100781565b600381565b60c881565b61100681565b6040518061062001604052806105ef8152602001616e906105ef913981565b60005460ff1681565b6402540be40081565b60005460ff16611d245760405162461bcd60e51b8152600401610c3b906164da565b3361100714611d455760405162461bcd60e51b8152600401610c3b906169b3565b611daf84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506147109050565b15611e4c5760208114611dd45760405162461bcd60e51b8152600401610c3b90616b67565b604080516020601f8401819004810282018101909252828152600091611e129185858083850183828082843760009201919091525061476992505050565b905060648110158015611e285750620186a08111155b611e445760405162461bcd60e51b8152600401610c3b90616793565b60025561256b565b611eac84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506147109050565b15611f485760208114611ed15760405162461bcd60e51b8152600401610c3b90616360565b604080516020601f8401819004810282018101909252828152600091611f0f9185858083850183828082843760009201919091525061476992505050565b9050612710811115611f335760405162461bcd60e51b8152600401610c3b90616678565b6006556007805460ff1916600117905561256b565b611fb284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506147109050565b1561204c5760208114611fd75760405162461bcd60e51b8152600401610c3b90616397565b604080516020601f84018190048102820181019092528281526000916120159185858083850183828082843760009201919091525061476992505050565b600c5490915080612024575060155b8082106120435760405162461bcd60e51b8152600401610c3b906166eb565b5060085561256b565b6120b584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506147109050565b1561214e57602081146120da5760405162461bcd60e51b8152600401610c3b90616460565b604080516020601f84018190048102820181019092528281526000916121189185858083850183828082843760009201919091525061476992505050565b905060008111801561212a5750600a81105b6121465760405162461bcd60e51b8152600401610c3b90616cc1565b600a5561256b565b6121c284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506147109050565b1561225157602081146121e75760405162461bcd60e51b8152600401610c3b90616414565b604080516020601f84018190048102820181019092528281526000916122259185858083850183828082843760009201919091525061476992505050565b9050600d548111156122495760405162461bcd60e51b8152600401610c3b90616809565b600e5561256b565b6122ba84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506147109050565b1561233c57602081146122df5760405162461bcd60e51b8152600401610c3b90616a01565b604080516020601f840181900481028201810190925282815260009161231d9185858083850183828082843760009201919091525061476992505050565b600d819055600e5490915081101561233657600d54600e555b5061256b565b6123a084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506147109050565b1561244e57602081146123c55760405162461bcd60e51b8152600401610c3b906164a5565b604080516020601f84018190048102820181019092528281526000916124039185858083850183828082843760009201919091525061476992505050565b9050600081116124255760405162461bcd60e51b8152600401610c3b90616548565b60298111156124465760405162461bcd60e51b8152600401610c3b90616590565b600c5561256b565b6124b884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601381527266696e616c697479526577617264526174696f60681b602082015291506147109050565b1561255357602081146124dd5760405162461bcd60e51b8152600401610c3b90616aea565b604080516020601f840181900481028201810190925282815260009161251b9185858083850183828082843760009201919091525061476992505050565b90506001811015801561252f575060648111155b61254b5760405162461bcd60e51b8152600401610c3b90616878565b600f5561256b565b60405162461bcd60e51b8152600401610c3b90616d1e565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516125a0949392919061632e565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156125fc576125e881611332565b156125f4578160010191505b6001016125d7565b50606081604051908082528060200260200182016040528015612629578160200160208202803683370190505b5090506000915060005b838110156126b05761264481611332565b156126a8576001818154811061265657fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061268157fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101612633565b50925050505b90565b601581565b61100281565b603281565b60006126d36125cd565b519050600080600c54116126e85760156126ec565b600c545b9050808211156126fa578091505b8161270457600191505b5090565b67016345785d8a000081565b60055481565b61100381565b602981565b60005460ff16156127485760405162461bcd60e51b8152600401610c3b90616ab3565b612750615cee565b60006127766040518061062001604052806105ef8152602001616e906105ef9139612f35565b91509150806127975760405162461bcd60e51b8152600401610c3b90616be4565b60005b8260200151518110156128bc576001836020015182815181106127b957fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061288f57fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161279a565b50506103e8600255506000805460ff19166001179055565b600d5481565b33611001146128fb5760405162461bcd60e51b8152600401610c3b90616d45565b600b546129b95761290a615c18565b60015460005b818110156129b557600b80546001810182556000919091528351600080516020616e50833981519152601690920291820190815560208086015160008051602061747f8339815191528401805460ff191691151591909117905560408601518051879461299193600080516020616e70833981519152909101920190615c47565b5060608201516129a79060038301906013615cc1565b505050806001019050612910565b5050505b60006129c48261476e565b90506129cf81611263565b156129de576129de8282614678565b5050565b606581565b334114612a065760405162461bcd60e51b8152600401610c3b90616c74565b60005460ff16612a285760405162461bcd60e51b8152600401610c3b906164da565b60003411612a485760405162461bcd60e51b8152600401610c3b906167da565b6001600160a01b0381166000908152600460205260409020546007543491906103e89060ff1615612a7857506006545b600083118015612a885750600081115b15612b29576000612aa5612710610fbe868563ffffffff613fa116565b90508015612b275760405161dead9082156108fc029083906000818181858888f19350505050158015612adc573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee581604051612b0c9190616d9d565b60405180910390a1612b24848263ffffffff613f1d16565b93505b505b8115612c27576000600180840381548110612b4057fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615612bad57846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b485604051612ba09190616d9d565b60405180910390a2612c21565b600354612bc0908563ffffffff613fdb16565b6003908155810154612bd8908563ffffffff613fdb16565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc05590612c18908790616d9d565b60405180910390a25b50612c69565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b484604051612c609190616d9d565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b8181548110612c8e57fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015612d395780601f10612d0e57610100808354040283529160200191612d39565b820191906000526020600020905b815481529060010190602001808311612d1c57829003601f168201915b5050505050905083565b61100481565b6000600a5460001480612d5a575081155b80612d655750600954155b15612d7257506000610ea2565b60096000815460019003919050819055506000612dbd600a54610fbe85610fbe600b8981548110612d9f57fe5b6000918252602090912060169091020154439063ffffffff613f1d16565b90506000600b8581548110612dce57fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015612e3357600080fd5b505afa158015612e47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6b9190616067565b9150915060009350808310612ee557612e848787614000565b506040516305bfb49960e41b815261100190635bfb499090612eaa908a906004016161a4565b600060405180830381600087803b158015612ec457600080fd5b505af1158015612ed8573d6000803e3d6000fd5b5050505060019350612ef7565b818310612ef757612ef58761476e565b505b6040516001600160a01b038816907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050509392505050565b612f3d615cee565b6000612f47615cee565b612f4f615d12565b612f60612f5b86614911565b614936565b90506000805b612f6f83614980565b156130e35780612f9457612f8a612f85846149a1565b6149ef565b60ff1684526130db565b80600114156130d6576060612fb0612fab856149a1565b614a6f565b90508051604051908082528060200260200182016040528015612fed57816020015b612fda615d32565b815260200190600190039081612fd25790505b508560200181905250805160405190808252806020026020018201604052801561302b57816020015b60608152602001906001900390816130165790505b50604086015260005b81518110156130cb57613045615d32565b6060600061306585858151811061305857fe5b6020026020010151614b40565b92509250925080613085578860009a509a505050505050505050506130ec565b828960200151858151811061309657fe5b602002602001018190525081896040015185815181106130b257fe5b6020026020010181905250505050806001019050613034565b5060019250506130db565b6130e3565b600101612f66565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b606081526020019060019003908161310b5790505090506131318363ffffffff16614c5a565b8160008151811061313e57fe5b6020026020010181905250610ea281614c6d565b600060298351111561318957600080516020616e30833981519152604051613179906165ed565b60405180910390a15060666113dd565b60005b83518110156132275760005b8181101561321e578481815181106131ac57fe5b6020026020010151600001516001600160a01b03168583815181106131cd57fe5b6020026020010151600001516001600160a01b0316141561321657600080516020616e3083398151915260405161320390616748565b60405180910390a16066925050506113dd565b600101613198565b5060010161318c565b506060806132358585614cf7565b60015491935091506000908190815b818110156132ba5767016345785d8a00006001828154811061326257fe5b90600052602060002090600402016003015410613284578360010193506132b2565b60006001828154811061329357fe5b90600052602060002090600402016003015411156132b2578260010192505b600101613244565b506060836040519080825280602002602001820160405280156132e7578160200160208202803683370190505b509050606084604051908082528060200260200182016040528015613316578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015613345578160200160208202803683370190505b509050606086604051908082528060200260200182016040528015613374578160200160208202803683370190505b50905060006060876040519080825280602002602001820160405280156133a5578160200160208202803683370190505b5090506060886040519080825280602002602001820160405280156133d4578160200160208202803683370190505b509050600099506000985060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561341c57600080fd5b505afa158015613430573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613454919061604f565b905067016345785d8a000081111561349f57600080516020616e3083398151915260405161348190616a72565b60405180910390a160689d50505050505050505050505050506113dd565b60005b898110156137105767016345785d8a0000600182815481106134c057fe5b9060005260206000209060040201600301541061364557600181815481106134e457fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898d8151811061351557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be4006001838154811061354a57fe5b9060005260206000209060040201600301548161356357fe5b066001838154811061357157fe5b9060005260206000209060040201600301540390506135998382613f1d90919063ffffffff16565b898e815181106135a557fe5b602002602001018181525050600182815481106135be57fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316878e815181106135ef57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888e8151811061361c57fe5b6020908102919091010152613637868263ffffffff613fdb16565b95508c6001019c5050613708565b60006001828154811061365457fe5b9060005260206000209060040201600301541115613708576001818154811061367957fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848c815181106136aa57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600181815481106136d757fe5b906000526020600020906004020160030154838c815181106136f557fe5b6020026020010181815250508a6001019a505b6001016134a2565b5060008415613986576002546040516303702b2960e51b815261100491636e05652091889161374a918e918e918d91420190600401616296565b6020604051808303818588803b15801561376357600080fd5b505af193505050508015613794575060408051601f3d908101601f1916820190925261379191810190615fbb565b60015b61390b576040516000815260443d10156137b05750600061384b565b60046000803e60005160e01c6308c379a081146137d157600091505061384b565b60043d036004833e81513d60248201116001600160401b03821117156137fc5760009250505061384b565b80830180516001600160401b0381111561381d57600094505050505061384b565b8060208301013d860181111561383b5760009550505050505061384b565b601f01601f191660405250925050505b806138565750613898565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf2808260405161388a919061631b565b60405180910390a250613906565b3d8080156138c2576040519150601f19603f3d011682016040523d82523d6000602084013e6138c7565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a45826040516138fc919061631b565b60405180910390a2505b613986565b801561394d577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b70866040516139409190616d9d565b60405180910390a1613984565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28060405161397b906163dd565b60405180910390a25b505b8015613b3c5760005b8751811015613b3a5760008882815181106139a657fe5b602002602001015190506000600182815481106139bf57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc91859081106139f057fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015613aac5760018281548110613a3157fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110613a8057fe5b906000526020600020906004020160030154604051613a9f9190616d9d565b60405180910390a2613b30565b60018281548110613ab957fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110613b0857fe5b906000526020600020906004020160030154604051613b279190616d9d565b60405180910390a25b505060010161398f565b505b835115613c865760005b8451811015613c84576000858281518110613b5d57fe5b60200260200101516001600160a01b03166108fc868481518110613b7d57fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015613c1357858281518110613bb357fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110613bf157fe5b6020026020010151604051613c069190616d9d565b60405180910390a2613c7b565b858281518110613c1f57fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110613c5d57fe5b6020026020010151604051613c729190616d9d565b60405180910390a25b50600101613b46565b505b5050505050505050505050506000471115613d02577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d47604051613cca9190616d9d565b60405180910390a1604051611002904780156108fc02916000818181858888f19350505050158015613d00573d6000803e3d6000fd5b505b60006003819055600555815115613d1d57613d1d8282614f30565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613d5a57600080fd5b505af1158015613d6e573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b80516001600160a01b0316600090815260046020526040812054801580613df75750600180820381548110613dd757fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b15613e3d5782516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a2600091505061132d565b600154600554600019820111801590613e935784516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a26000935050505061132d565b600580546001908101909155805481906000198601908110613eb157fe5b6000918252602082206002600490920201018054921515600160e01b0260ff60e01b199093169290921790915585516040516001600160a01b03909116917ff226e7d8f547ff903d9d419cf5f54e0d7d07efa9584135a53a057c5f1f27f49a91a2506000949350505050565b6000610ea283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506155fe565b6000610ea283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061562a565b600082613fb0575060006113dd565b82820282848281613fbd57fe5b0414610ea25760405162461bcd60e51b8152600401610c3b90616972565b600082820183811015610ea25760405162461bcd60e51b8152600401610c3b90616511565b6000806001838154811061401057fe5b9060005260206000209060040201600301549050600060018080549050039050600161403a6125cd565b511161406f5760006001858154811061404f57fe5b9060005260206000209060040201600301819055506000925050506113dd565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516140a89190616d9d565b60405180910390a26001600160a01b038516600090815260046020526040812055835b6001546000190181101561429557600181600101815481106140e957fe5b90600052602060002090600402016001828154811061410457fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b8054909183019081106141c557fe5b9060005260206000209060160201600b82815481106141e057fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054614237938386019390821615610100026000190190911604615d67565b5061424a60038281019084016013615ddc565b5090505080600101600460006001848154811061426357fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020556001016140cb565b5060018054806142a157fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b8054806142f457fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906143266002830182615e06565b614334600383016000615e4a565b50509055600081838161434357fe5b04905080156143a75760015460005b818110156143a457826001828154811061436857fe5b906000526020600020906004020160030154016001828154811061438857fe5b6000918252602090912060036004909202010155600101614352565b50505b50600195945050505050565b6001548151604080518281526020808402820101909152606092919083908280156143f257816020015b60608152602001906001900390816143dd5790505b50600b54909150831461440957925061132d915050565b60005b8281101561451857600b60016004600089858151811061442857fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054038154811061445c57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156144f45780601f106144c9576101008083540402835291602001916144f4565b820191906000526020600020905b8154815290600101906020018083116144d757829003601f168201915b505050505082828151811061450557fe5b602090810291909101015260010161440c565b50949350505050565b60005b8281101561466e5760008287838801604051602001614544929190616196565b6040516020818303038152906040528051906020012060001c8161456457fe5b06905080850182870114614665576000898388018151811061458257fe5b602002602001015190506060898489018151811061459c57fe5b602002602001015190508a838801815181106145b457fe5b60200260200101518b858a01815181106145ca57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b848901815181106145f957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061462757fe5b60200260200101518a858a018151811061463d57fe5b6020026020010181905250808a8489018151811061465757fe5b602002602001018190525050505b50600101614524565b5050505050505050565b600980546001908101909155600b80548390811061469257fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b82815481106146c857fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b600081604051602001614723919061617a565b604051602081830303815290604052805190602001208360405160200161474a919061617a565b6040516020818303038152906040528051906020012014905092915050565b015190565b6001600160a01b038116600090815260046020526040812054806147975750600019905061132d565b6001810390506000600182815481106147ac57fe5b90600052602060002090600402016003015490506000600183815481106147cf57fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90614828908590616d9d565b60405180910390a2806148405782935050505061132d565b600081838161484b57fe5b04905080156149075760005b848110156148a957816001828154811061486d57fe5b906000526020600020906004020160030154016001828154811061488d57fe5b6000918252602090912060036004909202010155600101614857565b50600180549085015b818110156149045782600182815481106148c857fe5b90600052602060002090600402016003015401600182815481106148e857fe5b60009182526020909120600360049092020101556001016148b2565b50505b5091949350505050565b614919615e59565b506040805180820190915281518152602082810190820152919050565b61493e615d12565b61494782615661565b61495057600080fd5b600061495f836020015161569b565b60208085015160408051808201909152868152920190820152915050919050565b600061498a615e59565b505080518051602091820151919092015191011190565b6149a9615e59565b6149b282614980565b6149bb57600080fd5b602082015160006149cb826156fe565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590614a0457508151602110155b614a0d57600080fd5b6000614a1c836020015161569b565b90508083600001511015614a425760405162461bcd60e51b8152600401610c3b90616b30565b82516020808501518301805192849003929183101561451857506020919091036101000a90049392505050565b6060614a7a82615661565b614a8357600080fd5b6000614a8e836157df565b9050606081604051908082528060200260200182016040528015614acc57816020015b614ab9615e59565b815260200190600190039081614ab15790505b5090506000614ade856020015161569b565b60208601510190506000805b84811015614b3557614afb836156fe565b9150604051806040016040528083815260200184815250848281518110614b1e57fe5b602090810291909101015291810191600101614aea565b509195945050505050565b614b48615d32565b60606000614b54615d32565b6060614b5e615d12565b614b6787614936565b90506000805b614b7683614980565b15614c4b5780614ba157614b91614b8c846149a1565b61583b565b6001600160a01b03168552614c43565b8060011415614bc957614bb6614b8c846149a1565b6001600160a01b03166020860152614c43565b8060021415614bf157614bde614b8c846149a1565b6001600160a01b03166040860152614c43565b8060031415614c1d57614c06612f85846149a1565b6001600160401b0316606086015260019150614c43565b8060041415614c3e57614c37614c32846149a1565b615855565b9350614c43565b614c4b565b600101614b6d565b50929791965091945092505050565b60606113dd614c68836158c5565b6159ab565b6060815160001415614c8e575060408051600081526020810190915261132d565b606082600081518110614c9d57fe5b602002602001015190506000600190505b8351811015614cde57614cd482858381518110614cc757fe5b60200260200101516159fd565b9150600101614cae565b50610ea2614cf1825160c060ff16615a7a565b826159fd565b606080600080808080614d086126c9565b6001549091505b8015614e1657600181039250600b8381548110614d2857fe5b600091825260209091206001601690920201015460ff16614d4857614e0d565b60018381548110614d5557fe5b60009182526020909120600490910201546001600160a01b03169450614d7c858484612d49565b9350831580614d8f575060018a51038610155b15614d9957614e0d565b60005b8a51811015614e0b57856001600160a01b03168b8281518110614dbb57fe5b6020026020010151600001516001600160a01b03161415614e035760018b8281518110614de457fe5b6020908102919091010151901515608090910152600190960195614e0b565b600101614d9c565b505b60001901614d0f565b5084895103604051908082528060200260200182016040528015614e5457816020015b614e41615d32565b815260200190600190039081614e395790505b50965084895103604051908082528060200260200182016040528015614e8e57816020015b6060815260200190600190039081614e795790505b5095506000915060005b8951811015614f2257898181518110614ead57fe5b602002602001015160800151614f1a57898181518110614ec957fe5b6020026020010151888481518110614edd57fe5b6020026020010181905250888181518110614ef457fe5b6020026020010151878481518110614f0857fe5b60200260200101819052508260010192505b600101614e98565b5050505050505b9250929050565b600154825160005b8281101561504d576001614f4a615d32565b60018381548110614f5757fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b8481101561502157878181518110614fe757fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b031614156150195760009250615021565b600101614fd3565b5081156150435780516001600160a01b03166000908152600460205260408120555b5050600101614f38565b508082111561510c57805b8281101561510a57600180548061506b57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b8054806150be57fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906150f06002830182615e06565b6150fe600383016000615e4a565b50509055600101615058565b505b600081831061511b578161511d565b825b905060005b818110156153b0576151cf86828151811061513957fe5b60200260200101516001838154811061514e57fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152615b4c565b6153835780600101600460008884815181106151e757fe5b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000208190555085818151811061522357fe5b60200260200101516001828154811061523857fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015584518590829081106152f357fe5b6020026020010151600b828154811061530857fe5b9060005260206000209060160201600201908051906020019061532c929190615c47565b506000600b828154811061533c57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061536d57fe5b60009182526020909120601690910201556153a8565b60006001828154811061539257fe5b9060005260206000209060040201600301819055505b600101615122565b5082821115615588576153c1615c18565b835b83811015615585578581815181106153d757fe5b6020026020010151826040018190525060018782815181106153f557fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020616e5083398151915281019182558583015160008051602061747f8339815191528201805491151560ff199092169190911790559285015180518694929361552b93600080516020616e7083398151915201920190615c47565b5060608201516155419060038301906013615cc1565b505050806001016004600089848151811061555857fe5b602090810291909101810151516001600160a01b03168252810191909152604001600020556001016153c3565b50505b6000600981905560015493505b838110156155f6576000600b82815481106155ac57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106155dd57fe5b6000918252602090912060169091020155600101615595565b505050505050565b600081848411156156225760405162461bcd60e51b8152600401610c3b919061631b565b505050900390565b6000818361564b5760405162461bcd60e51b8152600401610c3b919061631b565b50600083858161565757fe5b0495945050505050565b80516000906156725750600061132d565b6020820151805160001a9060c08210156156915760009250505061132d565b5060019392505050565b8051600090811a60808110156156b557600091505061132d565b60b88110806156d0575060c081108015906156d0575060f881105b156156df57600191505061132d565b60c08110156156f35760b51901905061132d565b60f51901905061132d565b80516000908190811a608081101561571957600191506157d8565b60b881101561572e57607e19810191506157d8565b60c081101561577f57600060b78203600186019550806020036101000a8651049150600181018201935050808310156157795760405162461bcd60e51b8152600401610c3b906168bf565b506157d8565b60f88110156157945760be19810191506157d8565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156157d65760405162461bcd60e51b8152600401610c3b906168bf565b505b5092915050565b80516000906157f05750600061132d565b60008090506000615804846020015161569b565b602085015185519181019250015b8082101561583257615823826156fe565b82019150826001019250615812565b50909392505050565b805160009060151461584c57600080fd5b6113dd826149ef565b805160609061586357600080fd5b6000615872836020015161569b565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156158a9576020820181803683370190505b5090506000816020019050614518848760200151018285615bcd565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166159095750601861592d565b6fffffffffffffffffffffffffffffffff1984166159295750601061592d565b5060005b60208110156159635781818151811061594257fe5b01602001516001600160f81b0319161561595b57615963565b60010161592d565b60008160200390506060816040519080825280601f01601f191660200182016040528015615998576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156159dd5750607f60f81b826000815181106159cb57fe5b01602001516001600160f81b03191611155b156159e957508061132d565b6113dd6159fb8351608060ff16615a7a565b835b6060806040519050835180825260208201818101602087015b81831015615a2e578051835260209283019201615a16565b50855184518101855292509050808201602086015b81831015615a5b578051835260209283019201615a43565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310615aa45760405162461bcd60e51b8152600401610c3b906166c3565b60408051600180825281830190925260609160208201818036833701905050905060378411615afe5782840160f81b81600081518110615ae057fe5b60200101906001600160f81b031916908160001a90535090506113dd565b6060615b09856158c5565b90508381510160370160f81b82600081518110615b2257fe5b60200101906001600160f81b031916908160001a905350615b4382826159fd565b95945050505050565b805182516000916001600160a01b039182169116148015615b86575081602001516001600160a01b031683602001516001600160a01b0316145b8015615bab575081604001516001600160a01b031683604001516001600160a01b0316145b8015610ea25750506060908101519101516001600160401b0390811691161490565b80615bd757610c5b565b5b60208110615bf7578251825260209283019290910190601f1901615bd8565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001615c42615e73565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c8857805160ff1916838001178555615cb5565b82800160010185558215615cb5579182015b82811115615cb5578251825591602001919060010190615c9a565b50612704929150615e92565b8260138101928215615cb55791602002820182811115615cb5578251825591602001919060010190615c9a565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040518060400160405280615d25615e59565b8152602001600081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615da05780548555615cb5565b82800160010185558215615cb557600052602060002091601f016020900482015b82811115615cb5578254825591600101919060010190615dc1565b8260138101928215615cb55791820182811115615cb5578254825591600101919060010190615dc1565b50805460018160011615610100020316600290046000825580601f10615e2c5750611539565b601f0160209004906000526020600020908101906115399190615e92565b50611539906013810190615e92565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b6126b691905b808211156127045760008155600101615e98565b60008083601f840112615ebd578182fd5b5081356001600160401b03811115615ed3578182fd5b6020830191508360208083028501011115614f2957600080fd5b60008083601f840112615efe578182fd5b5081356001600160401b03811115615f14578182fd5b602083019150836020828501011115614f2957600080fd5b600060208284031215615f3d578081fd5b81356001600160a01b0381168114610ea2578182fd5b60008060008060408587031215615f68578283fd5b84356001600160401b0380821115615f7e578485fd5b615f8a88838901615eac565b90965094506020870135915080821115615fa2578384fd5b50615faf87828801615eac565b95989497509550505050565b600060208284031215615fcc578081fd5b81518015158114610ea2578182fd5b60008060008060408587031215615ff0578384fd5b84356001600160401b0380821115616006578586fd5b61601288838901615eed565b9096509450602087013591508082111561602a578384fd5b50615faf87828801615eed565b600060208284031215616048578081fd5b5035919050565b600060208284031215616060578081fd5b5051919050565b60008060408385031215616079578182fd5b505080516020909101519092909150565b60008060006040848603121561609e578283fd5b833560ff811681146160ae578384fd5b925060208401356001600160401b038111156160c8578283fd5b6160d486828701615eed565b9497909650939450505050565b6000815180845260208085019450808401835b838110156161195781516001600160a01b0316875295820195908201906001016160f4565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452616166816020860160208601616e03565b601f01601f19169290920160200192915050565b6000825161618c818460208701616e03565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b600060208252610ea260208301846160e1565b60006040825261623960408301856160e1565b602083820381850152818551808452828401915082838202850101838801865b8381101561628757601f1987840301855261627583835161614e565b94860194925090850190600101616259565b50909998505050505050505050565b6000608082526162a960808301876160e1565b828103602084810191909152865180835287820192820190845b818110156162df578451835293830193918301916001016162c3565b505084810360408601526162f381886160e1565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b600060208252610ea2602083018461614e565b600060408252616342604083018688616124565b8281036020840152616355818587616124565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252602b908201527f746865206275726e526174696f206d757374206265206e6f206772656174657260408201526a0207468616e2031303030360ac1b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b60208082526027908201527f7468652066696e616c697479526577617264526174696f206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662066696e616c697479526577617264526174696f206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152615b43606083018461614e565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260406020830152615b43604083018486616124565b60005b83811015616e1e578181015183820152602001616e06565b83811115612c69575050600091015256fe70e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbbf905ec80f905e8f846942a7cdd959bfe8d9487b2a43b33565295a698f7e294b6a7edd747c0554875d3fc531d19ba1497992c5e941ff80f3f7f110ffd8920a3ac38fdef318fe94a3f86048c27395000f846946488aa4d1955ee33403f8ccb1d4de5fb97c7ade294220f003d8bdfaadf52aa1e55ae4cc485e6794875941a87e90e440a39c99aa9cb5cea0ad6a3f0b2407b86048c27395000f846949ef9f4360c606c7ab4db26b016007d3ad0ab86a0946103af86a874b705854033438383c82575f25bc29418e2db06cbff3e3c5f856410a1838649e760175786048c27395000f84694ee01c3b1283aa067c58eab4709f85e99d46de5fe94ee4b9bfb1871c64e2bcabb1dc382dc8b7c4218a29415904ab26ab0e99d70b51c220ccdcccabee6e29786048c27395000f84694685b1ded8013785d6623cc18d214320b6bb6475994a20ef4e5e4e7e36258dbf51f4d905114cb1b34bc9413e39085dc88704f4394d35209a02b1a9520320c86048c27395000f8469478f3adfc719c99674c072166708589033e2d9afe9448a30d5eaa7b64492a160f139e2da2800ec3834e94055838358c29edf4dcc1ba1985ad58aedbb6be2b86048c27395000f84694c2be4ec20253b8642161bc3f444f53679c1f3d479466f50c616d737e60d7ca6311ff0d9c434197898a94d1d678a2506eeaa365056fe565df8bc8659f28b086048c27395000f846942f7be8361c80a4c1e7e9aaf001d0877f1cfde218945f93992ac37f3e61db2ef8a587a436a161fd210b94ecbc4fb1a97861344dad0867ca3cba2b860411f086048c27395000f84694ce2fd7544e0b2cc94692d4a704debef7bcb613289444abc67b4b2fba283c582387f54c9cba7c34bafa948acc2ab395ded08bb75ce85bf0f95ad2abc51ad586048c27395000f84694b8f7166496996a7da21cf1f1b04d9b3e26a3d077946770572763289aac606e4f327c2f6cc1aa3b3e3b94882d745ed97d4422ca8da1c22ec49d880c4c097286048c27395000f846942d4c407bbe49438ed859fe965b140dcf1aab71a9943ad0939e120f33518fbba04631afe7a3ed6327b194b2bbb170ca4e499a2b0f3cc85ebfa6e8c4dfcbea86048c27395000f846946bbad7cf34b5fa511d8e963dbba288b1960e75d694853b0f6c324d1f4e76c8266942337ac1b0af1a229442498946a51ca5924552ead6fc2af08b94fcba648601d1a94a2000f846944430b3230294d12c6ab2aac5c2cd68e80b16b581947b107f4976a252a6939b771202c28e64e03f52d694795811a7f214084116949fc4f53cedbf189eeab28601d1a94a2000f84694ea0a6e3c511bbd10f4519ece37dc24887e11b55d946811ca77acfb221a49393c193f3a22db829fcc8e9464feb7c04830dd9ace164fc5c52b3f5a29e5018a8601d1a94a2000f846947ae2f5b9e386cd1b50a4550696d957cb4900f03a94e83bcc5077e6b873995c24bac871b5ad856047e19464e48d4057a90b233e026c1041e6012ada897fe88601d1a94a2000f8469482012708dafc9e1b880fd083b32182b869be8e09948e5adc73a2d233a1b496ed3115464dd6c7b887509428b383d324bc9a37f4e276190796ba5a8947f5ed8601d1a94a2000f8469422b81f8e175ffde54d797fe11eb03f9e3bf75f1d94a1c3ef7ca38d8ba80cce3bfc53ebd2903ed21658942767f7447f7b9b70313d4147b795414aecea54718601d1a94a2000f8469468bf0b8b6fb4e317a0f9d6f03eaf8ce6675bc60d94675cfe570b7902623f47e7f59c9664b5f5065dcf94d84f0d2e50bcf00f2fc476e1c57f5ca2d57f625b8601d1a94a2000f846948c4d90829ce8f72d0163c1d5cf348a862d5506309485c42a7b34309bee2ed6a235f86d16f059deec5894cc2cedc53f0fa6d376336efb67e43d167169f3b78601d1a94a2000f8469435e7a025f4da968de7e4d7e4004197917f4070f194b1182abaeeb3b4d8eba7e6a4162eac7ace23d57394c4fd0d870da52e73de2dd8ded19fe3d26f43a1138601d1a94a2000f84694d6caa02bbebaebb5d7e581e4b66559e635f805ff94c07335cf083c1c46a487f0325769d88e163b653694efaff03b42e41f953a925fc43720e45fb61a19938601d1a94a20000175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa2646970667358221220e27eda2c66e25ae7b26ab5145965b2a511fc42ef0bfcbd883a69eaaf8c697cfa64736f6c63430006040033",
+ },
+ {
+ ContractAddr: common.HexToAddress(SlashContract),
+ CommitUrl: "https://github.com/node-real/bsc-genesis-contract/commit/f8bab13f56955e979bfb754425dab1e62e52f151",
+ Code: "608060405234801561001057600080fd5b50600436106102745760003560e01c80638256ace611610151578063c81b1662116100c3578063dc927faf11610087578063dc927faf1461049a578063e1c7392a146104a2578063f9a2bbc7146104aa578063fc3e5908146104b2578063fc4333cd146104ba578063fd6a6879146104c257610274565b8063c81b166214610451578063c8509d8114610459578063c96be4cb1461046c578063cc844b731461047f578063d2a42e4b1461049257610274565b8063a1a11bf511610115578063a1a11bf514610409578063a78abc1614610411578063ab51bb9614610426578063ac0af6291461042e578063ac43175114610436578063c80d4b8f1461044957610274565b80638256ace6146103d6578063831d65d1146103de57806396713da9146103f15780639bc8e4f2146103f95780639dc092621461040157610274565b80634bf6c882116101ea5780636e47b482116101ae5780636e47b482146103a657806370fd5bad146103ae578063718a8aa8146103b657806375d47a0a146103be5780637912a65d146103c65780637942fd05146103ce57610274565b80634bf6c8821461037157806351e8067214610379578063567a372d146103815780635bfb49901461038957806362b72cf51461039e57610274565b806337c8dab91161023c57806337c8dab914610301578063389f4f71146103225780633a63f4b1146103375780633dffc3871461033f57806343756e5c14610354578063493279b11461035c57610274565b80630bee7a67146102795780630e2374a5146102975780631182b875146102ac57806323bac5a2146102cc57806335aa2e44146102ee575b600080fd5b6102816104ca565b60405161028e9190613056565b60405180910390f35b61029f6104cf565b60405161028e9190612987565b6102bf6102ba3660046128bd565b6104d5565b60405161028e91906129bf565b6102df6102da36600461266b565b61053b565b60405161028e9392919061303e565b61029f6102fc36600461288d565b61055e565b61031461030f36600461266b565b610585565b60405161028e929190613030565b61032a6105dc565b60405161028e9190613006565b61032a6105e2565b6103476105e8565b60405161028e9190613067565b61029f6105ed565b6103646105f3565b60405161028e9190612ff7565b6103476105f8565b61029f6105fd565b61032a610603565b61039c61039736600461266b565b610609565b005b61032a6106b4565b61029f6106ba565b6103476106c0565b6103476106c5565b61029f6106ca565b61032a6106d0565b6103476106d5565b6103146106da565b61039c6103ec3660046128bd565b6106e4565b6103476107f6565b61032a6107fb565b61029f610806565b61029f61080c565b610419610812565b60405161028e91906129b4565b61028161081b565b61032a610820565b61039c610444366004612771565b610825565b61032a610bd9565b61029f610bde565b61039c6104673660046128bd565b610be4565b61039c61047a36600461266b565b610c55565b61039c61048d3660046127da565b611046565b61032a61151c565b61029f611521565b61039c611527565b61029f611563565b610347611569565b61039c61156e565b61029f6119b7565b606481565b61200181565b606033612000146105015760405162461bcd60e51b81526004016104f890612e7d565b60405180910390fd5b60005460ff166105235760405162461bcd60e51b81526004016104f890612a6b565b60405162461bcd60e51b81526004016104f890612f40565b600260208190526000918252604090912080546001820154919092015460ff1683565b6001818154811061056b57fe5b6000918252602090912001546001600160a01b0316905081565b600080610590612452565b5050506001600160a01b0316600090815260026020818152604092839020835160608101855281548082526001830154938201849052919093015460ff16151592909301919091529091565b60055481565b60065481565b600181565b61100181565b603881565b600881565b61200081565b60045481565b336110001461062a5760405162461bcd60e51b81526004016104f890612c91565b60005460ff1661064c5760405162461bcd60e51b81526004016104f890612a6b565b61200063f7a251d7600b61065f846119bd565b60006040518463ffffffff1660e01b815260040161067f93929190613075565b600060405180830381600087803b15801561069957600080fd5b505af11580156106ad573d6000803e3d6000fd5b5050505050565b60035481565b61100581565b600281565b601081565b61100881565b603281565b600b81565b6004546005549091565b33612000146107055760405162461bcd60e51b81526004016104f890612e7d565b60005460ff166107275760405162461bcd60e51b81526004016104f890612a6b565b61072f612475565b600061077084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a8f92505050565b9150915080156107b75781516040517f7f0956d47419b9525356e7111652b653b530ec6f5096dccc04589bc38e629967916107aa91613056565b60405180910390a16106ad565b81516040517f7d45f62d17443dd4547bca8a8112c60e2385669318dc300ec61a5d2492f262e7916107e791613056565b60405180910390a15050505050565b600981565b662386f26fc1000081565b61100781565b61100681565b60005460ff1681565b600081565b600481565b60005460ff166108475760405162461bcd60e51b81526004016104f890612a6b565b33611007146108685760405162461bcd60e51b81526004016104f890612d3a565b6108d384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260148152731b5a5cd9195b59585b9bdc951a1c995cda1bdb1960621b60208201529150611b0f9050565b1561096e57602081146108f85760405162461bcd60e51b81526004016104f890612c1d565b604080516020601f840181900481028201810190925282815260009161093691858580838501838280828437600092019190915250611b6992505050565b90506001811015801561094a575060055481105b6109665760405162461bcd60e51b81526004016104f890612e38565b600455610b96565b6109d484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e19995b1bdb9e551a1c995cda1bdb19608a1b60208201529150611b0f9050565b15610a7057602081146109f95760405162461bcd60e51b81526004016104f890612d88565b604080516020601f8401819004810282018101909252828152600091610a3791858580838501838280828437600092019190915250611b6992505050565b90506103e88111158015610a4c575060045481115b610a685760405162461bcd60e51b81526004016104f890612ad9565b600555610b96565b610ae484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f66696e616c697479536c617368526577617264526174696f000000000000000060208201529150611b0f9050565b15610b7e5760208114610b095760405162461bcd60e51b81526004016104f890612f77565b604080516020601f8401819004810282018101909252828152600091610b4791858580838501838280828437600092019190915250611b6992505050565b9050600a8110158015610b5a5750606481105b610b765760405162461bcd60e51b81526004016104f890612bd1565b600655610b96565b60405162461bcd60e51b81526004016104f890612f19565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a84848484604051610bcb94939291906129d2565b60405180910390a150505050565b609681565b61100281565b3361200014610c055760405162461bcd60e51b81526004016104f890612e7d565b60005460ff16610c275760405162461bcd60e51b81526004016104f890612a6b565b6040517f07db600eebe2ac176be8dcebad61858c245a4961bb32ca2aa3d159b09aa0810e90600090a1505050565b334114610c745760405162461bcd60e51b81526004016104f890612ecc565b60005460ff16610c965760405162461bcd60e51b81526004016104f890612a6b565b6003544311610cb75760405162461bcd60e51b81526004016104f890612fc2565b3a15610cd55760405162461bcd60e51b81526004016104f890612d0c565b60405163155853f360e21b8152611000906355614fcc90610cfa908490600401612987565b60206040518083038186803b158015610d1257600080fd5b505afa158015610d26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4a9190612751565b610d535761103f565b610d5b612452565b506001600160a01b0381166000908152600260208181526040928390208351606081018552815481526001820154928101929092529091015460ff161580159282019290925290610db6576020810180516001019052610e0f565b60016040820181905260208201819052805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0384161790555b438152600554602082015181610e2157fe5b06610f6d57600060208201526040516335409f7f60e01b8152611000906335409f7f90610e52908590600401612987565b600060405180830381600087803b158015610e6c57600080fd5b505af1158015610e80573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b610ea0856119bd565b60006040518463ffffffff1660e01b8152600401610ec093929190613075565b600060405180830381600087803b158015610eda57600080fd5b505af1925050508015610eeb575060015b610f68573d808015610f19576040519150601f19603f3d011682016040523d82523d6000602084013e610f1e565b606091505b50826001600160a01b03167fd7bc86ff5d08c8ab043edec743302aba2520e6635172a428bc956721db9e2d1c836020015183604051610f5e92919061300f565b60405180910390a2505b610fd9565b600454816020015181610f7c57fe5b06610fd9576040516375abf10160e11b81526110009063eb57e20290610fa6908590600401612987565b600060405180830381600087803b158015610fc057600080fd5b505af1158015610fd4573d6000803e3d6000fd5b505050505b6001600160a01b0382166000818152600260208181526040808420865181559186015160018301558581015191909201805460ff1916911515919091179055517fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9190a2505b5043600355565b60005460ff166110685760405162461bcd60e51b81526004016104f890612a6b565b604051630a83aaa960e31b81526110069063541d55489061108d903390600401612987565b60206040518083038186803b1580156110a557600080fd5b505afa1580156110b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190612751565b6110f95760405162461bcd60e51b81526004016104f890612a04565b6006546111065760146006555b8051514361010090910111801561112857504381602001516000015161010001115b6111445760405162461bcd60e51b81526004016104f890612a3b565b8060200151602001518160000151602001511480156111725750806020015160600151816000015160600151145b1561118f5760405162461bcd60e51b81526004016104f890612c64565b8051604081015190511080156111ae5750602081015160408101519051105b6111ca5760405162461bcd60e51b81526004016104f890612b6d565b6020810151518151511080156111ef5750806000015160400151816020015160400151105b8061121a575080515160208201515110801561121a5750806020015160400151816000015160400151105b806112345750806020015160400151816000015160400151145b6112505760405162461bcd60e51b81526004016104f890612aa2565b6060806110006001600160a01b0316633b071dcc6040518163ffffffff1660e01b815260040160006040518083038186803b15801561128e57600080fd5b505afa1580156112a2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112ca919081019061268e565b60408501519193509150600090815b8351811015611327576112ff8482815181106112f157fe5b602002602001015183611b6e565b1561131f5784818151811061131057fe5b60200260200101519250611327565b6001016112d9565b506001600160a01b03821661134e5760405162461bcd60e51b81526004016104f890612ba4565b61136085600001518660400151611bd2565b8015611379575061137985602001518660400151611bd2565b6113955760405162461bcd60e51b81526004016104f890612b0e565b6006546040516309a99b4f60e41b815260646110028031909302049190639a99b4f0906113c8903390859060040161299b565b602060405180830381600087803b1580156113e257600080fd5b505af11580156113f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141a91906128a5565b506040516335409f7f60e01b8152611000906335409f7f90611440908690600401612987565b600060405180830381600087803b15801561145a57600080fd5b505af115801561146e573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b61148e866119bd565b60006040518463ffffffff1660e01b81526004016114ae93929190613075565b600060405180830381600087803b1580156114c857600080fd5b505af11580156114dc573d6000803e3d6000fd5b50506040516001600160a01b03861692507fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9150600090a2505050505050565b601481565b61100381565b60005460ff161561154a5760405162461bcd60e51b81526004016104f890612dca565b603260045560966005556000805460ff19166001179055565b61100081565b600381565b336110001461158f5760405162461bcd60e51b81526004016104f890612c91565b60005460ff166115b15760405162461bcd60e51b81526004016104f890612a6b565b6001546115bd576119b5565b600154600090600019015b808211611989576000805b828410156116ec576115e3612452565b60026000600187815481106115f457fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156116d65760046005548161166157fe5b0481602001510381602001818152505080600260006001888154811061168357fe5b6000918252602080832091909101546001600160a01b0316835282810193909352604091820190208351815591830151600183015591909101516002909101805460ff19169115159190911790556116e0565b60019250506116ec565b508360010193506115d3565b828411611883576116fb612452565b600260006001868154811061170c57fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156117f45760046005548161177957fe5b0481602001510381602001818152505080600260006001878154811061179b57fe5b6000918252602080832091909101546001600160a01b03168352828101939093526040918201902083518155918301516001808401919091559201516002909101805460ff191691151591909117905591506118839050565b600260006001868154811061180557fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff1916905580548061184957fe5b600082815260209020810160001990810180546001600160a01b0319169055019055836118765750611883565b50600019909201916116ec565b81801561188d5750805b1561196c5760026000600186815481106118a357fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff191690558054849081106118ea57fe5b600091825260209091200154600180546001600160a01b03909216918690811061191057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600180548061194957fe5b600082815260209020810160001990810180546001600160a01b03191690550190555b82611978575050611989565b5050600190910190600019016115c8565b6040517fcfdb3b6ccaeccbdc68be3c59c840e3b3c90f0a7c491f5fff1cf56cfda200dd9c90600090a150505b565b61100481565b60408051600480825260a08201909252606091829190816020015b60608152602001906001900390816119d8579050509050611a01836001600160a01b0316611daa565b81600081518110611a0e57fe5b6020026020010181905250611a2243611dcd565b81600181518110611a2f57fe5b6020908102919091010152611a446038611dcd565b81600281518110611a5157fe5b6020026020010181905250611a6542611dcd565b81600381518110611a7257fe5b6020026020010181905250611a8681611de0565b9150505b919050565b611a97612475565b6000611aa1612475565b611aa9612487565b611aba611ab586611e6a565b611e8f565b90506000805b611ac983611ed9565b15611b025780611af557611ae4611adf84611efa565b611f48565b63ffffffff16845260019150611afa565b611b02565b600101611ac0565b5091935090915050915091565b600081604051602001611b22919061296b565b6040516020818303038152906040528051906020012083604051602001611b49919061296b565b604051602081830303815290604052805190602001201490505b92915050565b015190565b815181516000916001918114808314611b8a5760009250611bc8565b600160208701838101602088015b600284838510011415611bc3578051835114611bb75760009650600093505b60209283019201611b98565b505050505b5090949350505050565b60408051600480825260a0820190925260009160609190816020015b6060815260200190600190039081611bee575050604080516020808252818301909252919250606091908082018180368337019050509050611c338560000151611dcd565b82600081518110611c4057fe5b6020026020010181905250611c5b6020866020015183611fca565b611c6481611fda565b82600181518110611c7157fe5b6020026020010181905250611c898560400151611dcd565b82600281518110611c9657fe5b6020026020010181905250611cb16020866060015183611fca565b611cba81611fda565b82600381518110611cc757fe5b6020026020010181905250611ced6020611ce084611de0565b8051906020012083611fca565b6040805160b080825260e08201909252606091602082018180368337019050509050611d1d818360006020612030565b611d2f81876080015160206060612030565b611d3d818660806030612030565b604080516001808252818301909252606091602082018180368337019050509050815160016020830182602086016066600019fa611d7a57600080fd5b506001611d88826000612083565b60ff1614611d9d576000945050505050611b63565b5060019695505050505050565b60408051600560a21b8318601482015260348101909152606090611a8681611fda565b6060611b63611ddb8361209f565b611fda565b6060815160001415611e015750604080516000815260208101909152611a8a565b606082600081518110611e1057fe5b602002602001015190506000600190505b8351811015611e5157611e4782858381518110611e3a57fe5b6020026020010151612185565b9150600101611e21565b50611a86611e64825160c060ff16612202565b82612185565b611e726124a7565b506040805180820190915281518152602082810190820152919050565b611e97612487565b611ea0826122d4565b611ea957600080fd5b6000611eb8836020015161230e565b60208085015160408051808201909152868152920190820152915050919050565b6000611ee36124a7565b505080518051602091820151919092015191011190565b611f026124a7565b611f0b82611ed9565b611f1457600080fd5b60208201516000611f2482612371565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590611f5d57508151602110155b611f6657600080fd5b6000611f75836020015161230e565b90508083600001511015611f9b5760405162461bcd60e51b81526004016104f890612e01565b825160208085015183018051928490039291831015611fc157826020036101000a820491505b50949350505050565b9091018181526020918201910152565b60608151600114801561200c5750607f60f81b82600081518110611ffa57fe5b01602001516001600160f81b03191611155b15612018575080611a8a565b611b6361202a8351608060ff16612202565b83612185565b60005b818110156106ad5783818151811061204757fe5b602001015160f81c60f81b85848060010195508151811061206457fe5b60200101906001600160f81b031916908160001a905350600101612033565b6000816001018351101561209657600080fd5b50016001015190565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166120e357506018612107565b6fffffffffffffffffffffffffffffffff19841661210357506010612107565b5060005b602081101561213d5781818151811061211c57fe5b01602001516001600160f81b031916156121355761213d565b600101612107565b60008160200390506060816040519080825280601f01601f191660200182016040528015612172576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b818310156121b657805183526020928301920161219e565b50855184518101855292509050808201602086015b818310156121e35780518352602092830192016121cb565b508651929092011591909101601f01601f191660405250905092915050565b606068010000000000000000831061222c5760405162461bcd60e51b81526004016104f890612b45565b604080516001808252818301909252606091602082018180368337019050509050603784116122865782840160f81b8160008151811061226857fe5b60200101906001600160f81b031916908160001a9053509050611b63565b60606122918561209f565b90508381510160370160f81b826000815181106122aa57fe5b60200101906001600160f81b031916908160001a9053506122cb8282612185565b95945050505050565b80516000906122e557506000611a8a565b6020820151805160001a9060c082101561230457600092505050611a8a565b5060019392505050565b8051600090811a6080811015612328576000915050611a8a565b60b8811080612343575060c08110801590612343575060f881105b15612352576001915050611a8a565b60c08110156123665760b519019050611a8a565b60f519019050611a8a565b80516000908190811a608081101561238c576001915061244b565b60b88110156123a157607e198101915061244b565b60c08110156123f257600060b78203600186019550806020036101000a8651049150600181018201935050808310156123ec5760405162461bcd60e51b81526004016104f890612ce1565b5061244b565b60f88110156124075760be198101915061244b565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156124495760405162461bcd60e51b81526004016104f890612ce1565b505b5092915050565b604051806060016040528060008152602001600081526020016000151581525090565b60408051602081019091526000815290565b604051806040016040528061249a6124a7565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b600082601f8301126124d1578081fd5b81516124e46124df826130c8565b6130a1565b818152915060208083019084810160005b8481101561255a578151870188603f82011261251057600080fd5b838101516125206124df826130e8565b81815260408b8184860101111561253657600080fd5b6125458388840183870161310c565b508652505092820192908201906001016124f5565b505050505092915050565b60008083601f840112612576578182fd5b50813567ffffffffffffffff81111561258d578182fd5b6020830191508360208285010111156125a557600080fd5b9250929050565b600082601f8301126125bc578081fd5b81356125ca6124df826130e8565b91508082528360208285010111156125e157600080fd5b8060208401602084013760009082016020015292915050565b600060a0828403121561260b578081fd5b61261560a06130a1565b905081358152602082013560208201526040820135604082015260608201356060820152608082013567ffffffffffffffff81111561265357600080fd5b61265f848285016125ac565b60808301525092915050565b60006020828403121561267c578081fd5b81356126878161313c565b9392505050565b600080604083850312156126a0578081fd5b825167ffffffffffffffff808211156126b7578283fd5b81850186601f8201126126c8578384fd5b805192506126d86124df846130c8565b80848252602080830192508084018a8283890287010111156126f8578788fd5b8794505b8685101561272357805161270f8161313c565b8452600194909401939281019281016126fc565b50880151909650935050508082111561273a578283fd5b50612747858286016124c1565b9150509250929050565b600060208284031215612762578081fd5b81518015158114612687578182fd5b60008060008060408587031215612786578182fd5b843567ffffffffffffffff8082111561279d578384fd5b6127a988838901612565565b909650945060208701359150808211156127c1578384fd5b506127ce87828801612565565b95989497509550505050565b6000602082840312156127eb578081fd5b813567ffffffffffffffff80821115612802578283fd5b81840160608187031215612814578384fd5b61281e60606130a1565b925080358281111561282e578485fd5b61283a878284016125fa565b84525060208101358281111561284e578485fd5b61285a878284016125fa565b602085015250604081013582811115612871578485fd5b61287d878284016125ac565b6040850152509195945050505050565b60006020828403121561289e578081fd5b5035919050565b6000602082840312156128b6578081fd5b5051919050565b6000806000604084860312156128d1578283fd5b833560ff811681146128e1578384fd5b9250602084013567ffffffffffffffff8111156128fc578283fd5b61290886828701612565565b9497909650939450505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b6000815180845261295781602086016020860161310c565b601f01601f19169290920160200192915050565b6000825161297d81846020870161310c565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b600060208252612687602083018461293f565b6000604082526129e6604083018688612915565b82810360208401526129f9818587612915565b979650505050505050565b6020808252601f908201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604082015260600190565b6020808252601690820152751d1bdbc81bdb1908189b1bd8dac81a5b9d9bdb1d995960521b604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601a908201527f6e6f2076696f6c6174696f6e206f6620766f74652072756c6573000000000000604082015260600190565b6020808252818101527f7468652066656c6f6e795468726573686f6c64206f7574206f662072616e6765604082015260600190565b60208082526017908201527f766572696679207369676e6174757265206661696c6564000000000000000000604082015260600190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526019908201527f7372634e756d20626967676572207468616e207461724e756d00000000000000604082015260600190565b6020808252601390820152721d985b1a59185d1bdc881b9bdd08195e1a5cdd606a1b604082015260600190565b6020808252602c908201527f7468652066696e616c69747920736c6173682072657761726420726174696f2060408201526b6f7574206f662072616e676560a01b606082015260800190565b60208082526027908201527f6c656e677468206f66206d697364656d65616e6f725468726573686f6c64206d6040820152660d2e6dac2e8c6d60cb1b606082015260800190565b60208082526013908201527274776f206964656e746963616c20766f74657360681b604082015260600190565b60208082526030908201527f746865206d6573736167652073656e646572206d7573742062652076616c696460408201526f185d1bdc94d95d0818dbdb9d1c9858dd60821b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526022908201527f6c656e677468206f662066656c6f6e795468726573686f6c64206d69736d61746040820152610c6d60f31b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526025908201527f746865206d697364656d65616e6f725468726573686f6c64206f7574206f662060408201526472616e676560d81b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b6020808252601e908201527f7265636569766520756e65787065637465642073796e207061636b6167650000604082015260600190565b6020808252602b908201527f6c656e677468206f662066696e616c697479536c61736852657761726452617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b6020808252818101527f63616e206e6f7420736c61736820747769636520696e206f6e6520626c6f636b604082015260600190565b61ffff91909116815260200190565b90815260200190565b600083825260406020830152613028604083018461293f565b949350505050565b918252602082015260400190565b92835260208301919091521515604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260606020830152613091606083018561293f565b9050826040830152949350505050565b60405181810167ffffffffffffffff811182821017156130c057600080fd5b604052919050565b600067ffffffffffffffff8211156130de578081fd5b5060209081020190565b600067ffffffffffffffff8211156130fe578081fd5b50601f01601f191660200190565b60005b8381101561312757818101518382015260200161310f565b83811115613136576000848401525b50505050565b6001600160a01b038116811461315157600080fd5b5056fea264697066735822122086a5b0c3194fbead4808634d6137151c6cb6180aacf059312af931e2f7b5c7ff64736f6c63430006040033",
+ },
+ {
+ ContractAddr: common.HexToAddress(SystemRewardContract),
+ CommitUrl: "https://github.com/node-real/bsc-genesis-contract/commit/f8bab13f56955e979bfb754425dab1e62e52f151",
+ Code: "6080604052600436106101a05760003560e01c80637942fd05116100ec578063ac4317511161008a578063f9a2bbc711610064578063f9a2bbc714610550578063fb5478b314610565578063fc3e59081461057a578063fd6a68791461058f576101e4565b8063ac43175114610457578063c81b166214610526578063dc927faf1461053b576101e4565b80639dc09262116100c65780639dc0926214610403578063a1a11bf514610418578063a78abc161461042d578063ab51bb9614610442576101e4565b80637942fd05146103a057806396713da9146103b55780639a99b4f0146103ca576101e4565b80634bf6c882116101595780636e47b482116101335780636e47b4821461034c57806370fd5bad14610361578063718a8aa81461037657806375d47a0a1461038b576101e4565b80634bf6c882146102db57806351e80672146102f05780636d70f7ae14610305576101e4565b80630bee7a67146101e95780630e2374a5146102175780633a0b0eff146102485780633dffc3871461026f57806343756e5c1461029a578063493279b1146102af576101e4565b366101e45734156101e25760408051348152905133917f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db919081900360200190a25b005b600080fd5b3480156101f557600080fd5b506101fe6105a4565b6040805163ffffffff9092168252519081900360200190f35b34801561022357600080fd5b5061022c6105a9565b604080516001600160a01b039092168252519081900360200190f35b34801561025457600080fd5b5061025d6105af565b60408051918252519081900360200190f35b34801561027b57600080fd5b506102846105b5565b6040805160ff9092168252519081900360200190f35b3480156102a657600080fd5b5061022c6105ba565b3480156102bb57600080fd5b506102c46105c0565b6040805161ffff9092168252519081900360200190f35b3480156102e757600080fd5b506102846105c5565b3480156102fc57600080fd5b5061022c6105ca565b34801561031157600080fd5b506103386004803603602081101561032857600080fd5b50356001600160a01b03166105d0565b604080519115158252519081900360200190f35b34801561035857600080fd5b5061022c6105ee565b34801561036d57600080fd5b506102846105f4565b34801561038257600080fd5b506102846105f9565b34801561039757600080fd5b5061022c6105fe565b3480156103ac57600080fd5b50610284610604565b3480156103c157600080fd5b50610284610609565b3480156103d657600080fd5b5061025d600480360360408110156103ed57600080fd5b506001600160a01b03813516906020013561060e565b34801561040f57600080fd5b5061022c6107b9565b34801561042457600080fd5b5061022c6107bf565b34801561043957600080fd5b506103386107c5565b34801561044e57600080fd5b506101fe6107ce565b34801561046357600080fd5b506101e26004803603604081101561047a57600080fd5b81019060208101813564010000000081111561049557600080fd5b8201836020820111156104a757600080fd5b803590602001918460018302840111640100000000831117156104c957600080fd5b9193909290916020810190356401000000008111156104e757600080fd5b8201836020820111156104f957600080fd5b8035906020019184600183028401116401000000008311171561051b57600080fd5b5090925090506107d3565b34801561053257600080fd5b5061022c610b56565b34801561054757600080fd5b5061022c610b5c565b34801561055c57600080fd5b5061022c610b62565b34801561057157600080fd5b5061025d610b68565b34801561058657600080fd5b50610284610b74565b34801561059b57600080fd5b5061022c610b79565b606481565b61200181565b60015481565b600181565b61100181565b603881565b600881565b61200081565b6001600160a01b031660009081526002602052604090205460ff1690565b61100581565b600281565b601081565b61100881565b600b81565b600981565b6000805460ff1661068b57600260208190527fe57bda0a954a7c7381b17b2c763e646ba2c60f67292d287ba583603e2c1c41668054600160ff19918216811790925561100560009081527fe25235fc0de9d7165652bef0846fefda506174abb9a190f03d0f7bcc6146dbce80548316841790559282558254161790555b3360009081526002602052604090205460ff166106d95760405162461bcd60e51b815260040180806020018281038252602b815260200180610c67602b913960400191505060405180910390fd5b60004783106106e857476106ea565b825b9050670de0b6b3a76400008111156107075750670de0b6b3a76400005b8015610788576040516001600160a01b0385169082156108fc029083906000818181858888f19350505050158015610743573d6000803e3d6000fd5b506040805182815290516001600160a01b038616917ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0919081900360200190a26107b2565b6040517fe589651933c2457488cc0d8e0941518abf748e799435e4e396d9c4d0b2db2d4d90600090a15b9392505050565b61100781565b61100681565b60005460ff1681565b600081565b33611007146108135760405162461bcd60e51b815260040180806020018281038252602e815260200180610cc1602e913960400191505060405180910390fd5b61087584848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600b81526a30b23227b832b930ba37b960a91b60208201529150610b7f9050565b1561094d57606082828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050825192935050601490911490506108f85760405162461bcd60e51b815260040180806020018281038252602c815260200180610cef602c913960400191505060405180910390fd5b60148101516001600160a01b038116600081815260026020526040808220805460ff19166001179055517f9870d7fe5d112134c55844951dedf365363006d9c588db07c4c85af6322a06199190a25050610ac4565b6109b284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600e81526d3232b632ba32a7b832b930ba37b960911b60208201529150610b7f9050565b15610a8757606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060149091149050610a355760405162461bcd60e51b815260040180806020018281038252602f815260200180610c92602f913960400191505060405180910390fd5b60148101516001600160a01b038116600081815260026020526040808220805460ff19169055517fb40992a19dba61ea600e87fce607102bf5908dc89076217b6ca6ae195224f7029190a25050610ac4565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b61100281565b61100381565b61100081565b670de0b6b3a764000081565b600381565b61100481565b6000816040516020018082805190602001908083835b60208310610bb45780518252601f199092019160209182019101610b95565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310610c225780518252601f199092019160209182019101610c03565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201490509291505056fe6f6e6c79206f70657261746f7220697320616c6c6f77656420746f2063616c6c20746865206d6574686f646c656e677468206f662076616c756520666f722064656c6574654f70657261746f722073686f756c64206265203230746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662076616c756520666f72206164644f70657261746f722073686f756c64206265203230a264697066735822122078be72e2672a87e28d3e6849bea141a139b304a089fceb003c016dabd5f556fb64736f6c63430006040033",
+ },
+ },
+ }
+
+ bonehUpgrade[chapelNet] = &Upgrade{
+ UpgradeName: "boneh",
+ Configs: []*UpgradeConfig{
+ {
+ ContractAddr: common.HexToAddress(ValidatorContract),
+ CommitUrl: "https://github.com/node-real/bsc-genesis-contract/commit/f8bab13f56955e979bfb754425dab1e62e52f151",
+ Code: "60806040526004361061046c5760003560e01c8063862498821161024a578063c6d3394511610139578063e40716a1116100b6578063f9a2bbc71161007a578063f9a2bbc714610b6b578063fc3e590814610b80578063fccc281314610b95578063fd4ad81f14610baa578063fd6a687914610bd957610473565b8063e40716a114610af9578063eb57e20214610b0e578063eda5868c14610b2e578063f340fa0114610b43578063f92eb86b14610b5657610473565b8063d86222d5116100fd578063d86222d514610a90578063daacdb6614610aa5578063dc927faf14610aba578063e086c7b114610acf578063e1c7392a14610ae457610473565b8063c6d3394514610a3c578063c81b166214610a51578063c8509d811461085f578063d04aa99614610a66578063d68fb56a14610a7b57610473565b8063a5422d5c116101c7578063ad3c9da61161018b578063ad3c9da6146109d0578063aef198a9146109f0578063b7ab4db514610a05578063b8cf4ef114610a27578063bf9f49951461062f57610473565b8063a5422d5c1461095c578063a78abc1614610971578063aaf5eb6814610986578063ab51bb961461099b578063ac431751146109b057610473565b806396713da91161020e57806396713da9146108f35780639dc09262146109085780639fe0f8161461091d578063a0dc275814610932578063a1a11bf51461094757610473565b8063862498821461087f57806388b32f11146108945780638b5ad0c9146108a95780638d19a410146108be5780639369d7de146108de57610473565b80634df6e0c3116103665780636e47b482116102e35780637942fd05116102a75780637942fd05146108205780637a84ca2a1461083557806381650b621461084a578063831d65d11461085f578063853230aa1461080b57610473565b80636e47b482146107b757806370fd5bad146107cc578063718a8aa8146107e157806375d47a0a146107f657806378dfed4a1461080b57610473565b8063565c56b31161032a578063565c56b3146107265780635667515a146107465780635d77156c1461075b57806362b72cf5146107705780636969a25c1461078557610473565b80634df6e0c3146106b25780635192c82c146106c757806351e80672146106dc578063549b03f2146106f157806355614fcc1461070657610473565b8063321d398a116103f45780633dffc387116103b85780633dffc3871461062f57806343756e5c1461065157806345cf9daf14610666578063493279b11461067b5780634bf6c8821461069d57610473565b8063321d398a146105975780633365af3a146105b757806335409f7f146105d75780633b071dcc146105f75780633de0f0d81461061a57610473565b80631182b8751161043b5780631182b875146104fe578063152ad3b81461052b5780631ff180691461054d578063219f22d514610562578063300c35671461057757610473565b806304c4fec61461047857806307a568471461048f5780630bee7a67146104ba5780630e2374a5146104dc57610473565b3661047357005b600080fd5b34801561048457600080fd5b5061048d610bee565b005b34801561049b57600080fd5b506104a4610c60565b6040516104b19190616d9d565b60405180910390f35b3480156104c657600080fd5b506104cf610c66565b6040516104b19190616dc7565b3480156104e857600080fd5b506104f1610c6b565b6040516104b191906161a4565b34801561050a57600080fd5b5061051e61051936600461608a565b610c71565b6040516104b1919061631b565b34801561053757600080fd5b50610540610ea9565b6040516104b19190616310565b34801561055957600080fd5b506104a4610eb2565b34801561056e57600080fd5b506104cf610eb8565b34801561058357600080fd5b5061048d610592366004615f53565b610ebd565b3480156105a357600080fd5b506105406105b2366004616037565b611263565b3480156105c357600080fd5b506105406105d2366004616037565b611332565b3480156105e357600080fd5b5061048d6105f2366004615f2c565b6113e3565b34801561060357600080fd5b5061060c61153c565b6040516104b1929190616226565b34801561062657600080fd5b506104a4611818565b34801561063b57600080fd5b5061064461181e565b6040516104b19190616dd8565b34801561065d57600080fd5b506104f1611823565b34801561067257600080fd5b506104a4611829565b34801561068757600080fd5b5061069061182f565b6040516104b19190616d8e565b3480156106a957600080fd5b50610644611834565b3480156106be57600080fd5b5061060c611839565b3480156106d357600080fd5b506104a46119b7565b3480156106e857600080fd5b506104f16119bd565b3480156106fd57600080fd5b506104a46119c3565b34801561071257600080fd5b50610540610721366004615f2c565b6119c9565b34801561073257600080fd5b506104a4610741366004615f2c565b6119fe565b34801561075257600080fd5b50610644611a4f565b34801561076757600080fd5b506104cf611a54565b34801561077c57600080fd5b506104a4611a59565b34801561079157600080fd5b506107a56107a0366004616037565b611a5f565b6040516104b1969594939291906161d1565b3480156107c357600080fd5b506104f1611ac3565b3480156107d857600080fd5b50610644611ac9565b3480156107ed57600080fd5b50610644611ace565b34801561080257600080fd5b506104f1611ad3565b34801561081757600080fd5b506104a4611ad9565b34801561082c57600080fd5b50610644611adf565b34801561084157600080fd5b506104a4611ae4565b34801561085657600080fd5b506104cf611aea565b34801561086b57600080fd5b5061048d61087a36600461608a565b611aef565b34801561088b57600080fd5b506104a4611b50565b3480156108a057600080fd5b506104a4611b56565b3480156108b557600080fd5b506104a4611b5c565b3480156108ca57600080fd5b506104a46108d9366004615f2c565b611b62565b3480156108ea57600080fd5b5061048d611ba2565b3480156108ff57600080fd5b50610644611cb6565b34801561091457600080fd5b506104f1611cbb565b34801561092957600080fd5b506104a4611cc1565b34801561093e57600080fd5b506104a4611cc6565b34801561095357600080fd5b506104f1611ccb565b34801561096857600080fd5b5061051e611cd1565b34801561097d57600080fd5b50610540611cf0565b34801561099257600080fd5b506104a4611cf9565b3480156109a757600080fd5b506104cf611a4f565b3480156109bc57600080fd5b5061048d6109cb366004615fdb565b611d02565b3480156109dc57600080fd5b506104a46109eb366004615f2c565b6125ae565b3480156109fc57600080fd5b506104a46125c0565b348015610a1157600080fd5b50610a1a6125cd565b6040516104b19190616213565b348015610a3357600080fd5b506104a46126b9565b348015610a4857600080fd5b506104a4611ac9565b348015610a5d57600080fd5b506104f16126be565b348015610a7257600080fd5b506104a46126c4565b348015610a8757600080fd5b506104a46126c9565b348015610a9c57600080fd5b506104a4612708565b348015610ab157600080fd5b506104a4612714565b348015610ac657600080fd5b506104f161271a565b348015610adb57600080fd5b506104a4612720565b348015610af057600080fd5b5061048d612725565b348015610b0557600080fd5b506104a46128d4565b348015610b1a57600080fd5b5061048d610b29366004615f2c565b6128da565b348015610b3a57600080fd5b506104cf6129e2565b61048d610b51366004615f2c565b6129e7565b348015610b6257600080fd5b506104a4612c6f565b348015610b7757600080fd5b506104f1612c75565b348015610b8c57600080fd5b50610644611cc1565b348015610ba157600080fd5b506104f1612c7b565b348015610bb657600080fd5b50610bca610bc5366004616037565b612c81565b6040516104b193929190616da6565b348015610be557600080fd5b506104f1612d43565b6000610bf933611b62565b9050600b8181548110610c0857fe5b600091825260209091206001601690920201015460ff16610c445760405162461bcd60e51b8152600401610c3b90616a46565b60405180910390fd5b6000610c4e6126c9565b9050610c5b338383612d49565b505050565b60095481565b606481565b61200181565b60005460609060ff16610c965760405162461bcd60e51b8152600401610c3b906164da565b3361200014610cb75760405162461bcd60e51b8152600401610c3b90616c25565b600b54610d7557610cc6615c18565b60015460005b81811015610d7157600b80546001810182556000919091528351600080516020616ffb833981519152601690920291820190815560208086015160008051602061703b8339815191528401805460ff1916911515919091179055604086015180518794610d4d9360008051602061701b833981519152909101920190615c47565b506060820151610d639060038301906013615cc1565b505050806001019050610ccc565b5050505b610d7d615cee565b6000610dbe85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f3592505050565b9150915080610dda57610dd160646130f1565b92505050610ea2565b815160009060ff16610dff57610df883602001518460400151613152565b9050610e6e565b825160ff1660011415610e6a57826020015151600114610e4457600080516020616fdb833981519152604051610e349061692d565b60405180910390a1506067610e65565b610df88360200151600081518110610e5857fe5b6020026020010151613da6565b610e6e565b5060655b63ffffffff8116610e935750506040805160008152602081019091529150610ea29050565b610e9c816130f1565b93505050505b9392505050565b60075460ff1681565b60035481565b606881565b334114610edc5760405162461bcd60e51b8152600401610c3b90616c74565b6010544311610efd5760405162461bcd60e51b8152600401610c3b90616636565b60005460ff16610f1f5760405162461bcd60e51b8152600401610c3b906164da565b600f54610f37576032600f5561100231601155611259565b60006110023181610f578268056bc75e2d6310000063ffffffff613f1d16565b1115610f7557610f6e81606463ffffffff613f5f16565b9150610fd1565b6000610f8c60115483613f1d90919063ffffffff16565b1115610fca57610f6e6064610fbe600f54610fb260115486613f1d90919063ffffffff16565b9063ffffffff613fa116565b9063ffffffff613f5f16565b5050611259565b6040516309a99b4f60e41b815261100290639a99b4f090610ff890309086906004016161b8565b602060405180830381600087803b15801561101257600080fd5b505af1158015611026573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061104a919061604f565b6110023160115591508161105f575050611259565b6000805b8481101561108d5785858281811061107757fe5b9050602002013582019150806001019050611063565b508061109b57505050611259565b6000806000805b8981101561125157848989838181106110b757fe5b905060200201358802816110c757fe5b0493508a8a828181106110d657fe5b90506020020160208101906110eb9190615f2c565b6001600160a01b0381166000908152600460205260409020549093509150811561120757600060018084038154811061112057fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561118d57836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85866040516111809190616d9d565b60405180910390a2611201565b6003546111a0908663ffffffff613fdb16565b60039081558101546111b8908663ffffffff613fdb16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b2906111f8908890616d9d565b60405180910390a25b50611249565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d85856040516112409190616d9d565b60405180910390a25b6001016110a2565b505050505050505b5050436010555050565b60015460009082106112775750600061132d565b60006001600160a01b03166001838154811061128f57fe5b60009182526020909120600490910201546001600160a01b031614806112bf575060085415806112bf5750600a54155b806112ce575060085460095410155b806112df57506112dd82611332565b155b8061130857506000600b83815481106112f457fe5b906000526020600020906016020160000154115b8061131c575060016113186125cd565b5111155b156113295750600061132d565b5060015b919050565b60015460009082106113465750600061132d565b600b548210611383576001828154811061135c57fe5b9060005260206000209060040201600201601c9054906101000a900460ff1615905061132d565b6001828154811061139057fe5b9060005260206000209060040201600201601c9054906101000a900460ff161580156113dd5750600b82815481106113c457fe5b600091825260209091206001601690920201015460ff16155b92915050565b33611001146114045760405162461bcd60e51b8152600401610c3b90616d45565b600b546114c257611413615c18565b60015460005b818110156114be57600b80546001810182556000919091528351600080516020616ffb833981519152601690920291820190815560208086015160008051602061703b8339815191528401805460ff191691151591909117905560408601518051879461149a9360008051602061701b833981519152909101920190615c47565b5060608201516114b09060038301906013615cc1565b505050806001019050611419565b5050505b6001600160a01b038116600090815260046020526040902054806114e65750611539565b6001810390506000600b82815481106114fb57fe5b600091825260209091206001601690920201015460ff16905061151e8383614000565b80156115275750805b15610c5b576009805460001901905550505b50565b60015460609081906000805b8281101561158f576001818154811061155d57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611587576001909101905b600101611548565b506060816040519080825280602002602001820160405280156115bc578160200160208202803683370190505b5090506060826040519080825280602002602001820160405280156115f557816020015b60608152602001906001900390816115e05790505b50600b54600094509091508414156117705760005b8481101561176a576001818154811061161f57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611762576001818154811061164f57fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061167a57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b81815481106116a757fe5b600091825260209182902060026016909202018101805460408051601f60001961010060018616150201909316949094049182018590048502840185019052808352919290919083018282801561173f5780601f106117145761010080835404028352916020019161173f565b820191906000526020600020905b81548152906001019060200180831161172257829003601f168201915b505050505082858151811061175057fe5b60209081029190910101526001909301925b60010161160a565b5061180c565b60005b8481101561180a576001818154811061178857fe5b9060005260206000209060040201600201601c9054906101000a900460ff1661180257600181815481106117b857fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106117e357fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101611773565b505b909450925050505b9091565b61271081565b600181565b61100181565b60085481565b606181565b600881565b600e54600c5460609182918061184d575060155b60606118576125cd565b90506060611864826143b3565b90508282511161187b579094509250611814915050565b8383835103101561188d578282510393505b83156118c35760c843046118a983838388880360008a8a614521565b6118c18383838888038989038a8b8b8b510301614521565b505b6060836040519080825280602002602001820160405280156118ef578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561192857816020015b60608152602001906001900390816119135790505b50905060005b858110156119a95784818151811061194257fe5b602002602001015183828151811061195657fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083818151811061198257fe5b602002602001015182828151811061199657fe5b602090810291909101015260010161192e565b509096509450505050509091565b60065481565b61200081565b600f5481565b6001600160a01b038116600090815260046020526040812054806119f157600091505061132d565b60001901610ea281611332565b6001600160a01b03811660009081526004602052604081205480611a2657600091505061132d565b600180820381548110611a3557fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b60105481565b60018181548110611a6c57fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b606681565b3361200014611b105760405162461bcd60e51b8152600401610c3b90616c25565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051611b4393929190616de6565b60405180910390a1505050565b60025481565b60115481565b600a5481565b6001600160a01b03811660009081526004602052604081205480611b985760405162461bcd60e51b8152600401610c3b90616bad565b6000190192915050565b600b54611c6057611bb1615c18565b60015460005b81811015611c5c57600b80546001810182556000919091528351600080516020616ffb833981519152601690920291820190815560208086015160008051602061703b8339815191528401805460ff1916911515919091179055604086015180518794611c389360008051602061701b833981519152909101920190615c47565b506060820151611c4e9060038301906013615cc1565b505050806001019050611bb7565b5050505b600854611c6d5760036008555b600a54611c7a576002600a555b6000611c8533611b62565b9050611c9081611263565b611cac5760405162461bcd60e51b8152600401610c3b906168ea565b6115393382614678565b600981565b61100781565b600381565b60c881565b61100681565b604051806101e001604052806101ab8152602001616e306101ab913981565b60005460ff1681565b6402540be40081565b60005460ff16611d245760405162461bcd60e51b8152600401610c3b906164da565b3361100714611d455760405162461bcd60e51b8152600401610c3b906169b3565b611daf84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506147109050565b15611e4c5760208114611dd45760405162461bcd60e51b8152600401610c3b90616b67565b604080516020601f8401819004810282018101909252828152600091611e129185858083850183828082843760009201919091525061476992505050565b905060648110158015611e285750620186a08111155b611e445760405162461bcd60e51b8152600401610c3b90616793565b60025561256b565b611eac84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506147109050565b15611f485760208114611ed15760405162461bcd60e51b8152600401610c3b90616360565b604080516020601f8401819004810282018101909252828152600091611f0f9185858083850183828082843760009201919091525061476992505050565b9050612710811115611f335760405162461bcd60e51b8152600401610c3b90616678565b6006556007805460ff1916600117905561256b565b611fb284848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506147109050565b1561204c5760208114611fd75760405162461bcd60e51b8152600401610c3b90616397565b604080516020601f84018190048102820181019092528281526000916120159185858083850183828082843760009201919091525061476992505050565b600c5490915080612024575060155b8082106120435760405162461bcd60e51b8152600401610c3b906166eb565b5060085561256b565b6120b584848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506147109050565b1561214e57602081146120da5760405162461bcd60e51b8152600401610c3b90616460565b604080516020601f84018190048102820181019092528281526000916121189185858083850183828082843760009201919091525061476992505050565b905060008111801561212a5750600a81105b6121465760405162461bcd60e51b8152600401610c3b90616cc1565b600a5561256b565b6121c284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506147109050565b1561225157602081146121e75760405162461bcd60e51b8152600401610c3b90616414565b604080516020601f84018190048102820181019092528281526000916122259185858083850183828082843760009201919091525061476992505050565b9050600d548111156122495760405162461bcd60e51b8152600401610c3b90616809565b600e5561256b565b6122ba84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506147109050565b1561233c57602081146122df5760405162461bcd60e51b8152600401610c3b90616a01565b604080516020601f840181900481028201810190925282815260009161231d9185858083850183828082843760009201919091525061476992505050565b600d819055600e5490915081101561233657600d54600e555b5061256b565b6123a084848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506147109050565b1561244e57602081146123c55760405162461bcd60e51b8152600401610c3b906164a5565b604080516020601f84018190048102820181019092528281526000916124039185858083850183828082843760009201919091525061476992505050565b9050600081116124255760405162461bcd60e51b8152600401610c3b90616548565b60298111156124465760405162461bcd60e51b8152600401610c3b90616590565b600c5561256b565b6124b884848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601381527266696e616c697479526577617264526174696f60681b602082015291506147109050565b1561255357602081146124dd5760405162461bcd60e51b8152600401610c3b90616aea565b604080516020601f840181900481028201810190925282815260009161251b9185858083850183828082843760009201919091525061476992505050565b90506001811015801561252f575060648111155b61254b5760405162461bcd60e51b8152600401610c3b90616878565b600f5561256b565b60405162461bcd60e51b8152600401610c3b90616d1e565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040516125a0949392919061632e565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156125fc576125e881611332565b156125f4578160010191505b6001016125d7565b50606081604051908082528060200260200182016040528015612629578160200160208202803683370190505b5090506000915060005b838110156126b05761264481611332565b156126a8576001818154811061265657fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061268157fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101612633565b50925050505b90565b601581565b61100281565b603281565b60006126d36125cd565b519050600080600c54116126e85760156126ec565b600c545b9050808211156126fa578091505b8161270457600191505b5090565b67016345785d8a000081565b60055481565b61100381565b602981565b60005460ff16156127485760405162461bcd60e51b8152600401610c3b90616ab3565b612750615cee565b6000612776604051806101e001604052806101ab8152602001616e306101ab9139612f35565b91509150806127975760405162461bcd60e51b8152600401610c3b90616be4565b60005b8260200151518110156128bc576001836020015182815181106127b957fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061288f57fe5b602090810291909101810151516001600160a01b031682528101919091526040016000205560010161279a565b50506103e8600255506000805460ff19166001179055565b600d5481565b33611001146128fb5760405162461bcd60e51b8152600401610c3b90616d45565b600b546129b95761290a615c18565b60015460005b818110156129b557600b80546001810182556000919091528351600080516020616ffb833981519152601690920291820190815560208086015160008051602061703b8339815191528401805460ff19169115159190911790556040860151805187946129919360008051602061701b833981519152909101920190615c47565b5060608201516129a79060038301906013615cc1565b505050806001019050612910565b5050505b60006129c48261476e565b90506129cf81611263565b156129de576129de8282614678565b5050565b606581565b334114612a065760405162461bcd60e51b8152600401610c3b90616c74565b60005460ff16612a285760405162461bcd60e51b8152600401610c3b906164da565b60003411612a485760405162461bcd60e51b8152600401610c3b906167da565b6001600160a01b0381166000908152600460205260409020546007543491906103e89060ff1615612a7857506006545b600083118015612a885750600081115b15612b29576000612aa5612710610fbe868563ffffffff613fa116565b90508015612b275760405161dead9082156108fc029083906000818181858888f19350505050158015612adc573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee581604051612b0c9190616d9d565b60405180910390a1612b24848263ffffffff613f1d16565b93505b505b8115612c27576000600180840381548110612b4057fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615612bad57846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b485604051612ba09190616d9d565b60405180910390a2612c21565b600354612bc0908563ffffffff613fdb16565b6003908155810154612bd8908563ffffffff613fdb16565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc05590612c18908790616d9d565b60405180910390a25b50612c69565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b484604051612c609190616d9d565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b8181548110612c8e57fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015612d395780601f10612d0e57610100808354040283529160200191612d39565b820191906000526020600020905b815481529060010190602001808311612d1c57829003601f168201915b5050505050905083565b61100481565b6000600a5460001480612d5a575081155b80612d655750600954155b15612d7257506000610ea2565b60096000815460019003919050819055506000612dbd600a54610fbe85610fbe600b8981548110612d9f57fe5b6000918252602090912060169091020154439063ffffffff613f1d16565b90506000600b8581548110612dce57fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015612e3357600080fd5b505afa158015612e47573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e6b9190616067565b9150915060009350808310612ee557612e848787614000565b506040516305bfb49960e41b815261100190635bfb499090612eaa908a906004016161a4565b600060405180830381600087803b158015612ec457600080fd5b505af1158015612ed8573d6000803e3d6000fd5b5050505060019350612ef7565b818310612ef757612ef58761476e565b505b6040516001600160a01b038816907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050509392505050565b612f3d615cee565b6000612f47615cee565b612f4f615d12565b612f60612f5b86614911565b614936565b90506000805b612f6f83614980565b156130e35780612f9457612f8a612f85846149a1565b6149ef565b60ff1684526130db565b80600114156130d6576060612fb0612fab856149a1565b614a6f565b90508051604051908082528060200260200182016040528015612fed57816020015b612fda615d32565b815260200190600190039081612fd25790505b508560200181905250805160405190808252806020026020018201604052801561302b57816020015b60608152602001906001900390816130165790505b50604086015260005b81518110156130cb57613045615d32565b6060600061306585858151811061305857fe5b6020026020010151614b40565b92509250925080613085578860009a509a505050505050505050506130ec565b828960200151858151811061309657fe5b602002602001018190525081896040015185815181106130b257fe5b6020026020010181905250505050806001019050613034565b5060019250506130db565b6130e3565b600101612f66565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b606081526020019060019003908161310b5790505090506131318363ffffffff16614c5a565b8160008151811061313e57fe5b6020026020010181905250610ea281614c6d565b600060298351111561318957600080516020616fdb833981519152604051613179906165ed565b60405180910390a15060666113dd565b60005b83518110156132275760005b8181101561321e578481815181106131ac57fe5b6020026020010151600001516001600160a01b03168583815181106131cd57fe5b6020026020010151600001516001600160a01b0316141561321657600080516020616fdb83398151915260405161320390616748565b60405180910390a16066925050506113dd565b600101613198565b5060010161318c565b506060806132358585614cf7565b60015491935091506000908190815b818110156132ba5767016345785d8a00006001828154811061326257fe5b90600052602060002090600402016003015410613284578360010193506132b2565b60006001828154811061329357fe5b90600052602060002090600402016003015411156132b2578260010192505b600101613244565b506060836040519080825280602002602001820160405280156132e7578160200160208202803683370190505b509050606084604051908082528060200260200182016040528015613316578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015613345578160200160208202803683370190505b509050606086604051908082528060200260200182016040528015613374578160200160208202803683370190505b50905060006060876040519080825280602002602001820160405280156133a5578160200160208202803683370190505b5090506060886040519080825280602002602001820160405280156133d4578160200160208202803683370190505b509050600099506000985060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b15801561341c57600080fd5b505afa158015613430573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190613454919061604f565b905067016345785d8a000081111561349f57600080516020616fdb83398151915260405161348190616a72565b60405180910390a160689d50505050505050505050505050506113dd565b60005b898110156137105767016345785d8a0000600182815481106134c057fe5b9060005260206000209060040201600301541061364557600181815481106134e457fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898d8151811061351557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be4006001838154811061354a57fe5b9060005260206000209060040201600301548161356357fe5b066001838154811061357157fe5b9060005260206000209060040201600301540390506135998382613f1d90919063ffffffff16565b898e815181106135a557fe5b602002602001018181525050600182815481106135be57fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316878e815181106135ef57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888e8151811061361c57fe5b6020908102919091010152613637868263ffffffff613fdb16565b95508c6001019c5050613708565b60006001828154811061365457fe5b9060005260206000209060040201600301541115613708576001818154811061367957fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848c815181106136aa57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600181815481106136d757fe5b906000526020600020906004020160030154838c815181106136f557fe5b6020026020010181815250508a6001019a505b6001016134a2565b5060008415613986576002546040516303702b2960e51b815261100491636e05652091889161374a918e918e918d91420190600401616296565b6020604051808303818588803b15801561376357600080fd5b505af193505050508015613794575060408051601f3d908101601f1916820190925261379191810190615fbb565b60015b61390b576040516000815260443d10156137b05750600061384b565b60046000803e60005160e01c6308c379a081146137d157600091505061384b565b60043d036004833e81513d60248201116001600160401b03821117156137fc5760009250505061384b565b80830180516001600160401b0381111561381d57600094505050505061384b565b8060208301013d860181111561383b5760009550505050505061384b565b601f01601f191660405250925050505b806138565750613898565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf2808260405161388a919061631b565b60405180910390a250613906565b3d8080156138c2576040519150601f19603f3d011682016040523d82523d6000602084013e6138c7565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a45826040516138fc919061631b565b60405180910390a2505b613986565b801561394d577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b70866040516139409190616d9d565b60405180910390a1613984565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28060405161397b906163dd565b60405180910390a25b505b8015613b3c5760005b8751811015613b3a5760008882815181106139a657fe5b602002602001015190506000600182815481106139bf57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc91859081106139f057fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015613aac5760018281548110613a3157fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110613a8057fe5b906000526020600020906004020160030154604051613a9f9190616d9d565b60405180910390a2613b30565b60018281548110613ab957fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110613b0857fe5b906000526020600020906004020160030154604051613b279190616d9d565b60405180910390a25b505060010161398f565b505b835115613c865760005b8451811015613c84576000858281518110613b5d57fe5b60200260200101516001600160a01b03166108fc868481518110613b7d57fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015613c1357858281518110613bb357fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110613bf157fe5b6020026020010151604051613c069190616d9d565b60405180910390a2613c7b565b858281518110613c1f57fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110613c5d57fe5b6020026020010151604051613c729190616d9d565b60405180910390a25b50600101613b46565b505b5050505050505050505050506000471115613d02577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d47604051613cca9190616d9d565b60405180910390a1604051611002904780156108fc02916000818181858888f19350505050158015613d00573d6000803e3d6000fd5b505b60006003819055600555815115613d1d57613d1d8282614f30565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613d5a57600080fd5b505af1158015613d6e573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b80516001600160a01b0316600090815260046020526040812054801580613df75750600180820381548110613dd757fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b15613e3d5782516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a2600091505061132d565b600154600554600019820111801590613e935784516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a26000935050505061132d565b600580546001908101909155805481906000198601908110613eb157fe5b6000918252602082206002600490920201018054921515600160e01b0260ff60e01b199093169290921790915585516040516001600160a01b03909116917ff226e7d8f547ff903d9d419cf5f54e0d7d07efa9584135a53a057c5f1f27f49a91a2506000949350505050565b6000610ea283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506155fe565b6000610ea283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f00000000000081525061562a565b600082613fb0575060006113dd565b82820282848281613fbd57fe5b0414610ea25760405162461bcd60e51b8152600401610c3b90616972565b600082820183811015610ea25760405162461bcd60e51b8152600401610c3b90616511565b6000806001838154811061401057fe5b9060005260206000209060040201600301549050600060018080549050039050600161403a6125cd565b511161406f5760006001858154811061404f57fe5b9060005260206000209060040201600301819055506000925050506113dd565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516140a89190616d9d565b60405180910390a26001600160a01b038516600090815260046020526040812055835b6001546000190181101561429557600181600101815481106140e957fe5b90600052602060002090600402016001828154811061410457fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b8054909183019081106141c557fe5b9060005260206000209060160201600b82815481106141e057fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054614237938386019390821615610100026000190190911604615d67565b5061424a60038281019084016013615ddc565b5090505080600101600460006001848154811061426357fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020556001016140cb565b5060018054806142a157fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b8054806142f457fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906143266002830182615e06565b614334600383016000615e4a565b50509055600081838161434357fe5b04905080156143a75760015460005b818110156143a457826001828154811061436857fe5b906000526020600020906004020160030154016001828154811061438857fe5b6000918252602090912060036004909202010155600101614352565b50505b50600195945050505050565b6001548151604080518281526020808402820101909152606092919083908280156143f257816020015b60608152602001906001900390816143dd5790505b50600b54909150831461440957925061132d915050565b60005b8281101561451857600b60016004600089858151811061442857fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054038154811061445c57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156144f45780601f106144c9576101008083540402835291602001916144f4565b820191906000526020600020905b8154815290600101906020018083116144d757829003601f168201915b505050505082828151811061450557fe5b602090810291909101015260010161440c565b50949350505050565b60005b8281101561466e5760008287838801604051602001614544929190616196565b6040516020818303038152906040528051906020012060001c8161456457fe5b06905080850182870114614665576000898388018151811061458257fe5b602002602001015190506060898489018151811061459c57fe5b602002602001015190508a838801815181106145b457fe5b60200260200101518b858a01815181106145ca57fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b848901815181106145f957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061462757fe5b60200260200101518a858a018151811061463d57fe5b6020026020010181905250808a8489018151811061465757fe5b602002602001018190525050505b50600101614524565b5050505050505050565b600980546001908101909155600b80548390811061469257fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b82815481106146c857fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b600081604051602001614723919061617a565b604051602081830303815290604052805190602001208360405160200161474a919061617a565b6040516020818303038152906040528051906020012014905092915050565b015190565b6001600160a01b038116600090815260046020526040812054806147975750600019905061132d565b6001810390506000600182815481106147ac57fe5b90600052602060002090600402016003015490506000600183815481106147cf57fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90614828908590616d9d565b60405180910390a2806148405782935050505061132d565b600081838161484b57fe5b04905080156149075760005b848110156148a957816001828154811061486d57fe5b906000526020600020906004020160030154016001828154811061488d57fe5b6000918252602090912060036004909202010155600101614857565b50600180549085015b818110156149045782600182815481106148c857fe5b90600052602060002090600402016003015401600182815481106148e857fe5b60009182526020909120600360049092020101556001016148b2565b50505b5091949350505050565b614919615e59565b506040805180820190915281518152602082810190820152919050565b61493e615d12565b61494782615661565b61495057600080fd5b600061495f836020015161569b565b60208085015160408051808201909152868152920190820152915050919050565b600061498a615e59565b505080518051602091820151919092015191011190565b6149a9615e59565b6149b282614980565b6149bb57600080fd5b602082015160006149cb826156fe565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590614a0457508151602110155b614a0d57600080fd5b6000614a1c836020015161569b565b90508083600001511015614a425760405162461bcd60e51b8152600401610c3b90616b30565b82516020808501518301805192849003929183101561451857506020919091036101000a90049392505050565b6060614a7a82615661565b614a8357600080fd5b6000614a8e836157df565b9050606081604051908082528060200260200182016040528015614acc57816020015b614ab9615e59565b815260200190600190039081614ab15790505b5090506000614ade856020015161569b565b60208601510190506000805b84811015614b3557614afb836156fe565b9150604051806040016040528083815260200184815250848281518110614b1e57fe5b602090810291909101015291810191600101614aea565b509195945050505050565b614b48615d32565b60606000614b54615d32565b6060614b5e615d12565b614b6787614936565b90506000805b614b7683614980565b15614c4b5780614ba157614b91614b8c846149a1565b61583b565b6001600160a01b03168552614c43565b8060011415614bc957614bb6614b8c846149a1565b6001600160a01b03166020860152614c43565b8060021415614bf157614bde614b8c846149a1565b6001600160a01b03166040860152614c43565b8060031415614c1d57614c06612f85846149a1565b6001600160401b0316606086015260019150614c43565b8060041415614c3e57614c37614c32846149a1565b615855565b9350614c43565b614c4b565b600101614b6d565b50929791965091945092505050565b60606113dd614c68836158c5565b6159ab565b6060815160001415614c8e575060408051600081526020810190915261132d565b606082600081518110614c9d57fe5b602002602001015190506000600190505b8351811015614cde57614cd482858381518110614cc757fe5b60200260200101516159fd565b9150600101614cae565b50610ea2614cf1825160c060ff16615a7a565b826159fd565b606080600080808080614d086126c9565b6001549091505b8015614e1657600181039250600b8381548110614d2857fe5b600091825260209091206001601690920201015460ff16614d4857614e0d565b60018381548110614d5557fe5b60009182526020909120600490910201546001600160a01b03169450614d7c858484612d49565b9350831580614d8f575060018a51038610155b15614d9957614e0d565b60005b8a51811015614e0b57856001600160a01b03168b8281518110614dbb57fe5b6020026020010151600001516001600160a01b03161415614e035760018b8281518110614de457fe5b6020908102919091010151901515608090910152600190960195614e0b565b600101614d9c565b505b60001901614d0f565b5084895103604051908082528060200260200182016040528015614e5457816020015b614e41615d32565b815260200190600190039081614e395790505b50965084895103604051908082528060200260200182016040528015614e8e57816020015b6060815260200190600190039081614e795790505b5095506000915060005b8951811015614f2257898181518110614ead57fe5b602002602001015160800151614f1a57898181518110614ec957fe5b6020026020010151888481518110614edd57fe5b6020026020010181905250888181518110614ef457fe5b6020026020010151878481518110614f0857fe5b60200260200101819052508260010192505b600101614e98565b5050505050505b9250929050565b600154825160005b8281101561504d576001614f4a615d32565b60018381548110614f5757fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b8481101561502157878181518110614fe757fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b031614156150195760009250615021565b600101614fd3565b5081156150435780516001600160a01b03166000908152600460205260408120555b5050600101614f38565b508082111561510c57805b8281101561510a57600180548061506b57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b8054806150be57fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906150f06002830182615e06565b6150fe600383016000615e4a565b50509055600101615058565b505b600081831061511b578161511d565b825b905060005b818110156153b0576151cf86828151811061513957fe5b60200260200101516001838154811061514e57fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152615b4c565b6153835780600101600460008884815181106151e757fe5b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000208190555085818151811061522357fe5b60200260200101516001828154811061523857fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015584518590829081106152f357fe5b6020026020010151600b828154811061530857fe5b9060005260206000209060160201600201908051906020019061532c929190615c47565b506000600b828154811061533c57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061536d57fe5b60009182526020909120601690910201556153a8565b60006001828154811061539257fe5b9060005260206000209060040201600301819055505b600101615122565b5082821115615588576153c1615c18565b835b83811015615585578581815181106153d757fe5b6020026020010151826040018190525060018782815181106153f557fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b8054928301815590935284516016909102600080516020616ffb83398151915281019182558583015160008051602061703b8339815191528201805491151560ff199092169190911790559285015180518694929361552b9360008051602061701b83398151915201920190615c47565b5060608201516155419060038301906013615cc1565b505050806001016004600089848151811061555857fe5b602090810291909101810151516001600160a01b03168252810191909152604001600020556001016153c3565b50505b6000600981905560015493505b838110156155f6576000600b82815481106155ac57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106155dd57fe5b6000918252602090912060169091020155600101615595565b505050505050565b600081848411156156225760405162461bcd60e51b8152600401610c3b919061631b565b505050900390565b6000818361564b5760405162461bcd60e51b8152600401610c3b919061631b565b50600083858161565757fe5b0495945050505050565b80516000906156725750600061132d565b6020820151805160001a9060c08210156156915760009250505061132d565b5060019392505050565b8051600090811a60808110156156b557600091505061132d565b60b88110806156d0575060c081108015906156d0575060f881105b156156df57600191505061132d565b60c08110156156f35760b51901905061132d565b60f51901905061132d565b80516000908190811a608081101561571957600191506157d8565b60b881101561572e57607e19810191506157d8565b60c081101561577f57600060b78203600186019550806020036101000a8651049150600181018201935050808310156157795760405162461bcd60e51b8152600401610c3b906168bf565b506157d8565b60f88110156157945760be19810191506157d8565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156157d65760405162461bcd60e51b8152600401610c3b906168bf565b505b5092915050565b80516000906157f05750600061132d565b60008090506000615804846020015161569b565b602085015185519181019250015b8082101561583257615823826156fe565b82019150826001019250615812565b50909392505050565b805160009060151461584c57600080fd5b6113dd826149ef565b805160609061586357600080fd5b6000615872836020015161569b565b83516040805191839003808352601f19601f82011683016020019091529192506060908280156158a9576020820181803683370190505b5090506000816020019050614518848760200151018285615bcd565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166159095750601861592d565b6fffffffffffffffffffffffffffffffff1984166159295750601061592d565b5060005b60208110156159635781818151811061594257fe5b01602001516001600160f81b0319161561595b57615963565b60010161592d565b60008160200390506060816040519080825280601f01601f191660200182016040528015615998576020820181803683370190505b5080830196909652508452509192915050565b6060815160011480156159dd5750607f60f81b826000815181106159cb57fe5b01602001516001600160f81b03191611155b156159e957508061132d565b6113dd6159fb8351608060ff16615a7a565b835b6060806040519050835180825260208201818101602087015b81831015615a2e578051835260209283019201615a16565b50855184518101855292509050808201602086015b81831015615a5b578051835260209283019201615a43565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310615aa45760405162461bcd60e51b8152600401610c3b906166c3565b60408051600180825281830190925260609160208201818036833701905050905060378411615afe5782840160f81b81600081518110615ae057fe5b60200101906001600160f81b031916908160001a90535090506113dd565b6060615b09856158c5565b90508381510160370160f81b82600081518110615b2257fe5b60200101906001600160f81b031916908160001a905350615b4382826159fd565b95945050505050565b805182516000916001600160a01b039182169116148015615b86575081602001516001600160a01b031683602001516001600160a01b0316145b8015615bab575081604001516001600160a01b031683604001516001600160a01b0316145b8015610ea25750506060908101519101516001600160401b0390811691161490565b80615bd757610c5b565b5b60208110615bf7578251825260209283019290910190601f1901615bd8565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001615c42615e73565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615c8857805160ff1916838001178555615cb5565b82800160010185558215615cb5579182015b82811115615cb5578251825591602001919060010190615c9a565b50612704929150615e92565b8260138101928215615cb55791602002820182811115615cb5578251825591602001919060010190615c9a565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040518060400160405280615d25615e59565b8152602001600081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615da05780548555615cb5565b82800160010185558215615cb557600052602060002091601f016020900482015b82811115615cb5578254825591600101919060010190615dc1565b8260138101928215615cb55791820182811115615cb5578254825591600101919060010190615dc1565b50805460018160011615610100020316600290046000825580601f10615e2c5750611539565b601f0160209004906000526020600020908101906115399190615e92565b50611539906013810190615e92565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b6126b691905b808211156127045760008155600101615e98565b60008083601f840112615ebd578182fd5b5081356001600160401b03811115615ed3578182fd5b6020830191508360208083028501011115614f2957600080fd5b60008083601f840112615efe578182fd5b5081356001600160401b03811115615f14578182fd5b602083019150836020828501011115614f2957600080fd5b600060208284031215615f3d578081fd5b81356001600160a01b0381168114610ea2578182fd5b60008060008060408587031215615f68578283fd5b84356001600160401b0380821115615f7e578485fd5b615f8a88838901615eac565b90965094506020870135915080821115615fa2578384fd5b50615faf87828801615eac565b95989497509550505050565b600060208284031215615fcc578081fd5b81518015158114610ea2578182fd5b60008060008060408587031215615ff0578384fd5b84356001600160401b0380821115616006578586fd5b61601288838901615eed565b9096509450602087013591508082111561602a578384fd5b50615faf87828801615eed565b600060208284031215616048578081fd5b5035919050565b600060208284031215616060578081fd5b5051919050565b60008060408385031215616079578182fd5b505080516020909101519092909150565b60008060006040848603121561609e578283fd5b833560ff811681146160ae578384fd5b925060208401356001600160401b038111156160c8578283fd5b6160d486828701615eed565b9497909650939450505050565b6000815180845260208085019450808401835b838110156161195781516001600160a01b0316875295820195908201906001016160f4565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b60008151808452616166816020860160208601616e03565b601f01601f19169290920160200192915050565b6000825161618c818460208701616e03565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b600060208252610ea260208301846160e1565b60006040825261623960408301856160e1565b602083820381850152818551808452828401915082838202850101838801865b8381101561628757601f1987840301855261627583835161614e565b94860194925090850190600101616259565b50909998505050505050505050565b6000608082526162a960808301876160e1565b828103602084810191909152865180835287820192820190845b818110156162df578451835293830193918301916001016162c3565b505084810360408601526162f381886160e1565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b600060208252610ea2602083018461614e565b600060408252616342604083018688616124565b8281036020840152616355818587616124565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252602b908201527f746865206275726e526174696f206d757374206265206e6f206772656174657260408201526a0207468616e2031303030360ac1b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b60208082526027908201527f7468652066696e616c697479526577617264526174696f206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662066696e616c697479526577617264526174696f206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152615b43606083018461614e565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260406020830152615b43604083018486616124565b60005b83811015616e1e578181015183820152602001616e06565b83811115612c69575050600091015256fef901a880f901a4f844941284214b9b9c85549ab3d2b972df0deef66ac2c9946ddf42a51534fc98d0c0a3b42c963cace8441ddf946ddf42a51534fc98d0c0a3b42c963cace8441ddf8410000000f84494a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0948081ef03f1d9e0bb4a5bf38f16285c879299f07f948081ef03f1d9e0bb4a5bf38f16285c879299f07f8410000000f8449435552c16704d214347f29fa77f77da6d75d7c75294dc4973e838e3949c77aced16ac2315dc2d7ab11194dc4973e838e3949c77aced16ac2315dc2d7ab1118410000000f84494980a75ecd1309ea12fa2ed87a8744fbfc9b863d594cc6ac05c95a99c1f7b5f88de0e3486c82293b27094cc6ac05c95a99c1f7b5f88de0e3486c82293b2708410000000f84494f474cf03cceff28abc65c9cbae594f725c80e12d94e61a183325a18a173319dd8e19c8d069459e217594e61a183325a18a173319dd8e19c8d069459e21758410000000f84494b71b214cb885500844365e95cd9942c7276e7fd894d22ca3ba2141d23adab65ce4940eb7665ea2b6a794d22ca3ba2141d23adab65ce4940eb7665ea2b6a7841000000070e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa264697066735822122066baf1b414176214a54e961d8a8bfa2613b6bb53f85786a9a7171a3bac231aa564736f6c63430006040033",
+ },
+ {
+ ContractAddr: common.HexToAddress(SlashContract),
+ CommitUrl: "https://github.com/node-real/bsc-genesis-contract/commit/f8bab13f56955e979bfb754425dab1e62e52f151",
+ Code: "608060405234801561001057600080fd5b50600436106102745760003560e01c80638256ace611610151578063c81b1662116100c3578063dc927faf11610087578063dc927faf1461049a578063e1c7392a146104a2578063f9a2bbc7146104aa578063fc3e5908146104b2578063fc4333cd146104ba578063fd6a6879146104c257610274565b8063c81b166214610451578063c8509d8114610459578063c96be4cb1461046c578063cc844b731461047f578063d2a42e4b1461049257610274565b8063a1a11bf511610115578063a1a11bf514610409578063a78abc1614610411578063ab51bb9614610426578063ac0af6291461042e578063ac43175114610436578063c80d4b8f1461044957610274565b80638256ace6146103d6578063831d65d1146103de57806396713da9146103f15780639bc8e4f2146103f95780639dc092621461040157610274565b80634bf6c882116101ea5780636e47b482116101ae5780636e47b482146103a657806370fd5bad146103ae578063718a8aa8146103b657806375d47a0a146103be5780637912a65d146103c65780637942fd05146103ce57610274565b80634bf6c8821461037157806351e8067214610379578063567a372d146103815780635bfb49901461038957806362b72cf51461039e57610274565b806337c8dab91161023c57806337c8dab914610301578063389f4f71146103225780633a63f4b1146103375780633dffc3871461033f57806343756e5c14610354578063493279b11461035c57610274565b80630bee7a67146102795780630e2374a5146102975780631182b875146102ac57806323bac5a2146102cc57806335aa2e44146102ee575b600080fd5b6102816104ca565b60405161028e9190613056565b60405180910390f35b61029f6104cf565b60405161028e9190612987565b6102bf6102ba3660046128bd565b6104d5565b60405161028e91906129bf565b6102df6102da36600461266b565b61053b565b60405161028e9392919061303e565b61029f6102fc36600461288d565b61055e565b61031461030f36600461266b565b610585565b60405161028e929190613030565b61032a6105dc565b60405161028e9190613006565b61032a6105e2565b6103476105e8565b60405161028e9190613067565b61029f6105ed565b6103646105f3565b60405161028e9190612ff7565b6103476105f8565b61029f6105fd565b61032a610603565b61039c61039736600461266b565b610609565b005b61032a6106b4565b61029f6106ba565b6103476106c0565b6103476106c5565b61029f6106ca565b61032a6106d0565b6103476106d5565b6103146106da565b61039c6103ec3660046128bd565b6106e4565b6103476107f6565b61032a6107fb565b61029f610806565b61029f61080c565b610419610812565b60405161028e91906129b4565b61028161081b565b61032a610820565b61039c610444366004612771565b610825565b61032a610bd9565b61029f610bde565b61039c6104673660046128bd565b610be4565b61039c61047a36600461266b565b610c55565b61039c61048d3660046127da565b611046565b61032a61151c565b61029f611521565b61039c611527565b61029f611563565b610347611569565b61039c61156e565b61029f6119b7565b606481565b61200181565b606033612000146105015760405162461bcd60e51b81526004016104f890612e7d565b60405180910390fd5b60005460ff166105235760405162461bcd60e51b81526004016104f890612a6b565b60405162461bcd60e51b81526004016104f890612f40565b600260208190526000918252604090912080546001820154919092015460ff1683565b6001818154811061056b57fe5b6000918252602090912001546001600160a01b0316905081565b600080610590612452565b5050506001600160a01b0316600090815260026020818152604092839020835160608101855281548082526001830154938201849052919093015460ff16151592909301919091529091565b60055481565b60065481565b600181565b61100181565b606181565b600881565b61200081565b60045481565b336110001461062a5760405162461bcd60e51b81526004016104f890612c91565b60005460ff1661064c5760405162461bcd60e51b81526004016104f890612a6b565b61200063f7a251d7600b61065f846119bd565b60006040518463ffffffff1660e01b815260040161067f93929190613075565b600060405180830381600087803b15801561069957600080fd5b505af11580156106ad573d6000803e3d6000fd5b5050505050565b60035481565b61100581565b600281565b601081565b61100881565b603281565b600b81565b6004546005549091565b33612000146107055760405162461bcd60e51b81526004016104f890612e7d565b60005460ff166107275760405162461bcd60e51b81526004016104f890612a6b565b61072f612475565b600061077084848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a8f92505050565b9150915080156107b75781516040517f7f0956d47419b9525356e7111652b653b530ec6f5096dccc04589bc38e629967916107aa91613056565b60405180910390a16106ad565b81516040517f7d45f62d17443dd4547bca8a8112c60e2385669318dc300ec61a5d2492f262e7916107e791613056565b60405180910390a15050505050565b600981565b662386f26fc1000081565b61100781565b61100681565b60005460ff1681565b600081565b600481565b60005460ff166108475760405162461bcd60e51b81526004016104f890612a6b565b33611007146108685760405162461bcd60e51b81526004016104f890612d3a565b6108d384848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260148152731b5a5cd9195b59585b9bdc951a1c995cda1bdb1960621b60208201529150611b0f9050565b1561096e57602081146108f85760405162461bcd60e51b81526004016104f890612c1d565b604080516020601f840181900481028201810190925282815260009161093691858580838501838280828437600092019190915250611b6992505050565b90506001811015801561094a575060055481105b6109665760405162461bcd60e51b81526004016104f890612e38565b600455610b96565b6109d484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e19995b1bdb9e551a1c995cda1bdb19608a1b60208201529150611b0f9050565b15610a7057602081146109f95760405162461bcd60e51b81526004016104f890612d88565b604080516020601f8401819004810282018101909252828152600091610a3791858580838501838280828437600092019190915250611b6992505050565b90506103e88111158015610a4c575060045481115b610a685760405162461bcd60e51b81526004016104f890612ad9565b600555610b96565b610ae484848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f66696e616c697479536c617368526577617264526174696f000000000000000060208201529150611b0f9050565b15610b7e5760208114610b095760405162461bcd60e51b81526004016104f890612f77565b604080516020601f8401819004810282018101909252828152600091610b4791858580838501838280828437600092019190915250611b6992505050565b9050600a8110158015610b5a5750606481105b610b765760405162461bcd60e51b81526004016104f890612bd1565b600655610b96565b60405162461bcd60e51b81526004016104f890612f19565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a84848484604051610bcb94939291906129d2565b60405180910390a150505050565b609681565b61100281565b3361200014610c055760405162461bcd60e51b81526004016104f890612e7d565b60005460ff16610c275760405162461bcd60e51b81526004016104f890612a6b565b6040517f07db600eebe2ac176be8dcebad61858c245a4961bb32ca2aa3d159b09aa0810e90600090a1505050565b334114610c745760405162461bcd60e51b81526004016104f890612ecc565b60005460ff16610c965760405162461bcd60e51b81526004016104f890612a6b565b6003544311610cb75760405162461bcd60e51b81526004016104f890612fc2565b3a15610cd55760405162461bcd60e51b81526004016104f890612d0c565b60405163155853f360e21b8152611000906355614fcc90610cfa908490600401612987565b60206040518083038186803b158015610d1257600080fd5b505afa158015610d26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4a9190612751565b610d535761103f565b610d5b612452565b506001600160a01b0381166000908152600260208181526040928390208351606081018552815481526001820154928101929092529091015460ff161580159282019290925290610db6576020810180516001019052610e0f565b60016040820181905260208201819052805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0384161790555b438152600554602082015181610e2157fe5b06610f6d57600060208201526040516335409f7f60e01b8152611000906335409f7f90610e52908590600401612987565b600060405180830381600087803b158015610e6c57600080fd5b505af1158015610e80573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b610ea0856119bd565b60006040518463ffffffff1660e01b8152600401610ec093929190613075565b600060405180830381600087803b158015610eda57600080fd5b505af1925050508015610eeb575060015b610f68573d808015610f19576040519150601f19603f3d011682016040523d82523d6000602084013e610f1e565b606091505b50826001600160a01b03167fd7bc86ff5d08c8ab043edec743302aba2520e6635172a428bc956721db9e2d1c836020015183604051610f5e92919061300f565b60405180910390a2505b610fd9565b600454816020015181610f7c57fe5b06610fd9576040516375abf10160e11b81526110009063eb57e20290610fa6908590600401612987565b600060405180830381600087803b158015610fc057600080fd5b505af1158015610fd4573d6000803e3d6000fd5b505050505b6001600160a01b0382166000818152600260208181526040808420865181559186015160018301558581015191909201805460ff1916911515919091179055517fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9190a2505b5043600355565b60005460ff166110685760405162461bcd60e51b81526004016104f890612a6b565b604051630a83aaa960e31b81526110069063541d55489061108d903390600401612987565b60206040518083038186803b1580156110a557600080fd5b505afa1580156110b9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110dd9190612751565b6110f95760405162461bcd60e51b81526004016104f890612a04565b6006546111065760146006555b8051514361010090910111801561112857504381602001516000015161010001115b6111445760405162461bcd60e51b81526004016104f890612a3b565b8060200151602001518160000151602001511480156111725750806020015160600151816000015160600151145b1561118f5760405162461bcd60e51b81526004016104f890612c64565b8051604081015190511080156111ae5750602081015160408101519051105b6111ca5760405162461bcd60e51b81526004016104f890612b6d565b6020810151518151511080156111ef5750806000015160400151816020015160400151105b8061121a575080515160208201515110801561121a5750806020015160400151816000015160400151105b806112345750806020015160400151816000015160400151145b6112505760405162461bcd60e51b81526004016104f890612aa2565b6060806110006001600160a01b0316633b071dcc6040518163ffffffff1660e01b815260040160006040518083038186803b15801561128e57600080fd5b505afa1580156112a2573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112ca919081019061268e565b60408501519193509150600090815b8351811015611327576112ff8482815181106112f157fe5b602002602001015183611b6e565b1561131f5784818151811061131057fe5b60200260200101519250611327565b6001016112d9565b506001600160a01b03821661134e5760405162461bcd60e51b81526004016104f890612ba4565b61136085600001518660400151611bd2565b8015611379575061137985602001518660400151611bd2565b6113955760405162461bcd60e51b81526004016104f890612b0e565b6006546040516309a99b4f60e41b815260646110028031909302049190639a99b4f0906113c8903390859060040161299b565b602060405180830381600087803b1580156113e257600080fd5b505af11580156113f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141a91906128a5565b506040516335409f7f60e01b8152611000906335409f7f90611440908690600401612987565b600060405180830381600087803b15801561145a57600080fd5b505af115801561146e573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b61148e866119bd565b60006040518463ffffffff1660e01b81526004016114ae93929190613075565b600060405180830381600087803b1580156114c857600080fd5b505af11580156114dc573d6000803e3d6000fd5b50506040516001600160a01b03861692507fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9150600090a2505050505050565b601481565b61100381565b60005460ff161561154a5760405162461bcd60e51b81526004016104f890612dca565b603260045560966005556000805460ff19166001179055565b61100081565b600381565b336110001461158f5760405162461bcd60e51b81526004016104f890612c91565b60005460ff166115b15760405162461bcd60e51b81526004016104f890612a6b565b6001546115bd576119b5565b600154600090600019015b808211611989576000805b828410156116ec576115e3612452565b60026000600187815481106115f457fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156116d65760046005548161166157fe5b0481602001510381602001818152505080600260006001888154811061168357fe5b6000918252602080832091909101546001600160a01b0316835282810193909352604091820190208351815591830151600183015591909101516002909101805460ff19169115159190911790556116e0565b60019250506116ec565b508360010193506115d3565b828411611883576116fb612452565b600260006001868154811061170c57fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156117f45760046005548161177957fe5b0481602001510381602001818152505080600260006001878154811061179b57fe5b6000918252602080832091909101546001600160a01b03168352828101939093526040918201902083518155918301516001808401919091559201516002909101805460ff191691151591909117905591506118839050565b600260006001868154811061180557fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff1916905580548061184957fe5b600082815260209020810160001990810180546001600160a01b0319169055019055836118765750611883565b50600019909201916116ec565b81801561188d5750805b1561196c5760026000600186815481106118a357fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff191690558054849081106118ea57fe5b600091825260209091200154600180546001600160a01b03909216918690811061191057fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600180548061194957fe5b600082815260209020810160001990810180546001600160a01b03191690550190555b82611978575050611989565b5050600190910190600019016115c8565b6040517fcfdb3b6ccaeccbdc68be3c59c840e3b3c90f0a7c491f5fff1cf56cfda200dd9c90600090a150505b565b61100481565b60408051600480825260a08201909252606091829190816020015b60608152602001906001900390816119d8579050509050611a01836001600160a01b0316611daa565b81600081518110611a0e57fe5b6020026020010181905250611a2243611dcd565b81600181518110611a2f57fe5b6020908102919091010152611a446061611dcd565b81600281518110611a5157fe5b6020026020010181905250611a6542611dcd565b81600381518110611a7257fe5b6020026020010181905250611a8681611de0565b9150505b919050565b611a97612475565b6000611aa1612475565b611aa9612487565b611aba611ab586611e6a565b611e8f565b90506000805b611ac983611ed9565b15611b025780611af557611ae4611adf84611efa565b611f48565b63ffffffff16845260019150611afa565b611b02565b600101611ac0565b5091935090915050915091565b600081604051602001611b22919061296b565b6040516020818303038152906040528051906020012083604051602001611b49919061296b565b604051602081830303815290604052805190602001201490505b92915050565b015190565b815181516000916001918114808314611b8a5760009250611bc8565b600160208701838101602088015b600284838510011415611bc3578051835114611bb75760009650600093505b60209283019201611b98565b505050505b5090949350505050565b60408051600480825260a0820190925260009160609190816020015b6060815260200190600190039081611bee575050604080516020808252818301909252919250606091908082018180368337019050509050611c338560000151611dcd565b82600081518110611c4057fe5b6020026020010181905250611c5b6020866020015183611fca565b611c6481611fda565b82600181518110611c7157fe5b6020026020010181905250611c898560400151611dcd565b82600281518110611c9657fe5b6020026020010181905250611cb16020866060015183611fca565b611cba81611fda565b82600381518110611cc757fe5b6020026020010181905250611ced6020611ce084611de0565b8051906020012083611fca565b6040805160b080825260e08201909252606091602082018180368337019050509050611d1d818360006020612030565b611d2f81876080015160206060612030565b611d3d818660806030612030565b604080516001808252818301909252606091602082018180368337019050509050815160016020830182602086016066600019fa611d7a57600080fd5b506001611d88826000612083565b60ff1614611d9d576000945050505050611b63565b5060019695505050505050565b60408051600560a21b8318601482015260348101909152606090611a8681611fda565b6060611b63611ddb8361209f565b611fda565b6060815160001415611e015750604080516000815260208101909152611a8a565b606082600081518110611e1057fe5b602002602001015190506000600190505b8351811015611e5157611e4782858381518110611e3a57fe5b6020026020010151612185565b9150600101611e21565b50611a86611e64825160c060ff16612202565b82612185565b611e726124a7565b506040805180820190915281518152602082810190820152919050565b611e97612487565b611ea0826122d4565b611ea957600080fd5b6000611eb8836020015161230e565b60208085015160408051808201909152868152920190820152915050919050565b6000611ee36124a7565b505080518051602091820151919092015191011190565b611f026124a7565b611f0b82611ed9565b611f1457600080fd5b60208201516000611f2482612371565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590611f5d57508151602110155b611f6657600080fd5b6000611f75836020015161230e565b90508083600001511015611f9b5760405162461bcd60e51b81526004016104f890612e01565b825160208085015183018051928490039291831015611fc157826020036101000a820491505b50949350505050565b9091018181526020918201910152565b60608151600114801561200c5750607f60f81b82600081518110611ffa57fe5b01602001516001600160f81b03191611155b15612018575080611a8a565b611b6361202a8351608060ff16612202565b83612185565b60005b818110156106ad5783818151811061204757fe5b602001015160f81c60f81b85848060010195508151811061206457fe5b60200101906001600160f81b031916908160001a905350600101612033565b6000816001018351101561209657600080fd5b50016001015190565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166120e357506018612107565b6fffffffffffffffffffffffffffffffff19841661210357506010612107565b5060005b602081101561213d5781818151811061211c57fe5b01602001516001600160f81b031916156121355761213d565b600101612107565b60008160200390506060816040519080825280601f01601f191660200182016040528015612172576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b818310156121b657805183526020928301920161219e565b50855184518101855292509050808201602086015b818310156121e35780518352602092830192016121cb565b508651929092011591909101601f01601f191660405250905092915050565b606068010000000000000000831061222c5760405162461bcd60e51b81526004016104f890612b45565b604080516001808252818301909252606091602082018180368337019050509050603784116122865782840160f81b8160008151811061226857fe5b60200101906001600160f81b031916908160001a9053509050611b63565b60606122918561209f565b90508381510160370160f81b826000815181106122aa57fe5b60200101906001600160f81b031916908160001a9053506122cb8282612185565b95945050505050565b80516000906122e557506000611a8a565b6020820151805160001a9060c082101561230457600092505050611a8a565b5060019392505050565b8051600090811a6080811015612328576000915050611a8a565b60b8811080612343575060c08110801590612343575060f881105b15612352576001915050611a8a565b60c08110156123665760b519019050611a8a565b60f519019050611a8a565b80516000908190811a608081101561238c576001915061244b565b60b88110156123a157607e198101915061244b565b60c08110156123f257600060b78203600186019550806020036101000a8651049150600181018201935050808310156123ec5760405162461bcd60e51b81526004016104f890612ce1565b5061244b565b60f88110156124075760be198101915061244b565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156124495760405162461bcd60e51b81526004016104f890612ce1565b505b5092915050565b604051806060016040528060008152602001600081526020016000151581525090565b60408051602081019091526000815290565b604051806040016040528061249a6124a7565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b600082601f8301126124d1578081fd5b81516124e46124df826130c8565b6130a1565b818152915060208083019084810160005b8481101561255a578151870188603f82011261251057600080fd5b838101516125206124df826130e8565b81815260408b8184860101111561253657600080fd5b6125458388840183870161310c565b508652505092820192908201906001016124f5565b505050505092915050565b60008083601f840112612576578182fd5b50813567ffffffffffffffff81111561258d578182fd5b6020830191508360208285010111156125a557600080fd5b9250929050565b600082601f8301126125bc578081fd5b81356125ca6124df826130e8565b91508082528360208285010111156125e157600080fd5b8060208401602084013760009082016020015292915050565b600060a0828403121561260b578081fd5b61261560a06130a1565b905081358152602082013560208201526040820135604082015260608201356060820152608082013567ffffffffffffffff81111561265357600080fd5b61265f848285016125ac565b60808301525092915050565b60006020828403121561267c578081fd5b81356126878161313c565b9392505050565b600080604083850312156126a0578081fd5b825167ffffffffffffffff808211156126b7578283fd5b81850186601f8201126126c8578384fd5b805192506126d86124df846130c8565b80848252602080830192508084018a8283890287010111156126f8578788fd5b8794505b8685101561272357805161270f8161313c565b8452600194909401939281019281016126fc565b50880151909650935050508082111561273a578283fd5b50612747858286016124c1565b9150509250929050565b600060208284031215612762578081fd5b81518015158114612687578182fd5b60008060008060408587031215612786578182fd5b843567ffffffffffffffff8082111561279d578384fd5b6127a988838901612565565b909650945060208701359150808211156127c1578384fd5b506127ce87828801612565565b95989497509550505050565b6000602082840312156127eb578081fd5b813567ffffffffffffffff80821115612802578283fd5b81840160608187031215612814578384fd5b61281e60606130a1565b925080358281111561282e578485fd5b61283a878284016125fa565b84525060208101358281111561284e578485fd5b61285a878284016125fa565b602085015250604081013582811115612871578485fd5b61287d878284016125ac565b6040850152509195945050505050565b60006020828403121561289e578081fd5b5035919050565b6000602082840312156128b6578081fd5b5051919050565b6000806000604084860312156128d1578283fd5b833560ff811681146128e1578384fd5b9250602084013567ffffffffffffffff8111156128fc578283fd5b61290886828701612565565b9497909650939450505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b6000815180845261295781602086016020860161310c565b601f01601f19169290920160200192915050565b6000825161297d81846020870161310c565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b600060208252612687602083018461293f565b6000604082526129e6604083018688612915565b82810360208401526129f9818587612915565b979650505050505050565b6020808252601f908201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604082015260600190565b6020808252601690820152751d1bdbc81bdb1908189b1bd8dac81a5b9d9bdb1d995960521b604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601a908201527f6e6f2076696f6c6174696f6e206f6620766f74652072756c6573000000000000604082015260600190565b6020808252818101527f7468652066656c6f6e795468726573686f6c64206f7574206f662072616e6765604082015260600190565b60208082526017908201527f766572696679207369676e6174757265206661696c6564000000000000000000604082015260600190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526019908201527f7372634e756d20626967676572207468616e207461724e756d00000000000000604082015260600190565b6020808252601390820152721d985b1a59185d1bdc881b9bdd08195e1a5cdd606a1b604082015260600190565b6020808252602c908201527f7468652066696e616c69747920736c6173682072657761726420726174696f2060408201526b6f7574206f662072616e676560a01b606082015260800190565b60208082526027908201527f6c656e677468206f66206d697364656d65616e6f725468726573686f6c64206d6040820152660d2e6dac2e8c6d60cb1b606082015260800190565b60208082526013908201527274776f206964656e746963616c20766f74657360681b604082015260600190565b60208082526030908201527f746865206d6573736167652073656e646572206d7573742062652076616c696460408201526f185d1bdc94d95d0818dbdb9d1c9858dd60821b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526022908201527f6c656e677468206f662066656c6f6e795468726573686f6c64206d69736d61746040820152610c6d60f31b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526025908201527f746865206d697364656d65616e6f725468726573686f6c64206f7574206f662060408201526472616e676560d81b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b6020808252601e908201527f7265636569766520756e65787065637465642073796e207061636b6167650000604082015260600190565b6020808252602b908201527f6c656e677468206f662066696e616c697479536c61736852657761726452617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b6020808252818101527f63616e206e6f7420736c61736820747769636520696e206f6e6520626c6f636b604082015260600190565b61ffff91909116815260200190565b90815260200190565b600083825260406020830152613028604083018461293f565b949350505050565b918252602082015260400190565b92835260208301919091521515604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260606020830152613091606083018561293f565b9050826040830152949350505050565b60405181810167ffffffffffffffff811182821017156130c057600080fd5b604052919050565b600067ffffffffffffffff8211156130de578081fd5b5060209081020190565b600067ffffffffffffffff8211156130fe578081fd5b50601f01601f191660200190565b60005b8381101561312757818101518382015260200161310f565b83811115613136576000848401525b50505050565b6001600160a01b038116811461315157600080fd5b5056fea26469706673582212201998b6d3cfafcfa417a78cc743a5d15a50d1d5c8615cc00839d6f07e9545a35b64736f6c63430006040033",
+ },
+ {
+ ContractAddr: common.HexToAddress(SystemRewardContract),
+ CommitUrl: "https://github.com/node-real/bsc-genesis-contract/commit/f8bab13f56955e979bfb754425dab1e62e52f151",
+ Code: "6080604052600436106101a05760003560e01c80637942fd05116100ec578063ac4317511161008a578063f9a2bbc711610064578063f9a2bbc714610550578063fb5478b314610565578063fc3e59081461057a578063fd6a68791461058f576101e4565b8063ac43175114610457578063c81b166214610526578063dc927faf1461053b576101e4565b80639dc09262116100c65780639dc0926214610403578063a1a11bf514610418578063a78abc161461042d578063ab51bb9614610442576101e4565b80637942fd05146103a057806396713da9146103b55780639a99b4f0146103ca576101e4565b80634bf6c882116101595780636e47b482116101335780636e47b4821461034c57806370fd5bad14610361578063718a8aa81461037657806375d47a0a1461038b576101e4565b80634bf6c882146102db57806351e80672146102f05780636d70f7ae14610305576101e4565b80630bee7a67146101e95780630e2374a5146102175780633a0b0eff146102485780633dffc3871461026f57806343756e5c1461029a578063493279b1146102af576101e4565b366101e45734156101e25760408051348152905133917f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db919081900360200190a25b005b600080fd5b3480156101f557600080fd5b506101fe6105a4565b6040805163ffffffff9092168252519081900360200190f35b34801561022357600080fd5b5061022c6105a9565b604080516001600160a01b039092168252519081900360200190f35b34801561025457600080fd5b5061025d6105af565b60408051918252519081900360200190f35b34801561027b57600080fd5b506102846105b5565b6040805160ff9092168252519081900360200190f35b3480156102a657600080fd5b5061022c6105ba565b3480156102bb57600080fd5b506102c46105c0565b6040805161ffff9092168252519081900360200190f35b3480156102e757600080fd5b506102846105c5565b3480156102fc57600080fd5b5061022c6105ca565b34801561031157600080fd5b506103386004803603602081101561032857600080fd5b50356001600160a01b03166105d0565b604080519115158252519081900360200190f35b34801561035857600080fd5b5061022c6105ee565b34801561036d57600080fd5b506102846105f4565b34801561038257600080fd5b506102846105f9565b34801561039757600080fd5b5061022c6105fe565b3480156103ac57600080fd5b50610284610604565b3480156103c157600080fd5b50610284610609565b3480156103d657600080fd5b5061025d600480360360408110156103ed57600080fd5b506001600160a01b03813516906020013561060e565b34801561040f57600080fd5b5061022c6107b9565b34801561042457600080fd5b5061022c6107bf565b34801561043957600080fd5b506103386107c5565b34801561044e57600080fd5b506101fe6107ce565b34801561046357600080fd5b506101e26004803603604081101561047a57600080fd5b81019060208101813564010000000081111561049557600080fd5b8201836020820111156104a757600080fd5b803590602001918460018302840111640100000000831117156104c957600080fd5b9193909290916020810190356401000000008111156104e757600080fd5b8201836020820111156104f957600080fd5b8035906020019184600183028401116401000000008311171561051b57600080fd5b5090925090506107d3565b34801561053257600080fd5b5061022c610b56565b34801561054757600080fd5b5061022c610b5c565b34801561055c57600080fd5b5061022c610b62565b34801561057157600080fd5b5061025d610b68565b34801561058657600080fd5b50610284610b74565b34801561059b57600080fd5b5061022c610b79565b606481565b61200181565b60015481565b600181565b61100181565b606181565b600881565b61200081565b6001600160a01b031660009081526002602052604090205460ff1690565b61100581565b600281565b601081565b61100881565b600b81565b600981565b6000805460ff1661068b57600260208190527fe57bda0a954a7c7381b17b2c763e646ba2c60f67292d287ba583603e2c1c41668054600160ff19918216811790925561100560009081527fe25235fc0de9d7165652bef0846fefda506174abb9a190f03d0f7bcc6146dbce80548316841790559282558254161790555b3360009081526002602052604090205460ff166106d95760405162461bcd60e51b815260040180806020018281038252602b815260200180610c67602b913960400191505060405180910390fd5b60004783106106e857476106ea565b825b9050670de0b6b3a76400008111156107075750670de0b6b3a76400005b8015610788576040516001600160a01b0385169082156108fc029083906000818181858888f19350505050158015610743573d6000803e3d6000fd5b506040805182815290516001600160a01b038616917ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0919081900360200190a26107b2565b6040517fe589651933c2457488cc0d8e0941518abf748e799435e4e396d9c4d0b2db2d4d90600090a15b9392505050565b61100781565b61100681565b60005460ff1681565b600081565b33611007146108135760405162461bcd60e51b815260040180806020018281038252602e815260200180610cc1602e913960400191505060405180910390fd5b61087584848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600b81526a30b23227b832b930ba37b960a91b60208201529150610b7f9050565b1561094d57606082828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050825192935050601490911490506108f85760405162461bcd60e51b815260040180806020018281038252602c815260200180610cef602c913960400191505060405180910390fd5b60148101516001600160a01b038116600081815260026020526040808220805460ff19166001179055517f9870d7fe5d112134c55844951dedf365363006d9c588db07c4c85af6322a06199190a25050610ac4565b6109b284848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600e81526d3232b632ba32a7b832b930ba37b960911b60208201529150610b7f9050565b15610a8757606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060149091149050610a355760405162461bcd60e51b815260040180806020018281038252602f815260200180610c92602f913960400191505060405180910390fd5b60148101516001600160a01b038116600081815260026020526040808220805460ff19169055517fb40992a19dba61ea600e87fce607102bf5908dc89076217b6ca6ae195224f7029190a25050610ac4565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b61100281565b61100381565b61100081565b670de0b6b3a764000081565b600381565b61100481565b6000816040516020018082805190602001908083835b60208310610bb45780518252601f199092019160209182019101610b95565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310610c225780518252601f199092019160209182019101610c03565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201490509291505056fe6f6e6c79206f70657261746f7220697320616c6c6f77656420746f2063616c6c20746865206d6574686f646c656e677468206f662076616c756520666f722064656c6574654f70657261746f722073686f756c64206265203230746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662076616c756520666f72206164644f70657261746f722073686f756c64206265203230a26469706673582212205c998ac20925f17d8af20803f32be2cf1698c9a844de45001ca5ed8c879cc93f64736f6c63430006040033",
+ },
+ },
+ }
+
+ bonehUpgrade[rialtoNet] = &Upgrade{
+ UpgradeName: "boneh",
+ Configs: []*UpgradeConfig{
+ {
+ ContractAddr: common.HexToAddress(ValidatorContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/030cf951e9f5ae1f8211333af807e5d30f3b5a85",
+ Code: "60806040526004361061046c5760003560e01c8063862498821161024a578063c6d3394511610139578063e40716a1116100b6578063f9a2bbc71161007a578063f9a2bbc714610b6b578063fc3e590814610b80578063fccc281314610b95578063fd4ad81f14610baa578063fd6a687914610bd957610473565b8063e40716a114610af9578063eb57e20214610b0e578063eda5868c14610b2e578063f340fa0114610b43578063f92eb86b14610b5657610473565b8063d86222d5116100fd578063d86222d514610a90578063daacdb6614610aa5578063dc927faf14610aba578063e086c7b114610acf578063e1c7392a14610ae457610473565b8063c6d3394514610a3c578063c81b166214610a51578063c8509d811461085f578063d04aa99614610a66578063d68fb56a14610a7b57610473565b8063a5422d5c116101c7578063ad3c9da61161018b578063ad3c9da6146109d0578063aef198a9146109f0578063b7ab4db514610a05578063b8cf4ef114610a27578063bf9f49951461062f57610473565b8063a5422d5c1461095c578063a78abc1614610971578063aaf5eb6814610986578063ab51bb961461099b578063ac431751146109b057610473565b806396713da91161020e57806396713da9146108f35780639dc09262146109085780639fe0f8161461091d578063a0dc275814610932578063a1a11bf51461094757610473565b8063862498821461087f57806388b32f11146108945780638b5ad0c9146108a95780638d19a410146108be5780639369d7de146108de57610473565b80634df6e0c3116103665780636e47b482116102e35780637942fd05116102a75780637942fd05146108205780637a84ca2a1461083557806381650b621461084a578063831d65d11461085f578063853230aa1461080b57610473565b80636e47b482146107b757806370fd5bad146107cc578063718a8aa8146107e157806375d47a0a146107f657806378dfed4a1461080b57610473565b8063565c56b31161032a578063565c56b3146107265780635667515a146107465780635d77156c1461075b57806362b72cf5146107705780636969a25c1461078557610473565b80634df6e0c3146106b25780635192c82c146106c757806351e80672146106dc578063549b03f2146106f157806355614fcc1461070657610473565b8063321d398a116103f45780633dffc387116103b85780633dffc3871461062f57806343756e5c1461065157806345cf9daf14610666578063493279b11461067b5780634bf6c8821461069d57610473565b8063321d398a146105975780633365af3a146105b757806335409f7f146105d75780633b071dcc146105f75780633de0f0d81461061a57610473565b80631182b8751161043b5780631182b875146104fe578063152ad3b81461052b5780631ff180691461054d578063219f22d514610562578063300c35671461057757610473565b806304c4fec61461047857806307a568471461048f5780630bee7a67146104ba5780630e2374a5146104dc57610473565b3661047357005b600080fd5b34801561048457600080fd5b5061048d610bee565b005b34801561049b57600080fd5b506104a4610c60565b6040516104b19190616ef1565b60405180910390f35b3480156104c657600080fd5b506104cf610c66565b6040516104b19190616f1b565b3480156104e857600080fd5b506104f1610c6b565b6040516104b191906162f8565b34801561050a57600080fd5b5061051e6105193660046161de565b610c71565b6040516104b1919061646f565b34801561053757600080fd5b50610540610ea9565b6040516104b19190616464565b34801561055957600080fd5b506104a4610eb2565b34801561056e57600080fd5b506104cf610eb8565b34801561058357600080fd5b5061048d6105923660046160a7565b610ebd565b3480156105a357600080fd5b506105406105b236600461618b565b611241565b3480156105c357600080fd5b506105406105d236600461618b565b611310565b3480156105e357600080fd5b5061048d6105f2366004616080565b6113c1565b34801561060357600080fd5b5061060c61151a565b6040516104b192919061637a565b34801561062657600080fd5b506104a46117f6565b34801561063b57600080fd5b506106446117fc565b6040516104b19190616f2c565b34801561065d57600080fd5b506104f1611801565b34801561067257600080fd5b506104a4611807565b34801561068757600080fd5b5061069061180d565b6040516104b19190616ee2565b3480156106a957600080fd5b50610644611813565b3480156106be57600080fd5b5061060c611818565b3480156106d357600080fd5b506104a4611996565b3480156106e857600080fd5b506104f161199c565b3480156106fd57600080fd5b506104a46119a2565b34801561071257600080fd5b50610540610721366004616080565b6119a8565b34801561073257600080fd5b506104a4610741366004616080565b6119dd565b34801561075257600080fd5b50610644611a2e565b34801561076757600080fd5b506104cf611a33565b34801561077c57600080fd5b506104a4611a38565b34801561079157600080fd5b506107a56107a036600461618b565b611a3e565b6040516104b196959493929190616325565b3480156107c357600080fd5b506104f1611aa2565b3480156107d857600080fd5b50610644611aa8565b3480156107ed57600080fd5b50610644611aad565b34801561080257600080fd5b506104f1611ab2565b34801561081757600080fd5b506104a4611ab8565b34801561082c57600080fd5b50610644611abe565b34801561084157600080fd5b506104a4611ac3565b34801561085657600080fd5b506104cf611ac9565b34801561086b57600080fd5b5061048d61087a3660046161de565b611ace565b34801561088b57600080fd5b506104a4611b2f565b3480156108a057600080fd5b506104a4611b35565b3480156108b557600080fd5b506104a4611b3b565b3480156108ca57600080fd5b506104a46108d9366004616080565b611b41565b3480156108ea57600080fd5b5061048d611b81565b3480156108ff57600080fd5b50610644611c95565b34801561091457600080fd5b506104f1611c9a565b34801561092957600080fd5b506104a4611ca0565b34801561093e57600080fd5b506104a4611ca5565b34801561095357600080fd5b506104f1611caa565b34801561096857600080fd5b5061051e611cb0565b34801561097d57600080fd5b50610540611ccf565b34801561099257600080fd5b506104a4611cd8565b3480156109a757600080fd5b506104cf611a2e565b3480156109bc57600080fd5b5061048d6109cb36600461612f565b611ce1565b3480156109dc57600080fd5b506104a46109eb366004616080565b61258d565b3480156109fc57600080fd5b506104a461259f565b348015610a1157600080fd5b50610a1a6125ac565b6040516104b19190616367565b348015610a3357600080fd5b506104a4612698565b348015610a4857600080fd5b506104a4611aa8565b348015610a5d57600080fd5b506104f161269d565b348015610a7257600080fd5b506104a46126a3565b348015610a8757600080fd5b506104a46126a8565b348015610a9c57600080fd5b506104a46126e7565b348015610ab157600080fd5b506104a46126f3565b348015610ac657600080fd5b506104f16126f9565b348015610adb57600080fd5b506104a46126ff565b348015610af057600080fd5b5061048d612704565b348015610b0557600080fd5b506104a46128b3565b348015610b1a57600080fd5b5061048d610b29366004616080565b6128b9565b348015610b3a57600080fd5b506104cf6129c1565b61048d610b51366004616080565b6129c6565b348015610b6257600080fd5b506104a4612c4e565b348015610b7757600080fd5b506104f1612c54565b348015610b8c57600080fd5b50610644611ca0565b348015610ba157600080fd5b506104f1612c5a565b348015610bb657600080fd5b50610bca610bc536600461618b565b612c60565b6040516104b193929190616efa565b348015610be557600080fd5b506104f1612d22565b6000610bf933611b41565b9050600b8181548110610c0857fe5b600091825260209091206001601690920201015460ff16610c445760405162461bcd60e51b8152600401610c3b90616b9a565b60405180910390fd5b6000610c4e6126a8565b9050610c5b338383612d28565b505050565b60095481565b606481565b61200181565b60005460609060ff16610c965760405162461bcd60e51b8152600401610c3b9061662e565b3361200014610cb75760405162461bcd60e51b8152600401610c3b90616d79565b600b54610d7557610cc6615d6c565b60015460005b81811015610d7157600b8054600181018255600091909152835160008051602061714f833981519152601690920291820190815560208086015160008051602061718f8339815191528401805460ff1916911515919091179055604086015180518794610d4d9360008051602061716f833981519152909101920190615d9b565b506060820151610d639060038301906013615e15565b505050806001019050610ccc565b5050505b610d7d615e42565b6000610dbe85858080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612f1492505050565b9150915080610dda57610dd160646130d0565b92505050610ea2565b815160009060ff16610dff57610df883602001518460400151613131565b9050610e6e565b825160ff1660011415610e6a57826020015151600114610e445760008051602061712f833981519152604051610e3490616a81565b60405180910390a1506067610e65565b610df88360200151600081518110610e5857fe5b6020026020010151613d85565b610e6e565b5060655b63ffffffff8116610e935750506040805160008152602081019091529150610ea29050565b610e9c816130d0565b93505050505b9392505050565b60075460ff1681565b60035481565b606881565b334114610edc5760405162461bcd60e51b8152600401610c3b90616dc8565b6010544311610efd5760405162461bcd60e51b8152600401610c3b9061678a565b60005460ff16610f1f5760405162461bcd60e51b8152600401610c3b9061662e565b600f54610f37576032600f5561100231601155611237565b60006110023168056bc75e2d63100000811115610f6657610f5f81606463ffffffff613efc16565b9150610faf565b601154811115610fa857610f5f6064610f9c600f54610f9060115486613f3e90919063ffffffff16565b9063ffffffff613f8016565b9063ffffffff613efc16565b5050611237565b6040516309a99b4f60e41b815261100290639a99b4f090610fd6903090869060040161630c565b602060405180830381600087803b158015610ff057600080fd5b505af1158015611004573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102891906161a3565b6110023160115591508161103d575050611237565b6000805b8481101561106b5785858281811061105557fe5b9050602002013582019150806001019050611041565b508061107957505050611237565b6000806000805b8981101561122f578489898381811061109557fe5b905060200201358802816110a557fe5b0493508a8a828181106110b457fe5b90506020020160208101906110c99190616080565b6001600160a01b038116600090815260046020526040902054909350915081156111e55760006001808403815481106110fe57fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff161561116b57836001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d858660405161115e9190616ef1565b60405180910390a26111df565b60035461117e908663ffffffff613fba16565b6003908155810154611196908663ffffffff613fba16565b60038201556040516001600160a01b038516907fcb0aad6cf9cd03bdf6137e359f541c42f38b39f007cae8e89e88aa7d8c6617b2906111d6908890616ef1565b60405180910390a25b50611227565b826001600160a01b03167fb9c75cbbfde137c4281689580799ef5f52144e78858f776a5979b2b212137d858560405161121e9190616ef1565b60405180910390a25b600101611080565b505050505050505b5050436010555050565b60015460009082106112555750600061130b565b60006001600160a01b03166001838154811061126d57fe5b60009182526020909120600490910201546001600160a01b0316148061129d5750600854158061129d5750600a54155b806112ac575060085460095410155b806112bd57506112bb82611310565b155b806112e657506000600b83815481106112d257fe5b906000526020600020906016020160000154115b806112fa575060016112f66125ac565b5111155b156113075750600061130b565b5060015b919050565b60015460009082106113245750600061130b565b600b548210611361576001828154811061133a57fe5b9060005260206000209060040201600201601c9054906101000a900460ff1615905061130b565b6001828154811061136e57fe5b9060005260206000209060040201600201601c9054906101000a900460ff161580156113bb5750600b82815481106113a257fe5b600091825260209091206001601690920201015460ff16155b92915050565b33611001146113e25760405162461bcd60e51b8152600401610c3b90616e99565b600b546114a0576113f1615d6c565b60015460005b8181101561149c57600b8054600181018255600091909152835160008051602061714f833981519152601690920291820190815560208086015160008051602061718f8339815191528401805460ff19169115159190911790556040860151805187946114789360008051602061716f833981519152909101920190615d9b565b50606082015161148e9060038301906013615e15565b5050508060010190506113f7565b5050505b6001600160a01b038116600090815260046020526040902054806114c45750611517565b6001810390506000600b82815481106114d957fe5b600091825260209091206001601690920201015460ff1690506114fc8383613fdf565b80156115055750805b15610c5b576009805460001901905550505b50565b60015460609081906000805b8281101561156d576001818154811061153b57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611565576001909101905b600101611526565b5060608160405190808252806020026020018201604052801561159a578160200160208202803683370190505b5090506060826040519080825280602002602001820160405280156115d357816020015b60608152602001906001900390816115be5790505b50600b546000945090915084141561174e5760005b8481101561174857600181815481106115fd57fe5b9060005260206000209060040201600201601c9054906101000a900460ff16611740576001818154811061162d57fe5b600091825260209091206004909102015483516001600160a01b039091169084908690811061165857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600b818154811061168557fe5b600091825260209182902060026016909202018101805460408051601f60001961010060018616150201909316949094049182018590048502840185019052808352919290919083018282801561171d5780601f106116f25761010080835404028352916020019161171d565b820191906000526020600020905b81548152906001019060200180831161170057829003601f168201915b505050505082858151811061172e57fe5b60209081029190910101526001909301925b6001016115e8565b506117ea565b60005b848110156117e8576001818154811061176657fe5b9060005260206000209060040201600201601c9054906101000a900460ff166117e0576001818154811061179657fe5b600091825260209091206004909102015483516001600160a01b03909116908490869081106117c157fe5b6001600160a01b03909216602092830291909101909101526001909301925b600101611751565b505b909450925050505b9091565b61271081565b600181565b61100181565b60085481565b6102ca81565b600881565b600e54600c5460609182918061182c575060155b60606118366125ac565b9050606061184382614392565b90508282511161185a5790945092506117f2915050565b8383835103101561186c578282510393505b83156118a25760c8430461188883838388880360008a8a614500565b6118a08383838888038989038a8b8b8b510301614500565b505b6060836040519080825280602002602001820160405280156118ce578160200160208202803683370190505b50905060608460405190808252806020026020018201604052801561190757816020015b60608152602001906001900390816118f25790505b50905060005b858110156119885784818151811061192157fe5b602002602001015183828151811061193557fe5b60200260200101906001600160a01b031690816001600160a01b03168152505083818151811061196157fe5b602002602001015182828151811061197557fe5b602090810291909101015260010161190d565b509096509450505050509091565b60065481565b61200081565b600f5481565b6001600160a01b038116600090815260046020526040812054806119d057600091505061130b565b60001901610ea281611310565b6001600160a01b03811660009081526004602052604081205480611a0557600091505061130b565b600180820381548110611a1457fe5b906000526020600020906004020160030154915050919050565b600081565b606781565b60105481565b60018181548110611a4b57fe5b600091825260209091206004909102018054600182015460028301546003909301546001600160a01b0392831694509082169291821691600160a01b81046001600160401b031691600160e01b90910460ff169086565b61100581565b600281565b601081565b61100881565b6103e881565b600b81565b600c5481565b606681565b3361200014611aef5760405162461bcd60e51b8152600401610c3b90616d79565b7f41ce201247b6ceb957dcdb217d0b8acb50b9ea0e12af9af4f5e7f38902101605838383604051611b2293929190616f3a565b60405180910390a1505050565b60025481565b60115481565b600a5481565b6001600160a01b03811660009081526004602052604081205480611b775760405162461bcd60e51b8152600401610c3b90616d01565b6000190192915050565b600b54611c3f57611b90615d6c565b60015460005b81811015611c3b57600b8054600181018255600091909152835160008051602061714f833981519152601690920291820190815560208086015160008051602061718f8339815191528401805460ff1916911515919091179055604086015180518794611c179360008051602061716f833981519152909101920190615d9b565b506060820151611c2d9060038301906013615e15565b505050806001019050611b96565b5050505b600854611c4c5760036008555b600a54611c59576002600a555b6000611c6433611b41565b9050611c6f81611241565b611c8b5760405162461bcd60e51b8152600401610c3b90616a3e565b6115173382614657565b600981565b61100781565b600381565b60c881565b61100681565b604051806101e001604052806101ab8152602001616f846101ab913981565b60005460ff1681565b6402540be40081565b60005460ff16611d035760405162461bcd60e51b8152600401610c3b9061662e565b3361100714611d245760405162461bcd60e51b8152600401610c3b90616b07565b611d8e84848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080518082019091526013815272065787069726554696d655365636f6e6447617606c1b602082015291506146ef9050565b15611e2b5760208114611db35760405162461bcd60e51b8152600401610c3b90616cbb565b604080516020601f8401819004810282018101909252828152600091611df19185858083850183828082843760009201919091525061474892505050565b905060648110158015611e075750620186a08111155b611e235760405162461bcd60e51b8152600401610c3b906168e7565b60025561254a565b611e8b84848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260098152686275726e526174696f60b81b602082015291506146ef9050565b15611f275760208114611eb05760405162461bcd60e51b8152600401610c3b906164b4565b604080516020601f8401819004810282018101909252828152600091611eee9185858083850183828082843760009201919091525061474892505050565b9050612710811115611f125760405162461bcd60e51b8152600401610c3b906167cc565b6006556007805460ff1916600117905561254a565b611f9184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260138152726d61784e756d4f664d61696e7461696e696e6760681b602082015291506146ef9050565b1561202b5760208114611fb65760405162461bcd60e51b8152600401610c3b906164eb565b604080516020601f8401819004810282018101909252828152600091611ff49185858083850183828082843760009201919091525061474892505050565b600c5490915080612003575060155b8082106120225760405162461bcd60e51b8152600401610c3b9061683f565b5060085561254a565b61209484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61696e7461696e536c6173685363616c6560701b602082015291506146ef9050565b1561212d57602081146120b95760405162461bcd60e51b8152600401610c3b906165b4565b604080516020601f84018190048102820181019092528281526000916120f79185858083850183828082843760009201919091525061474892505050565b90506000811180156121095750600a81105b6121255760405162461bcd60e51b8152600401610c3b90616e15565b600a5561254a565b6121a184848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601981527f6d61784e756d4f66576f726b696e6743616e6469646174657300000000000000602082015291506146ef9050565b1561223057602081146121c65760405162461bcd60e51b8152600401610c3b90616568565b604080516020601f84018190048102820181019092528281526000916122049185858083850183828082843760009201919091525061474892505050565b9050600d548111156122285760405162461bcd60e51b8152600401610c3b9061695d565b600e5561254a565b61229984848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260128152716d61784e756d4f6643616e6469646174657360701b602082015291506146ef9050565b1561231b57602081146122be5760405162461bcd60e51b8152600401610c3b90616b55565b604080516020601f84018190048102820181019092528281526000916122fc9185858083850183828082843760009201919091525061474892505050565b600d819055600e5490915081101561231557600d54600e555b5061254a565b61237f84848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600d81526c6e756d4f66436162696e65747360981b602082015291506146ef9050565b1561242d57602081146123a45760405162461bcd60e51b8152600401610c3b906165f9565b604080516020601f84018190048102820181019092528281526000916123e29185858083850183828082843760009201919091525061474892505050565b9050600081116124045760405162461bcd60e51b8152600401610c3b9061669c565b60298111156124255760405162461bcd60e51b8152600401610c3b906166e4565b600c5561254a565b61249784848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601381527266696e616c697479526577617264526174696f60681b602082015291506146ef9050565b1561253257602081146124bc5760405162461bcd60e51b8152600401610c3b90616c3e565b604080516020601f84018190048102820181019092528281526000916124fa9185858083850183828082843760009201919091525061474892505050565b90506001811015801561250e575060648111155b61252a5760405162461bcd60e51b8152600401610c3b906169cc565b600f5561254a565b60405162461bcd60e51b8152600401610c3b90616e72565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a8484848460405161257f9493929190616482565b60405180910390a150505050565b60046020526000908152604090205481565b68056bc75e2d6310000081565b6001546060906000805b828110156125db576125c781611310565b156125d3578160010191505b6001016125b6565b50606081604051908082528060200260200182016040528015612608578160200160208202803683370190505b5090506000915060005b8381101561268f5761262381611310565b15612687576001818154811061263557fe5b600091825260209091206004909102015482516001600160a01b039091169083908590811061266057fe5b60200260200101906001600160a01b031690816001600160a01b0316815250508260010192505b600101612612565b50925050505b90565b601581565b61100281565b603281565b60006126b26125ac565b519050600080600c54116126c75760156126cb565b600c545b9050808211156126d9578091505b816126e357600191505b5090565b67016345785d8a000081565b60055481565b61100381565b602981565b60005460ff16156127275760405162461bcd60e51b8152600401610c3b90616c07565b61272f615e42565b6000612755604051806101e001604052806101ab8152602001616f846101ab9139612f14565b91509150806127765760405162461bcd60e51b8152600401610c3b90616d38565b60005b82602001515181101561289b5760018360200151828151811061279857fe5b60209081029190910181015182546001818101855560009485528385208351600493840290910180546001600160a01b039283166001600160a01b03199182161782558587015182850180549185169183169190911790556040860151600283018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b199590981692909516919091179290921694909417161790915560a09093015160039093019290925591860151805191850193918590811061286e57fe5b602090810291909101810151516001600160a01b0316825281019190915260400160002055600101612779565b50506103e8600255506000805460ff19166001179055565b600d5481565b33611001146128da5760405162461bcd60e51b8152600401610c3b90616e99565b600b54612998576128e9615d6c565b60015460005b8181101561299457600b8054600181018255600091909152835160008051602061714f833981519152601690920291820190815560208086015160008051602061718f8339815191528401805460ff19169115159190911790556040860151805187946129709360008051602061716f833981519152909101920190615d9b565b5060608201516129869060038301906013615e15565b5050508060010190506128ef565b5050505b60006129a38261474d565b90506129ae81611241565b156129bd576129bd8282614657565b5050565b606581565b3341146129e55760405162461bcd60e51b8152600401610c3b90616dc8565b60005460ff16612a075760405162461bcd60e51b8152600401610c3b9061662e565b60003411612a275760405162461bcd60e51b8152600401610c3b9061692e565b6001600160a01b0381166000908152600460205260409020546007543491906103e89060ff1615612a5757506006545b600083118015612a675750600081115b15612b08576000612a84612710610f9c868563ffffffff613f8016565b90508015612b065760405161dead9082156108fc029083906000818181858888f19350505050158015612abb573d6000803e3d6000fd5b507f627059660ea01c4733a328effb2294d2f86905bf806da763a89cee254de8bee581604051612aeb9190616ef1565b60405180910390a1612b03848263ffffffff613f3e16565b93505b505b8115612c06576000600180840381548110612b1f57fe5b9060005260206000209060040201905080600201601c9054906101000a900460ff1615612b8c57846001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b485604051612b7f9190616ef1565b60405180910390a2612c00565b600354612b9f908563ffffffff613fba16565b6003908155810154612bb7908563ffffffff613fba16565b60038201556040516001600160a01b038616907f93a090ecc682c002995fad3c85b30c5651d7fd29b0be5da9d784a3302aedc05590612bf7908790616ef1565b60405180910390a25b50612c48565b836001600160a01b03167ff177e5d6c5764d79c32883ed824111d9b13f5668cf6ab1cc12dd36791dd955b484604051612c3f9190616ef1565b60405180910390a25b50505050565b600e5481565b61100081565b61dead81565b600b8181548110612c6d57fe5b6000918252602091829020601691909102018054600180830154600280850180546040805161010096831615969096026000190190911692909204601f810188900488028501880190925281845293965060ff90911694919291830182828015612d185780601f10612ced57610100808354040283529160200191612d18565b820191906000526020600020905b815481529060010190602001808311612cfb57829003601f168201915b5050505050905083565b61100481565b6000600a5460001480612d39575081155b80612d445750600954155b15612d5157506000610ea2565b60096000815460019003919050819055506000612d9c600a54610f9c85610f9c600b8981548110612d7e57fe5b6000918252602090912060169091020154439063ffffffff613f3e16565b90506000600b8581548110612dad57fe5b906000526020600020906016020160010160006101000a81548160ff0219169083151502179055506000806110016001600160a01b0316638256ace66040518163ffffffff1660e01b8152600401604080518083038186803b158015612e1257600080fd5b505afa158015612e26573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612e4a91906161bb565b9150915060009350808310612ec457612e638787613fdf565b506040516305bfb49960e41b815261100190635bfb499090612e89908a906004016162f8565b600060405180830381600087803b158015612ea357600080fd5b505af1158015612eb7573d6000803e3d6000fd5b5050505060019350612ed6565b818310612ed657612ed48761474d565b505b6040516001600160a01b038816907fb9d38178dc641ff1817967a63c9078cbcd955a9f1fcd75e0e3636de615d44d3b90600090a25050509392505050565b612f1c615e42565b6000612f26615e42565b612f2e615e66565b612f3f612f3a866148f0565b614915565b90506000805b612f4e8361495f565b156130c25780612f7357612f69612f6484614980565b6149ce565b60ff1684526130ba565b80600114156130b5576060612f8f612f8a85614980565b614a4e565b90508051604051908082528060200260200182016040528015612fcc57816020015b612fb9615e86565b815260200190600190039081612fb15790505b508560200181905250805160405190808252806020026020018201604052801561300a57816020015b6060815260200190600190039081612ff55790505b50604086015260005b81518110156130aa57613024615e86565b6060600061304485858151811061303757fe5b6020026020010151614b1f565b92509250925080613064578860009a509a505050505050505050506130cb565b828960200151858151811061307557fe5b6020026020010181905250818960400151858151811061309157fe5b6020026020010181905250505050806001019050613013565b5060019250506130ba565b6130c2565b600101612f45565b50919350909150505b915091565b604080516001808252818301909252606091829190816020015b60608152602001906001900390816130ea5790505090506131108363ffffffff16614c39565b8160008151811061311d57fe5b6020026020010181905250610ea281614c4c565b60006029835111156131685760008051602061712f83398151915260405161315890616741565b60405180910390a15060666113bb565b60005b83518110156132065760005b818110156131fd5784818151811061318b57fe5b6020026020010151600001516001600160a01b03168583815181106131ac57fe5b6020026020010151600001516001600160a01b031614156131f55760008051602061712f8339815191526040516131e29061689c565b60405180910390a16066925050506113bb565b600101613177565b5060010161316b565b506060806132148585614cd6565b60015491935091506000908190815b818110156132995767016345785d8a00006001828154811061324157fe5b9060005260206000209060040201600301541061326357836001019350613291565b60006001828154811061327257fe5b9060005260206000209060040201600301541115613291578260010192505b600101613223565b506060836040519080825280602002602001820160405280156132c6578160200160208202803683370190505b5090506060846040519080825280602002602001820160405280156132f5578160200160208202803683370190505b509050606085604051908082528060200260200182016040528015613324578160200160208202803683370190505b509050606086604051908082528060200260200182016040528015613353578160200160208202803683370190505b5090506000606087604051908082528060200260200182016040528015613384578160200160208202803683370190505b5090506060886040519080825280602002602001820160405280156133b3578160200160208202803683370190505b509050600099506000985060006110046001600160a01b031663149d14d96040518163ffffffff1660e01b815260040160206040518083038186803b1580156133fb57600080fd5b505afa15801561340f573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061343391906161a3565b905067016345785d8a000081111561347e5760008051602061712f83398151915260405161346090616bc6565b60405180910390a160689d50505050505050505050505050506113bb565b60005b898110156136ef5767016345785d8a00006001828154811061349f57fe5b9060005260206000209060040201600301541061362457600181815481106134c357fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316898d815181106134f457fe5b60200260200101906001600160a01b031690816001600160a01b03168152505060006402540be4006001838154811061352957fe5b9060005260206000209060040201600301548161354257fe5b066001838154811061355057fe5b9060005260206000209060040201600301540390506135788382613f3e90919063ffffffff16565b898e8151811061358457fe5b6020026020010181815250506001828154811061359d57fe5b906000526020600020906004020160020160009054906101000a90046001600160a01b0316878e815181106135ce57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505081888e815181106135fb57fe5b6020908102919091010152613616868263ffffffff613fba16565b95508c6001019c50506136e7565b60006001828154811061363357fe5b90600052602060002090600402016003015411156136e7576001818154811061365857fe5b906000526020600020906004020160010160009054906101000a90046001600160a01b0316848c8151811061368957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050600181815481106136b657fe5b906000526020600020906004020160030154838c815181106136d457fe5b6020026020010181815250508a6001019a505b600101613481565b5060008415613965576002546040516303702b2960e51b815261100491636e056520918891613729918e918e918d914201906004016163ea565b6020604051808303818588803b15801561374257600080fd5b505af193505050508015613773575060408051601f3d908101601f191682019092526137709181019061610f565b60015b6138ea576040516000815260443d101561378f5750600061382a565b60046000803e60005160e01c6308c379a081146137b057600091505061382a565b60043d036004833e81513d60248201116001600160401b03821117156137db5760009250505061382a565b80830180516001600160401b038111156137fc57600094505050505061382a565b8060208301013d860181111561381a5760009550505050505061382a565b601f01601f191660405250925050505b806138355750613877565b60019150857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28082604051613869919061646f565b60405180910390a2506138e5565b3d8080156138a1576040519150601f19603f3d011682016040523d82523d6000602084013e6138a6565b606091505b5060019150857fbfa884552dd8921b6ce90bfe906952ae5b3b29be0cc1a951d4f62697635a3a45826040516138db919061646f565b60405180910390a2505b613965565b801561392c577fa217d08e65f80c73121cd9db834d81652d544bfbf452f6d04922b16c90a37b708660405161391f9190616ef1565b60405180910390a1613963565b857fa7cdeed7d0db45e3219a6e5d60838824c16f1d39991fcfe3f963029c844bf28060405161395a90616531565b60405180910390a25b505b8015613b1b5760005b8751811015613b1957600088828151811061398557fe5b6020026020010151905060006001828154811061399e57fe5b60009182526020909120600160049092020181015481546001600160a01b03909116916108fc91859081106139cf57fe5b9060005260206000209060040201600301549081150290604051600060405180830381858888f1935050505090508015613a8b5760018281548110613a1057fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d9185908110613a5f57fe5b906000526020600020906004020160030154604051613a7e9190616ef1565b60405180910390a2613b0f565b60018281548110613a9857fe5b60009182526020909120600160049092020181015481546001600160a01b03909116917f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d9185908110613ae757fe5b906000526020600020906004020160030154604051613b069190616ef1565b60405180910390a25b505060010161396e565b505b835115613c655760005b8451811015613c63576000858281518110613b3c57fe5b60200260200101516001600160a01b03166108fc868481518110613b5c57fe5b60200260200101519081150290604051600060405180830381858888f1935050505090508015613bf257858281518110613b9257fe5b60200260200101516001600160a01b03167f6c61d60f69a7beb3e1c80db7f39f37b208537cbb19da3174511b477812b2fc7d868481518110613bd057fe5b6020026020010151604051613be59190616ef1565b60405180910390a2613c5a565b858281518110613bfe57fe5b60200260200101516001600160a01b03167f25d0ce7d2f0cec669a8c17efe49d195c13455bb8872b65fa610ac7f53fe4ca7d868481518110613c3c57fe5b6020026020010151604051613c519190616ef1565b60405180910390a25b50600101613b25565b505b5050505050505050505050506000471115613ce1577f6ecc855f9440a9282c90913bbc91619fd44f5ec0b462af28d127b116f130aa4d47604051613ca99190616ef1565b60405180910390a1604051611002904780156108fc02916000818181858888f19350505050158015613cdf573d6000803e3d6000fd5b505b60006003819055600555815115613cfc57613cfc8282614f0f565b6110016001600160a01b031663fc4333cd6040518163ffffffff1660e01b8152600401600060405180830381600087803b158015613d3957600080fd5b505af1158015613d4d573d6000803e3d6000fd5b50506040517fedd8d7296956dd970ab4de3f2fc03be2b0ffc615d20cd4c72c6e44f928630ebf925060009150a1506000949350505050565b80516001600160a01b0316600090815260046020526040812054801580613dd65750600180820381548110613db657fe5b9060005260206000209060040201600201601c9054906101000a900460ff165b15613e1c5782516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a2600091505061130b565b600154600554600019820111801590613e725784516040516001600160a01b03909116907fe209c46bebf57cf265d5d9009a00870e256d9150f3ed5281ab9d9eb3cec6e4be90600090a26000935050505061130b565b600580546001908101909155805481906000198601908110613e9057fe5b6000918252602082206002600490920201018054921515600160e01b0260ff60e01b199093169290921790915585516040516001600160a01b03909116917ff226e7d8f547ff903d9d419cf5f54e0d7d07efa9584135a53a057c5f1f27f49a91a2506000949350505050565b6000610ea283836040518060400160405280601a81526020017f536166654d6174683a206469766973696f6e206279207a65726f0000000000008152506156ee565b6000610ea283836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f770000815250615725565b600082613f8f575060006113bb565b82820282848281613f9c57fe5b0414610ea25760405162461bcd60e51b8152600401610c3b90616ac6565b600082820183811015610ea25760405162461bcd60e51b8152600401610c3b90616665565b60008060018381548110613fef57fe5b906000526020600020906004020160030154905060006001808054905003905060016140196125ac565b511161404e5760006001858154811061402e57fe5b9060005260206000209060040201600301819055506000925050506113bb565b846001600160a01b03167f3b6f9ef90462b512a1293ecec018670bf7b7f1876fb727590a8a6d7643130a70836040516140879190616ef1565b60405180910390a26001600160a01b038516600090815260046020526040812055835b6001546000190181101561427457600181600101815481106140c857fe5b9060005260206000209060040201600182815481106140e357fe5b60009182526020909120825460049092020180546001600160a01b03199081166001600160a01b0393841617825560018085015481840180548416918616919091179055600280860180549185018054909416919095161780835584546001600160401b03600160a01b91829004160267ffffffffffffffff60a01b1990911617808355935460ff600160e01b918290041615150260ff60e01b19909416939093179055600392830154920191909155600b8054909183019081106141a457fe5b9060005260206000209060160201600b82815481106141bf57fe5b600091825260209091208254601690920201908155600180830154818301805460ff909216151560ff1990921691909117905560028084018054614216938386019390821615610100026000190190911604615ebb565b5061422960038281019084016013615f30565b5090505080600101600460006001848154811061424257fe5b600091825260208083206004909202909101546001600160a01b031683528201929092526040019020556001016140aa565b50600180548061428057fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b8054806142d357fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906143056002830182615f5a565b614313600383016000615f9e565b50509055600081838161432257fe5b04905080156143865760015460005b8181101561438357826001828154811061434757fe5b906000526020600020906004020160030154016001828154811061436757fe5b6000918252602090912060036004909202010155600101614331565b50505b50600195945050505050565b6001548151604080518281526020808402820101909152606092919083908280156143d157816020015b60608152602001906001900390816143bc5790505b50600b5490915083146143e857925061130b915050565b60005b828110156144f757600b60016004600089858151811061440757fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002054038154811061443b57fe5b600091825260209182902060026016909202018101805460408051601f6000196101006001861615020190931694909404918201859004850284018501905280835291929091908301828280156144d35780601f106144a8576101008083540402835291602001916144d3565b820191906000526020600020905b8154815290600101906020018083116144b657829003601f168201915b50505050508282815181106144e457fe5b60209081029190910101526001016143eb565b50949350505050565b60005b8281101561464d57600082878388016040516020016145239291906162ea565b6040516020818303038152906040528051906020012060001c8161454357fe5b06905080850182870114614644576000898388018151811061456157fe5b602002602001015190506060898489018151811061457b57fe5b602002602001015190508a8388018151811061459357fe5b60200260200101518b858a01815181106145a957fe5b60200260200101906001600160a01b031690816001600160a01b031681525050818b848901815181106145d857fe5b60200260200101906001600160a01b031690816001600160a01b031681525050898388018151811061460657fe5b60200260200101518a858a018151811061461c57fe5b6020026020010181905250808a8489018151811061463657fe5b602002602001018190525050505b50600101614503565b5050505050505050565b600980546001908101909155600b80548390811061467157fe5b906000526020600020906016020160010160006101000a81548160ff02191690831515021790555043600b82815481106146a757fe5b600091825260208220601690910201919091556040516001600160a01b038416917ff62981a567ec3cec866c6fa93c55bcdf841d6292d18b8d522ececa769375d82d91a25050565b60008160405160200161470291906162ce565b604051602081830303815290604052805190602001208360405160200161472991906162ce565b6040516020818303038152906040528051906020012014905092915050565b015190565b6001600160a01b038116600090815260046020526040812054806147765750600019905061130b565b60018103905060006001828154811061478b57fe5b90600052602060002090600402016003015490506000600183815481106147ae57fe5b6000918252602090912060036004909202010155600154604051600019909101906001600160a01b038616907f8cd4e147d8af98a9e3b6724021b8bf6aed2e5dac71c38f2dce8161b82585b25d90614807908590616ef1565b60405180910390a28061481f5782935050505061130b565b600081838161482a57fe5b04905080156148e65760005b8481101561488857816001828154811061484c57fe5b906000526020600020906004020160030154016001828154811061486c57fe5b6000918252602090912060036004909202010155600101614836565b50600180549085015b818110156148e35782600182815481106148a757fe5b90600052602060002090600402016003015401600182815481106148c757fe5b6000918252602090912060036004909202010155600101614891565b50505b5091949350505050565b6148f8615fad565b506040805180820190915281518152602082810190820152919050565b61491d615e66565b61492682615751565b61492f57600080fd5b600061493e836020015161578b565b60208085015160408051808201909152868152920190820152915050919050565b6000614969615fad565b505080518051602091820151919092015191011190565b614988615fad565b6149918261495f565b61499a57600080fd5b602082015160006149aa826157ee565b80830160209586015260408051808201909152908152938401919091525090919050565b8051600090158015906149e357508151602110155b6149ec57600080fd5b60006149fb836020015161578b565b90508083600001511015614a215760405162461bcd60e51b8152600401610c3b90616c84565b8251602080850151830180519284900392918310156144f757506020919091036101000a90049392505050565b6060614a5982615751565b614a6257600080fd5b6000614a6d836158cf565b9050606081604051908082528060200260200182016040528015614aab57816020015b614a98615fad565b815260200190600190039081614a905790505b5090506000614abd856020015161578b565b60208601510190506000805b84811015614b1457614ada836157ee565b9150604051806040016040528083815260200184815250848281518110614afd57fe5b602090810291909101015291810191600101614ac9565b509195945050505050565b614b27615e86565b60606000614b33615e86565b6060614b3d615e66565b614b4687614915565b90506000805b614b558361495f565b15614c2a5780614b8057614b70614b6b84614980565b61592b565b6001600160a01b03168552614c22565b8060011415614ba857614b95614b6b84614980565b6001600160a01b03166020860152614c22565b8060021415614bd057614bbd614b6b84614980565b6001600160a01b03166040860152614c22565b8060031415614bfc57614be5612f6484614980565b6001600160401b0316606086015260019150614c22565b8060041415614c1d57614c16614c1184614980565b615945565b9350614c22565b614c2a565b600101614b4c565b50929791965091945092505050565b60606113bb614c47836159b5565b615a9b565b6060815160001415614c6d575060408051600081526020810190915261130b565b606082600081518110614c7c57fe5b602002602001015190506000600190505b8351811015614cbd57614cb382858381518110614ca657fe5b6020026020010151615aed565b9150600101614c8d565b50610ea2614cd0825160c060ff16615b6a565b82615aed565b606080600080808080614ce76126a8565b6001549091505b8015614df557600181039250600b8381548110614d0757fe5b600091825260209091206001601690920201015460ff16614d2757614dec565b60018381548110614d3457fe5b60009182526020909120600490910201546001600160a01b03169450614d5b858484612d28565b9350831580614d6e575060018a51038610155b15614d7857614dec565b60005b8a51811015614dea57856001600160a01b03168b8281518110614d9a57fe5b6020026020010151600001516001600160a01b03161415614de25760018b8281518110614dc357fe5b6020908102919091010151901515608090910152600190960195614dea565b600101614d7b565b505b60001901614cee565b5084895103604051908082528060200260200182016040528015614e3357816020015b614e20615e86565b815260200190600190039081614e185790505b50965084895103604051908082528060200260200182016040528015614e6d57816020015b6060815260200190600190039081614e585790505b5095506000915060005b8951811015614f0157898181518110614e8c57fe5b602002602001015160800151614ef957898181518110614ea857fe5b6020026020010151888481518110614ebc57fe5b6020026020010181905250888181518110614ed357fe5b6020026020010151878481518110614ee757fe5b60200260200101819052508260010192505b600101614e77565b5050505050505b9250929050565b600154825160005b8281101561502c576001614f29615e86565b60018381548110614f3657fe5b600091825260208083206040805160c08101825260049490940290910180546001600160a01b0390811685526001820154811693850193909352600281015492831691840191909152600160a01b82046001600160401b03166060840152600160e01b90910460ff16151560808301526003015460a082015291505b8481101561500057878181518110614fc657fe5b6020026020010151600001516001600160a01b031682600001516001600160a01b03161415614ff85760009250615000565b600101614fb2565b5081156150225780516001600160a01b03166000908152600460205260408120555b5050600101614f17565b50808211156150eb57805b828110156150e957600180548061504a57fe5b60008281526020812060046000199093019283020180546001600160a01b0319908116825560018201805490911690556002810180546001600160e81b0319169055600301559055600b80548061509d57fe5b60008281526020812060166000199093019283020181815560018101805460ff19169055906150cf6002830182615f5a565b6150dd600383016000615f9e565b50509055600101615037565b505b60008183106150fa57816150fc565b825b905060005b818110156154a0576151ae86828151811061511857fe5b60200260200101516001838154811061512d57fe5b60009182526020918290206040805160c08101825260049390930290910180546001600160a01b0390811684526001820154811694840194909452600281015493841691830191909152600160a01b83046001600160401b03166060830152600160e01b90920460ff161515608082015260039091015460a0820152615c3c565b6153625780600101600460008884815181106151c657fe5b6020026020010151600001516001600160a01b03166001600160a01b031681526020019081526020016000208190555085818151811061520257fe5b60200260200101516001828154811061521757fe5b6000918252602091829020835160049092020180546001600160a01b039283166001600160a01b0319918216178255928401516001820180549184169185169190911790556040840151600282018054606087015160808801511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909716929097169190911792909216939093171692909217905560a09091015160039091015584518590829081106152d257fe5b6020026020010151600b82815481106152e757fe5b9060005260206000209060160201600201908051906020019061530b929190615d9b565b506000600b828154811061531b57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b80548390811061534c57fe5b6000918252602090912060169091020155615498565b61542885828151811061537157fe5b6020026020010151600b838154811061538657fe5b600091825260209182902060026016909202018101805460408051601f60001961010060018616150201909316949094049182018590048502840185019052808352919290919083018282801561541e5780601f106153f35761010080835404028352916020019161541e565b820191906000526020600020905b81548152906001019060200180831161540157829003601f168201915b5050505050615cbd565b6154735784818151811061543857fe5b6020026020010151600b828154811061544d57fe5b90600052602060002090601602016002019080519060200190615471929190615d9b565b505b60006001828154811061548257fe5b9060005260206000209060040201600301819055505b600101615101565b5082821115615678576154b1615d6c565b835b83811015615675578581815181106154c757fe5b6020026020010151826040018190525060018782815181106154e557fe5b6020908102919091018101518254600181810185556000948552838520835160049093020180546001600160a01b039384166001600160a01b0319918216178255848601518284018054918616918316919091179055604080860151600284018054606089015160808a01511515600160e01b0260ff60e01b196001600160401b03909216600160a01b0267ffffffffffffffff60a01b1995909a1692909616919091179290921696909617169190911790935560a090930151600390930192909255600b805492830181559093528451601690910260008051602061714f83398151915281019182558583015160008051602061718f8339815191528201805491151560ff199092169190911790559285015180518694929361561b9360008051602061716f83398151915201920190615d9b565b5060608201516156319060038301906013615e15565b505050806001016004600089848151811061564857fe5b602090810291909101810151516001600160a01b03168252810191909152604001600020556001016154b3565b50505b6000600981905560015493505b838110156156e6576000600b828154811061569c57fe5b60009182526020822060169190910201600101805460ff191692151592909217909155600b8054839081106156cd57fe5b6000918252602090912060169091020155600101615685565b505050505050565b6000818361570f5760405162461bcd60e51b8152600401610c3b919061646f565b50600083858161571b57fe5b0495945050505050565b600081848411156157495760405162461bcd60e51b8152600401610c3b919061646f565b505050900390565b80516000906157625750600061130b565b6020820151805160001a9060c08210156157815760009250505061130b565b5060019392505050565b8051600090811a60808110156157a557600091505061130b565b60b88110806157c0575060c081108015906157c0575060f881105b156157cf57600191505061130b565b60c08110156157e35760b51901905061130b565b60f51901905061130b565b80516000908190811a608081101561580957600191506158c8565b60b881101561581e57607e19810191506158c8565b60c081101561586f57600060b78203600186019550806020036101000a8651049150600181018201935050808310156158695760405162461bcd60e51b8152600401610c3b90616a13565b506158c8565b60f88110156158845760be19810191506158c8565b600060f78203600186019550806020036101000a8651049150600181018201935050808310156158c65760405162461bcd60e51b8152600401610c3b90616a13565b505b5092915050565b80516000906158e05750600061130b565b600080905060006158f4846020015161578b565b602085015185519181019250015b8082101561592257615913826157ee565b82019150826001019250615902565b50909392505050565b805160009060151461593c57600080fd5b6113bb826149ce565b805160609061595357600080fd5b6000615962836020015161578b565b83516040805191839003808352601f19601f8201168301602001909152919250606090828015615999576020820181803683370190505b50905060008160200190506144f7848760200151018285615d21565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166159f957506018615a1d565b6fffffffffffffffffffffffffffffffff198416615a1957506010615a1d565b5060005b6020811015615a5357818181518110615a3257fe5b01602001516001600160f81b03191615615a4b57615a53565b600101615a1d565b60008160200390506060816040519080825280601f01601f191660200182016040528015615a88576020820181803683370190505b5080830196909652508452509192915050565b606081516001148015615acd5750607f60f81b82600081518110615abb57fe5b01602001516001600160f81b03191611155b15615ad957508061130b565b6113bb615aeb8351608060ff16615b6a565b835b6060806040519050835180825260208201818101602087015b81831015615b1e578051835260209283019201615b06565b50855184518101855292509050808201602086015b81831015615b4b578051835260209283019201615b33565b508651929092011591909101601f01601f191660405250905092915050565b6060680100000000000000008310615b945760405162461bcd60e51b8152600401610c3b90616817565b60408051600180825281830190925260609160208201818036833701905050905060378411615bee5782840160f81b81600081518110615bd057fe5b60200101906001600160f81b031916908160001a90535090506113bb565b6060615bf9856159b5565b90508381510160370160f81b82600081518110615c1257fe5b60200101906001600160f81b031916908160001a905350615c338282615aed565b95945050505050565b805182516000916001600160a01b039182169116148015615c76575081602001516001600160a01b031683602001516001600160a01b0316145b8015615c9b575081604001516001600160a01b031683604001516001600160a01b0316145b8015610ea25750506060908101519101516001600160401b0390811691161490565b815181516000916001918114808314615cd95760009250615d17565b600160208701838101602088015b600284838510011415615d12578051835114615d065760009650600093505b60209283019201615ce7565b505050505b5090949350505050565b80615d2b57610c5b565b5b60208110615d4b578251825260209283019290910190601f1901615d2c565b915181516020939093036101000a6000190180199091169216919091179052565b60405180608001604052806000815260200160001515815260200160608152602001615d96615fc7565b905290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615ddc57805160ff1916838001178555615e09565b82800160010185558215615e09579182015b82811115615e09578251825591602001919060010190615dee565b506126e3929150615fe6565b8260138101928215615e095791602002820182811115615e09578251825591602001919060010190615dee565b6040518060600160405280600060ff16815260200160608152602001606081525090565b6040518060400160405280615e79615fad565b8152602001600081525090565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10615ef45780548555615e09565b82800160010185558215615e0957600052602060002091601f016020900482015b82811115615e09578254825591600101919060010190615f15565b8260138101928215615e095791820182811115615e09578254825591600101919060010190615f15565b50805460018160011615610100020316600290046000825580601f10615f805750611517565b601f0160209004906000526020600020908101906115179190615fe6565b50611517906013810190615fe6565b604051806040016040528060008152602001600081525090565b6040518061026001604052806013906020820280368337509192915050565b61269591905b808211156126e35760008155600101615fec565b60008083601f840112616011578182fd5b5081356001600160401b03811115616027578182fd5b6020830191508360208083028501011115614f0857600080fd5b60008083601f840112616052578182fd5b5081356001600160401b03811115616068578182fd5b602083019150836020828501011115614f0857600080fd5b600060208284031215616091578081fd5b81356001600160a01b0381168114610ea2578182fd5b600080600080604085870312156160bc578283fd5b84356001600160401b03808211156160d2578485fd5b6160de88838901616000565b909650945060208701359150808211156160f6578384fd5b5061610387828801616000565b95989497509550505050565b600060208284031215616120578081fd5b81518015158114610ea2578182fd5b60008060008060408587031215616144578384fd5b84356001600160401b038082111561615a578586fd5b61616688838901616041565b9096509450602087013591508082111561617e578384fd5b5061610387828801616041565b60006020828403121561619c578081fd5b5035919050565b6000602082840312156161b4578081fd5b5051919050565b600080604083850312156161cd578182fd5b505080516020909101519092909150565b6000806000604084860312156161f2578283fd5b833560ff81168114616202578384fd5b925060208401356001600160401b0381111561621c578283fd5b61622886828701616041565b9497909650939450505050565b6000815180845260208085019450808401835b8381101561626d5781516001600160a01b031687529582019590820190600101616248565b509495945050505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b600081518084526162ba816020860160208601616f57565b601f01601f19169290920160200192915050565b600082516162e0818460208701616f57565b9190910192915050565b918252602082015260400190565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b03968716815294861660208601529290941660408401526001600160401b03166060830152911515608082015260a081019190915260c00190565b600060208252610ea26020830184616235565b60006040825261638d6040830185616235565b602083820381850152818551808452828401915082838202850101838801865b838110156163db57601f198784030185526163c98383516162a2565b948601949250908501906001016163ad565b50909998505050505050505050565b6000608082526163fd6080830187616235565b828103602084810191909152865180835287820192820190845b8181101561643357845183529383019391830191600101616417565b505084810360408601526164478188616235565b93505050506001600160401b038316606083015295945050505050565b901515815260200190565b600060208252610ea260208301846162a2565b600060408252616496604083018688616278565b82810360208401526164a9818587616278565b979650505050505050565b6020808252601c908201527f6c656e677468206f66206275726e526174696f206d69736d6174636800000000604082015260600190565b60208082526026908201527f6c656e677468206f66206d61784e756d4f664d61696e7461696e696e67206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601b908201527f6261746368207472616e736665722072657475726e2066616c73650000000000604082015260600190565b6020808252602c908201527f6c656e677468206f66206d61784e756d4f66576f726b696e6743616e6469646160408201526b0e8cae640dad2e6dac2e8c6d60a31b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61696e7461696e536c6173685363616c65206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252818101527f6c656e677468206f66206e756d4f66436162696e657473206d69736d61746368604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526028908201527f746865206e756d4f66436162696e657473206d75737420626520677265617465604082015267072207468616e20360c41b606082015260800190565b60208082526039908201527f746865206e756d4f66436162696e657473206d757374206265206c657373207460408201527f68616e204d41585f4e554d5f4f465f56414c494441544f525300000000000000606082015260800190565b60208082526029908201527f746865206e756d626572206f662076616c696461746f727320657863656564206040820152681d1a19481b1a5b5a5d60ba1b606082015260800190565b60208082526022908201527f63616e206e6f7420646f207468697320747769636520696e206f6e6520626c6f604082015261636b60f01b606082015260800190565b6020808252602b908201527f746865206275726e526174696f206d757374206265206e6f206772656174657260408201526a0207468616e2031303030360ac1b606082015260800190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526037908201527f746865206d61784e756d4f664d61696e7461696e696e67206d7573742062652060408201527f6c657373207468616e206e756d4f66436162696e657473000000000000000000606082015260800190565b6020808252602b908201527f6475706c696361746520636f6e73656e7375732061646472657373206f66207660408201526a185b1a59185d1bdc94d95d60aa1b606082015260800190565b60208082526027908201527f7468652065787069726554696d655365636f6e64476170206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601590820152746465706f7369742076616c7565206973207a65726f60581b604082015260600190565b60208082526049908201527f746865206d61784e756d4f66576f726b696e6743616e64696461746573206d7560408201527f7374206265206e6f742067726561746572207468616e206d61784e756d4f6643606082015268616e6469646174657360b81b608082015260a00190565b60208082526027908201527f7468652066696e616c697479526577617264526174696f206973206f7574206f604082015266662072616e676560c81b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b60208082526023908201527f63616e206e6f7420656e7465722054656d706f72617279204d61696e74656e616040820152626e636560e81b606082015260800190565b60208082526025908201527f6c656e677468206f66206a61696c2076616c696461746f7273206d757374206260408201526465206f6e6560d81b606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f6040820152607760f81b606082015260800190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526025908201527f6c656e677468206f66206d61784e756d4f6643616e64696461746573206d69736040820152640dac2e8c6d60db1b606082015260800190565b6020808252601290820152716e6f7420696e206d61696e74656e616e636560701b604082015260600190565b60208082526021908201527f666565206973206c6172676572207468616e2044555354595f494e434f4d494e6040820152604760f81b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662066696e616c697479526577617264526174696f206d696040820152650e6dac2e8c6d60d31b606082015260800190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526026908201527f6c656e677468206f662065787069726554696d655365636f6e64476170206d696040820152650e6dac2e8c6d60d31b606082015260800190565b60208082526017908201527f6f6e6c792063757272656e742076616c696461746f7273000000000000000000604082015260600190565b60208082526021908201527f6661696c656420746f20706172736520696e69742076616c696461746f7253656040820152601d60fa1b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252603e908201527f746865206d61696e7461696e536c6173685363616c65206d757374206265206760408201527f726561746572207468616e203020616e64206c657373207468616e2031300000606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b60208082526029908201527f746865206d6573736167652073656e646572206d75737420626520736c6173686040820152680818dbdb9d1c9858dd60ba1b606082015260800190565b61ffff91909116815260200190565b90815260200190565b6000848252831515602083015260606040830152615c3360608301846162a2565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff8516825260406020830152615c33604083018486616278565b60005b83811015616f72578181015183820152602001616f5a565b83811115612c48575050600091015256fef901a880f901a4f844941284214b9b9c85549ab3d2b972df0deef66ac2c9946ddf42a51534fc98d0c0a3b42c963cace8441ddf946ddf42a51534fc98d0c0a3b42c963cace8441ddf8410000000f84494a2959d3f95eae5dc7d70144ce1b73b403b7eb6e0948081ef03f1d9e0bb4a5bf38f16285c879299f07f948081ef03f1d9e0bb4a5bf38f16285c879299f07f8410000000f8449435552c16704d214347f29fa77f77da6d75d7c75294dc4973e838e3949c77aced16ac2315dc2d7ab11194dc4973e838e3949c77aced16ac2315dc2d7ab1118410000000f84494980a75ecd1309ea12fa2ed87a8744fbfc9b863d594cc6ac05c95a99c1f7b5f88de0e3486c82293b27094cc6ac05c95a99c1f7b5f88de0e3486c82293b2708410000000f84494f474cf03cceff28abc65c9cbae594f725c80e12d94e61a183325a18a173319dd8e19c8d069459e217594e61a183325a18a173319dd8e19c8d069459e21758410000000f84494b71b214cb885500844365e95cd9942c7276e7fd894d22ca3ba2141d23adab65ce4940eb7665ea2b6a794d22ca3ba2141d23adab65ce4940eb7665ea2b6a7841000000070e72399380dcfb0338abc03dc8d47f9f470ada8e769c9a78d644ea97385ecb20175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01db90175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbb0175b7a638427703f0dbe7bb9bbf987a2551717b34e79f33b5b1008d1fa01dbaa2646970667358221220cdf966601ebb54cb0e5a2ce03b7bba1df8f8464b1bf85237f62391faa3c8dd5164736f6c63430006040033",
+ },
+ {
+ ContractAddr: common.HexToAddress(SlashContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/030cf951e9f5ae1f8211333af807e5d30f3b5a85",
+ Code: "608060405234801561001057600080fd5b50600436106102745760003560e01c80638256ace611610151578063c81b1662116100c3578063dc927faf11610087578063dc927faf1461049a578063e1c7392a146104a2578063f9a2bbc7146104aa578063fc3e5908146104b2578063fc4333cd146104ba578063fd6a6879146104c257610274565b8063c81b166214610451578063c8509d8114610459578063c96be4cb1461046c578063cc844b731461047f578063d2a42e4b1461049257610274565b8063a1a11bf511610115578063a1a11bf514610409578063a78abc1614610411578063ab51bb9614610426578063ac0af6291461042e578063ac43175114610436578063c80d4b8f1461044957610274565b80638256ace6146103d6578063831d65d1146103de57806396713da9146103f15780639bc8e4f2146103f95780639dc092621461040157610274565b80634bf6c882116101ea5780636e47b482116101ae5780636e47b482146103a657806370fd5bad146103ae578063718a8aa8146103b657806375d47a0a146103be5780637912a65d146103c65780637942fd05146103ce57610274565b80634bf6c8821461037157806351e8067214610379578063567a372d146103815780635bfb49901461038957806362b72cf51461039e57610274565b806337c8dab91161023c57806337c8dab914610301578063389f4f71146103225780633a63f4b1146103375780633dffc3871461033f57806343756e5c14610354578063493279b11461035c57610274565b80630bee7a67146102795780630e2374a5146102975780631182b875146102ac57806323bac5a2146102cc57806335aa2e44146102ee575b600080fd5b6102816104ca565b60405161028e9190613058565b60405180910390f35b61029f6104cf565b60405161028e9190612989565b6102bf6102ba3660046128bf565b6104d5565b60405161028e91906129c1565b6102df6102da36600461266d565b61053b565b60405161028e93929190613040565b61029f6102fc36600461288f565b61055e565b61031461030f36600461266d565b610585565b60405161028e929190613032565b61032a6105dc565b60405161028e9190613008565b61032a6105e2565b6103476105e8565b60405161028e9190613069565b61029f6105ed565b6103646105f3565b60405161028e9190612ff9565b6103476105f9565b61029f6105fe565b61032a610604565b61039c61039736600461266d565b61060a565b005b61032a6106b5565b61029f6106bb565b6103476106c1565b6103476106c6565b61029f6106cb565b61032a6106d1565b6103476106d6565b6103146106db565b61039c6103ec3660046128bf565b6106e5565b6103476107f7565b61032a6107fc565b61029f610807565b61029f61080d565b610419610813565b60405161028e91906129b6565b61028161081c565b61032a610821565b61039c610444366004612773565b610826565b61032a610bda565b61029f610bdf565b61039c6104673660046128bf565b610be5565b61039c61047a36600461266d565b610c56565b61039c61048d3660046127dc565b611047565b61032a61151d565b61029f611522565b61039c611528565b61029f611564565b61034761156a565b61039c61156f565b61029f6119b8565b606481565b61200181565b606033612000146105015760405162461bcd60e51b81526004016104f890612e7f565b60405180910390fd5b60005460ff166105235760405162461bcd60e51b81526004016104f890612a6d565b60405162461bcd60e51b81526004016104f890612f42565b600260208190526000918252604090912080546001820154919092015460ff1683565b6001818154811061056b57fe5b6000918252602090912001546001600160a01b0316905081565b600080610590612454565b5050506001600160a01b0316600090815260026020818152604092839020835160608101855281548082526001830154938201849052919093015460ff16151592909301919091529091565b60055481565b60065481565b600181565b61100181565b6102ca81565b600881565b61200081565b60045481565b336110001461062b5760405162461bcd60e51b81526004016104f890612c93565b60005460ff1661064d5760405162461bcd60e51b81526004016104f890612a6d565b61200063f7a251d7600b610660846119be565b60006040518463ffffffff1660e01b815260040161068093929190613077565b600060405180830381600087803b15801561069a57600080fd5b505af11580156106ae573d6000803e3d6000fd5b5050505050565b60035481565b61100581565b600281565b601081565b61100881565b603281565b600b81565b6004546005549091565b33612000146107065760405162461bcd60e51b81526004016104f890612e7f565b60005460ff166107285760405162461bcd60e51b81526004016104f890612a6d565b610730612477565b600061077184848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611a9192505050565b9150915080156107b85781516040517f7f0956d47419b9525356e7111652b653b530ec6f5096dccc04589bc38e629967916107ab91613058565b60405180910390a16106ae565b81516040517f7d45f62d17443dd4547bca8a8112c60e2385669318dc300ec61a5d2492f262e7916107e891613058565b60405180910390a15050505050565b600981565b662386f26fc1000081565b61100781565b61100681565b60005460ff1681565b600081565b600481565b60005460ff166108485760405162461bcd60e51b81526004016104f890612a6d565b33611007146108695760405162461bcd60e51b81526004016104f890612d3c565b6108d484848080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250506040805180820190915260148152731b5a5cd9195b59585b9bdc951a1c995cda1bdb1960621b60208201529150611b119050565b1561096f57602081146108f95760405162461bcd60e51b81526004016104f890612c1f565b604080516020601f840181900481028201810190925282815260009161093791858580838501838280828437600092019190915250611b6b92505050565b90506001811015801561094b575060055481105b6109675760405162461bcd60e51b81526004016104f890612e3a565b600455610b97565b6109d584848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600f81526e19995b1bdb9e551a1c995cda1bdb19608a1b60208201529150611b119050565b15610a7157602081146109fa5760405162461bcd60e51b81526004016104f890612d8a565b604080516020601f8401819004810282018101909252828152600091610a3891858580838501838280828437600092019190915250611b6b92505050565b90506103e88111158015610a4d575060045481115b610a695760405162461bcd60e51b81526004016104f890612adb565b600555610b97565b610ae584848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152601881527f66696e616c697479536c617368526577617264526174696f000000000000000060208201529150611b119050565b15610b7f5760208114610b0a5760405162461bcd60e51b81526004016104f890612f79565b604080516020601f8401819004810282018101909252828152600091610b4891858580838501838280828437600092019190915250611b6b92505050565b9050600a8110158015610b5b5750606481105b610b775760405162461bcd60e51b81526004016104f890612bd3565b600655610b97565b60405162461bcd60e51b81526004016104f890612f1b565b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a84848484604051610bcc94939291906129d4565b60405180910390a150505050565b609681565b61100281565b3361200014610c065760405162461bcd60e51b81526004016104f890612e7f565b60005460ff16610c285760405162461bcd60e51b81526004016104f890612a6d565b6040517f07db600eebe2ac176be8dcebad61858c245a4961bb32ca2aa3d159b09aa0810e90600090a1505050565b334114610c755760405162461bcd60e51b81526004016104f890612ece565b60005460ff16610c975760405162461bcd60e51b81526004016104f890612a6d565b6003544311610cb85760405162461bcd60e51b81526004016104f890612fc4565b3a15610cd65760405162461bcd60e51b81526004016104f890612d0e565b60405163155853f360e21b8152611000906355614fcc90610cfb908490600401612989565b60206040518083038186803b158015610d1357600080fd5b505afa158015610d27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d4b9190612753565b610d5457611040565b610d5c612454565b506001600160a01b0381166000908152600260208181526040928390208351606081018552815481526001820154928101929092529091015460ff161580159282019290925290610db7576020810180516001019052610e10565b60016040820181905260208201819052805480820182556000919091527fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf60180546001600160a01b0319166001600160a01b0384161790555b438152600554602082015181610e2257fe5b06610f6e57600060208201526040516335409f7f60e01b8152611000906335409f7f90610e53908590600401612989565b600060405180830381600087803b158015610e6d57600080fd5b505af1158015610e81573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b610ea1856119be565b60006040518463ffffffff1660e01b8152600401610ec193929190613077565b600060405180830381600087803b158015610edb57600080fd5b505af1925050508015610eec575060015b610f69573d808015610f1a576040519150601f19603f3d011682016040523d82523d6000602084013e610f1f565b606091505b50826001600160a01b03167fd7bc86ff5d08c8ab043edec743302aba2520e6635172a428bc956721db9e2d1c836020015183604051610f5f929190613011565b60405180910390a2505b610fda565b600454816020015181610f7d57fe5b06610fda576040516375abf10160e11b81526110009063eb57e20290610fa7908590600401612989565b600060405180830381600087803b158015610fc157600080fd5b505af1158015610fd5573d6000803e3d6000fd5b505050505b6001600160a01b0382166000818152600260208181526040808420865181559186015160018301558581015191909201805460ff1916911515919091179055517fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9190a2505b5043600355565b60005460ff166110695760405162461bcd60e51b81526004016104f890612a6d565b604051630a83aaa960e31b81526110069063541d55489061108e903390600401612989565b60206040518083038186803b1580156110a657600080fd5b505afa1580156110ba573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110de9190612753565b6110fa5760405162461bcd60e51b81526004016104f890612a06565b6006546111075760146006555b8051514361010090910111801561112957504381602001516000015161010001115b6111455760405162461bcd60e51b81526004016104f890612a3d565b8060200151602001518160000151602001511480156111735750806020015160600151816000015160600151145b156111905760405162461bcd60e51b81526004016104f890612c66565b8051604081015190511080156111af5750602081015160408101519051105b6111cb5760405162461bcd60e51b81526004016104f890612b6f565b6020810151518151511080156111f05750806000015160400151816020015160400151105b8061121b575080515160208201515110801561121b5750806020015160400151816000015160400151105b806112355750806020015160400151816000015160400151145b6112515760405162461bcd60e51b81526004016104f890612aa4565b6060806110006001600160a01b0316633b071dcc6040518163ffffffff1660e01b815260040160006040518083038186803b15801561128f57600080fd5b505afa1580156112a3573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526112cb9190810190612690565b60408501519193509150600090815b8351811015611328576113008482815181106112f257fe5b602002602001015183611b70565b156113205784818151811061131157fe5b60200260200101519250611328565b6001016112da565b506001600160a01b03821661134f5760405162461bcd60e51b81526004016104f890612ba6565b61136185600001518660400151611bd4565b801561137a575061137a85602001518660400151611bd4565b6113965760405162461bcd60e51b81526004016104f890612b10565b6006546040516309a99b4f60e41b815260646110028031909302049190639a99b4f0906113c9903390859060040161299d565b602060405180830381600087803b1580156113e357600080fd5b505af11580156113f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061141b91906128a7565b506040516335409f7f60e01b8152611000906335409f7f90611441908690600401612989565b600060405180830381600087803b15801561145b57600080fd5b505af115801561146f573d6000803e3d6000fd5b505050506120006001600160a01b031663f7a251d7600b61148f866119be565b60006040518463ffffffff1660e01b81526004016114af93929190613077565b600060405180830381600087803b1580156114c957600080fd5b505af11580156114dd573d6000803e3d6000fd5b50506040516001600160a01b03861692507fddb6012116e51abf5436d956a4f0ebd927e92c576ff96d7918290c8782291e3e9150600090a2505050505050565b601481565b61100381565b60005460ff161561154b5760405162461bcd60e51b81526004016104f890612dcc565b603260045560966005556000805460ff19166001179055565b61100081565b600381565b33611000146115905760405162461bcd60e51b81526004016104f890612c93565b60005460ff166115b25760405162461bcd60e51b81526004016104f890612a6d565b6001546115be576119b6565b600154600090600019015b80821161198a576000805b828410156116ed576115e4612454565b60026000600187815481106115f557fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156116d75760046005548161166257fe5b0481602001510381602001818152505080600260006001888154811061168457fe5b6000918252602080832091909101546001600160a01b0316835282810193909352604091820190208351815591830151600183015591909101516002909101805460ff19169115159190911790556116e1565b60019250506116ed565b508360010193506115d4565b828411611884576116fc612454565b600260006001868154811061170d57fe5b60009182526020808320909101546001600160a01b0316835282810193909352604091820190208151606081018352815481526001820154938101939093526002015460ff1615159082015260055490915060049004816020015111156117f55760046005548161177a57fe5b0481602001510381602001818152505080600260006001878154811061179c57fe5b6000918252602080832091909101546001600160a01b03168352828101939093526040918201902083518155918301516001808401919091559201516002909101805460ff191691151591909117905591506118849050565b600260006001868154811061180657fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff1916905580548061184a57fe5b600082815260209020810160001990810180546001600160a01b0319169055019055836118775750611884565b50600019909201916116ed565b81801561188e5750805b1561196d5760026000600186815481106118a457fe5b60009182526020808320909101546001600160a01b031683528201929092526040018120818155600181810192909255600201805460ff191690558054849081106118eb57fe5b600091825260209091200154600180546001600160a01b03909216918690811061191157fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550600180548061194a57fe5b600082815260209020810160001990810180546001600160a01b03191690550190555b8261197957505061198a565b5050600190910190600019016115c9565b6040517fcfdb3b6ccaeccbdc68be3c59c840e3b3c90f0a7c491f5fff1cf56cfda200dd9c90600090a150505b565b61100481565b60408051600480825260a08201909252606091829190816020015b60608152602001906001900390816119d9579050509050611a02836001600160a01b0316611dac565b81600081518110611a0f57fe5b6020026020010181905250611a2343611dcf565b81600181518110611a3057fe5b6020908102919091010152611a466102ca611dcf565b81600281518110611a5357fe5b6020026020010181905250611a6742611dcf565b81600381518110611a7457fe5b6020026020010181905250611a8881611de2565b9150505b919050565b611a99612477565b6000611aa3612477565b611aab612489565b611abc611ab786611e6c565b611e91565b90506000805b611acb83611edb565b15611b045780611af757611ae6611ae184611efc565b611f4a565b63ffffffff16845260019150611afc565b611b04565b600101611ac2565b5091935090915050915091565b600081604051602001611b24919061296d565b6040516020818303038152906040528051906020012083604051602001611b4b919061296d565b604051602081830303815290604052805190602001201490505b92915050565b015190565b815181516000916001918114808314611b8c5760009250611bca565b600160208701838101602088015b600284838510011415611bc5578051835114611bb95760009650600093505b60209283019201611b9a565b505050505b5090949350505050565b60408051600480825260a0820190925260009160609190816020015b6060815260200190600190039081611bf0575050604080516020808252818301909252919250606091908082018180368337019050509050611c358560000151611dcf565b82600081518110611c4257fe5b6020026020010181905250611c5d6020866020015183611fcc565b611c6681611fdc565b82600181518110611c7357fe5b6020026020010181905250611c8b8560400151611dcf565b82600281518110611c9857fe5b6020026020010181905250611cb36020866060015183611fcc565b611cbc81611fdc565b82600381518110611cc957fe5b6020026020010181905250611cef6020611ce284611de2565b8051906020012083611fcc565b6040805160b080825260e08201909252606091602082018180368337019050509050611d1f818360006020612032565b611d3181876080015160206060612032565b611d3f818660806030612032565b604080516001808252818301909252606091602082018180368337019050509050815160016020830182602086016066600019fa611d7c57600080fd5b506001611d8a826000612085565b60ff1614611d9f576000945050505050611b65565b5060019695505050505050565b60408051600560a21b8318601482015260348101909152606090611a8881611fdc565b6060611b65611ddd836120a1565b611fdc565b6060815160001415611e035750604080516000815260208101909152611a8c565b606082600081518110611e1257fe5b602002602001015190506000600190505b8351811015611e5357611e4982858381518110611e3c57fe5b6020026020010151612187565b9150600101611e23565b50611a88611e66825160c060ff16612204565b82612187565b611e746124a9565b506040805180820190915281518152602082810190820152919050565b611e99612489565b611ea2826122d6565b611eab57600080fd5b6000611eba8360200151612310565b60208085015160408051808201909152868152920190820152915050919050565b6000611ee56124a9565b505080518051602091820151919092015191011190565b611f046124a9565b611f0d82611edb565b611f1657600080fd5b60208201516000611f2682612373565b80830160209586015260408051808201909152908152938401919091525090919050565b805160009015801590611f5f57508151602110155b611f6857600080fd5b6000611f778360200151612310565b90508083600001511015611f9d5760405162461bcd60e51b81526004016104f890612e03565b825160208085015183018051928490039291831015611fc357826020036101000a820491505b50949350505050565b9091018181526020918201910152565b60608151600114801561200e5750607f60f81b82600081518110611ffc57fe5b01602001516001600160f81b03191611155b1561201a575080611a8c565b611b6561202c8351608060ff16612204565b83612187565b60005b818110156106ae5783818151811061204957fe5b602001015160f81c60f81b85848060010195508151811061206657fe5b60200101906001600160f81b031916908160001a905350600101612035565b6000816001018351101561209857600080fd5b50016001015190565b604080516020808252818301909252606091829190602082018180368337505050602081018490529050600067ffffffffffffffff1984166120e557506018612109565b6fffffffffffffffffffffffffffffffff19841661210557506010612109565b5060005b602081101561213f5781818151811061211e57fe5b01602001516001600160f81b031916156121375761213f565b600101612109565b60008160200390506060816040519080825280601f01601f191660200182016040528015612174576020820181803683370190505b5080830196909652508452509192915050565b6060806040519050835180825260208201818101602087015b818310156121b85780518352602092830192016121a0565b50855184518101855292509050808201602086015b818310156121e55780518352602092830192016121cd565b508651929092011591909101601f01601f191660405250905092915050565b606068010000000000000000831061222e5760405162461bcd60e51b81526004016104f890612b47565b604080516001808252818301909252606091602082018180368337019050509050603784116122885782840160f81b8160008151811061226a57fe5b60200101906001600160f81b031916908160001a9053509050611b65565b6060612293856120a1565b90508381510160370160f81b826000815181106122ac57fe5b60200101906001600160f81b031916908160001a9053506122cd8282612187565b95945050505050565b80516000906122e757506000611a8c565b6020820151805160001a9060c082101561230657600092505050611a8c565b5060019392505050565b8051600090811a608081101561232a576000915050611a8c565b60b8811080612345575060c08110801590612345575060f881105b15612354576001915050611a8c565b60c08110156123685760b519019050611a8c565b60f519019050611a8c565b80516000908190811a608081101561238e576001915061244d565b60b88110156123a357607e198101915061244d565b60c08110156123f457600060b78203600186019550806020036101000a8651049150600181018201935050808310156123ee5760405162461bcd60e51b81526004016104f890612ce3565b5061244d565b60f88110156124095760be198101915061244d565b600060f78203600186019550806020036101000a86510491506001810182019350508083101561244b5760405162461bcd60e51b81526004016104f890612ce3565b505b5092915050565b604051806060016040528060008152602001600081526020016000151581525090565b60408051602081019091526000815290565b604051806040016040528061249c6124a9565b8152602001600081525090565b604051806040016040528060008152602001600081525090565b600082601f8301126124d3578081fd5b81516124e66124e1826130ca565b6130a3565b818152915060208083019084810160005b8481101561255c578151870188603f82011261251257600080fd5b838101516125226124e1826130ea565b81815260408b8184860101111561253857600080fd5b6125478388840183870161310e565b508652505092820192908201906001016124f7565b505050505092915050565b60008083601f840112612578578182fd5b50813567ffffffffffffffff81111561258f578182fd5b6020830191508360208285010111156125a757600080fd5b9250929050565b600082601f8301126125be578081fd5b81356125cc6124e1826130ea565b91508082528360208285010111156125e357600080fd5b8060208401602084013760009082016020015292915050565b600060a0828403121561260d578081fd5b61261760a06130a3565b905081358152602082013560208201526040820135604082015260608201356060820152608082013567ffffffffffffffff81111561265557600080fd5b612661848285016125ae565b60808301525092915050565b60006020828403121561267e578081fd5b81356126898161313e565b9392505050565b600080604083850312156126a2578081fd5b825167ffffffffffffffff808211156126b9578283fd5b81850186601f8201126126ca578384fd5b805192506126da6124e1846130ca565b80848252602080830192508084018a8283890287010111156126fa578788fd5b8794505b868510156127255780516127118161313e565b8452600194909401939281019281016126fe565b50880151909650935050508082111561273c578283fd5b50612749858286016124c3565b9150509250929050565b600060208284031215612764578081fd5b81518015158114612689578182fd5b60008060008060408587031215612788578182fd5b843567ffffffffffffffff8082111561279f578384fd5b6127ab88838901612567565b909650945060208701359150808211156127c3578384fd5b506127d087828801612567565b95989497509550505050565b6000602082840312156127ed578081fd5b813567ffffffffffffffff80821115612804578283fd5b81840160608187031215612816578384fd5b61282060606130a3565b9250803582811115612830578485fd5b61283c878284016125fc565b845250602081013582811115612850578485fd5b61285c878284016125fc565b602085015250604081013582811115612873578485fd5b61287f878284016125ae565b6040850152509195945050505050565b6000602082840312156128a0578081fd5b5035919050565b6000602082840312156128b8578081fd5b5051919050565b6000806000604084860312156128d3578283fd5b833560ff811681146128e3578384fd5b9250602084013567ffffffffffffffff8111156128fe578283fd5b61290a86828701612567565b9497909650939450505050565b60008284528282602086013780602084860101526020601f19601f85011685010190509392505050565b6000815180845261295981602086016020860161310e565b601f01601f19169290920160200192915050565b6000825161297f81846020870161310e565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b6000602082526126896020830184612941565b6000604082526129e8604083018688612917565b82810360208401526129fb818587612917565b979650505050505050565b6020808252601f908201527f746865206d73672073656e646572206973206e6f7420612072656c6179657200604082015260600190565b6020808252601690820152751d1bdbc81bdb1908189b1bd8dac81a5b9d9bdb1d995960521b604082015260600190565b60208082526019908201527f74686520636f6e7472616374206e6f7420696e69742079657400000000000000604082015260600190565b6020808252601a908201527f6e6f2076696f6c6174696f6e206f6620766f74652072756c6573000000000000604082015260600190565b6020808252818101527f7468652066656c6f6e795468726573686f6c64206f7574206f662072616e6765604082015260600190565b60208082526017908201527f766572696679207369676e6174757265206661696c6564000000000000000000604082015260600190565b6020808252600e908201526d696e70757420746f6f206c6f6e6760901b604082015260600190565b60208082526019908201527f7372634e756d20626967676572207468616e207461724e756d00000000000000604082015260600190565b6020808252601390820152721d985b1a59185d1bdc881b9bdd08195e1a5cdd606a1b604082015260600190565b6020808252602c908201527f7468652066696e616c69747920736c6173682072657761726420726174696f2060408201526b6f7574206f662072616e676560a01b606082015260800190565b60208082526027908201527f6c656e677468206f66206d697364656d65616e6f725468726573686f6c64206d6040820152660d2e6dac2e8c6d60cb1b606082015260800190565b60208082526013908201527274776f206964656e746963616c20766f74657360681b604082015260600190565b60208082526030908201527f746865206d6573736167652073656e646572206d7573742062652076616c696460408201526f185d1bdc94d95d0818dbdb9d1c9858dd60821b606082015260800190565b6020808252601190820152706164646974696f6e206f766572666c6f7760781b604082015260600190565b6020808252601490820152736761737072696365206973206e6f74207a65726f60601b604082015260600190565b6020808252602e908201527f746865206d6573736167652073656e646572206d75737420626520676f76657260408201526d1b985b98d94818dbdb9d1c9858dd60921b606082015260800190565b60208082526022908201527f6c656e677468206f662066656c6f6e795468726573686f6c64206d69736d61746040820152610c6d60f31b606082015260800190565b60208082526019908201527f74686520636f6e747261637420616c726561647920696e697400000000000000604082015260600190565b6020808252601a908201527f6c656e677468206973206c657373207468616e206f6666736574000000000000604082015260600190565b60208082526025908201527f746865206d697364656d65616e6f725468726573686f6c64206f7574206f662060408201526472616e676560d81b606082015260800190565b6020808252602f908201527f746865206d6573736167652073656e646572206d7573742062652063726f737360408201526e0818da185a5b8818dbdb9d1c9858dd608a1b606082015260800190565b6020808252602d908201527f746865206d6573736167652073656e646572206d75737420626520746865206260408201526c3637b1b590383937b23ab1b2b960991b606082015260800190565b6020808252600d908201526c756e6b6e6f776e20706172616d60981b604082015260600190565b6020808252601e908201527f7265636569766520756e65787065637465642073796e207061636b6167650000604082015260600190565b6020808252602b908201527f6c656e677468206f662066696e616c697479536c61736852657761726452617460408201526a0d2de40dad2e6dac2e8c6d60ab1b606082015260800190565b6020808252818101527f63616e206e6f7420736c61736820747769636520696e206f6e6520626c6f636b604082015260600190565b61ffff91909116815260200190565b90815260200190565b60008382526040602083015261302a6040830184612941565b949350505050565b918252602082015260400190565b92835260208301919091521515604082015260600190565b63ffffffff91909116815260200190565b60ff91909116815260200190565b600060ff85168252606060208301526130936060830185612941565b9050826040830152949350505050565b60405181810167ffffffffffffffff811182821017156130c257600080fd5b604052919050565b600067ffffffffffffffff8211156130e0578081fd5b5060209081020190565b600067ffffffffffffffff821115613100578081fd5b50601f01601f191660200190565b60005b83811015613129578181015183820152602001613111565b83811115613138576000848401525b50505050565b6001600160a01b038116811461315357600080fd5b5056fea264697066735822122062d6936d7751cb36a7753c3187f769a6c7d5ce515f68149fca01eefaf8f04af564736f6c63430006040033",
+ },
+ {
+ ContractAddr: common.HexToAddress(SystemRewardContract),
+ CommitUrl: "https://github.com/bnb-chain/bsc-genesis-contract/commit/030cf951e9f5ae1f8211333af807e5d30f3b5a85",
+ Code: "6080604052600436106101a05760003560e01c80637942fd05116100ec578063ac4317511161008a578063f9a2bbc711610064578063f9a2bbc714610550578063fb5478b314610565578063fc3e59081461057a578063fd6a68791461058f576101e4565b8063ac43175114610457578063c81b166214610526578063dc927faf1461053b576101e4565b80639dc09262116100c65780639dc0926214610403578063a1a11bf514610418578063a78abc161461042d578063ab51bb9614610442576101e4565b80637942fd05146103a057806396713da9146103b55780639a99b4f0146103ca576101e4565b80634bf6c882116101595780636e47b482116101335780636e47b4821461034c57806370fd5bad14610361578063718a8aa81461037657806375d47a0a1461038b576101e4565b80634bf6c882146102db57806351e80672146102f05780636d70f7ae14610305576101e4565b80630bee7a67146101e95780630e2374a5146102175780633a0b0eff146102485780633dffc3871461026f57806343756e5c1461029a578063493279b1146102af576101e4565b366101e45734156101e25760408051348152905133917f6c98249d85d88c3753a04a22230f595e4dc8d3dc86c34af35deeeedc861b89db919081900360200190a25b005b600080fd5b3480156101f557600080fd5b506101fe6105a4565b6040805163ffffffff9092168252519081900360200190f35b34801561022357600080fd5b5061022c6105a9565b604080516001600160a01b039092168252519081900360200190f35b34801561025457600080fd5b5061025d6105af565b60408051918252519081900360200190f35b34801561027b57600080fd5b506102846105b5565b6040805160ff9092168252519081900360200190f35b3480156102a657600080fd5b5061022c6105ba565b3480156102bb57600080fd5b506102c46105c0565b6040805161ffff9092168252519081900360200190f35b3480156102e757600080fd5b506102846105c6565b3480156102fc57600080fd5b5061022c6105cb565b34801561031157600080fd5b506103386004803603602081101561032857600080fd5b50356001600160a01b03166105d1565b604080519115158252519081900360200190f35b34801561035857600080fd5b5061022c6105ef565b34801561036d57600080fd5b506102846105f5565b34801561038257600080fd5b506102846105fa565b34801561039757600080fd5b5061022c6105ff565b3480156103ac57600080fd5b50610284610605565b3480156103c157600080fd5b5061028461060a565b3480156103d657600080fd5b5061025d600480360360408110156103ed57600080fd5b506001600160a01b03813516906020013561060f565b34801561040f57600080fd5b5061022c6107ba565b34801561042457600080fd5b5061022c6107c0565b34801561043957600080fd5b506103386107c6565b34801561044e57600080fd5b506101fe6107cf565b34801561046357600080fd5b506101e26004803603604081101561047a57600080fd5b81019060208101813564010000000081111561049557600080fd5b8201836020820111156104a757600080fd5b803590602001918460018302840111640100000000831117156104c957600080fd5b9193909290916020810190356401000000008111156104e757600080fd5b8201836020820111156104f957600080fd5b8035906020019184600183028401116401000000008311171561051b57600080fd5b5090925090506107d4565b34801561053257600080fd5b5061022c610b57565b34801561054757600080fd5b5061022c610b5d565b34801561055c57600080fd5b5061022c610b63565b34801561057157600080fd5b5061025d610b69565b34801561058657600080fd5b50610284610b75565b34801561059b57600080fd5b5061022c610b7a565b606481565b61200181565b60015481565b600181565b61100181565b6102ca81565b600881565b61200081565b6001600160a01b031660009081526002602052604090205460ff1690565b61100581565b600281565b601081565b61100881565b600b81565b600981565b6000805460ff1661068c57600260208190527fe57bda0a954a7c7381b17b2c763e646ba2c60f67292d287ba583603e2c1c41668054600160ff19918216811790925561100560009081527fe25235fc0de9d7165652bef0846fefda506174abb9a190f03d0f7bcc6146dbce80548316841790559282558254161790555b3360009081526002602052604090205460ff166106da5760405162461bcd60e51b815260040180806020018281038252602b815260200180610c68602b913960400191505060405180910390fd5b60004783106106e957476106eb565b825b9050670de0b6b3a76400008111156107085750670de0b6b3a76400005b8015610789576040516001600160a01b0385169082156108fc029083906000818181858888f19350505050158015610744573d6000803e3d6000fd5b506040805182815290516001600160a01b038616917ff8b71c64315fc33b2ead2adfa487955065152a8ac33d9d5193aafd7f45dc15a0919081900360200190a26107b3565b6040517fe589651933c2457488cc0d8e0941518abf748e799435e4e396d9c4d0b2db2d4d90600090a15b9392505050565b61100781565b61100681565b60005460ff1681565b600081565b33611007146108145760405162461bcd60e51b815260040180806020018281038252602e815260200180610cc2602e913960400191505060405180910390fd5b61087684848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600b81526a30b23227b832b930ba37b960a91b60208201529150610b809050565b1561094e57606082828080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050825192935050601490911490506108f95760405162461bcd60e51b815260040180806020018281038252602c815260200180610cf0602c913960400191505060405180910390fd5b60148101516001600160a01b038116600081815260026020526040808220805460ff19166001179055517f9870d7fe5d112134c55844951dedf365363006d9c588db07c4c85af6322a06199190a25050610ac5565b6109b384848080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505060408051808201909152600e81526d3232b632ba32a7b832b930ba37b960911b60208201529150610b809050565b15610a8857606082828080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152505082519293505060149091149050610a365760405162461bcd60e51b815260040180806020018281038252602f815260200180610c93602f913960400191505060405180910390fd5b60148101516001600160a01b038116600081815260026020526040808220805460ff19169055517fb40992a19dba61ea600e87fce607102bf5908dc89076217b6ca6ae195224f7029190a25050610ac5565b6040805162461bcd60e51b815260206004820152600d60248201526c756e6b6e6f776e20706172616d60981b604482015290519081900360640190fd5b7f6cdb0ac70ab7f2e2d035cca5be60d89906f2dede7648ddbd7402189c1eeed17a848484846040518080602001806020018381038352878782818152602001925080828437600083820152601f01601f191690910184810383528581526020019050858580828437600083820152604051601f909101601f19169092018290039850909650505050505050a150505050565b61100281565b61100381565b61100081565b670de0b6b3a764000081565b600381565b61100481565b6000816040516020018082805190602001908083835b60208310610bb55780518252601f199092019160209182019101610b96565b6001836020036101000a03801982511681845116808217855250505050505090500191505060405160208183030381529060405280519060200120836040516020018082805190602001908083835b60208310610c235780518252601f199092019160209182019101610c04565b6001836020036101000a038019825116818451168082178552505050505050905001915050604051602081830303815290604052805190602001201490509291505056fe6f6e6c79206f70657261746f7220697320616c6c6f77656420746f2063616c6c20746865206d6574686f646c656e677468206f662076616c756520666f722064656c6574654f70657261746f722073686f756c64206265203230746865206d6573736167652073656e646572206d75737420626520676f7665726e616e636520636f6e74726163746c656e677468206f662076616c756520666f72206164644f70657261746f722073686f756c64206265203230a2646970667358221220dfab8b447e80ff45b4921032d6fc749c076c81bafdd35dc3adbf21cb41cdac7964736f6c63430006040033",
+ },
+ },
+ }
}
func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.Int, statedb *state.StateDB) {
@@ -603,6 +667,10 @@ func UpgradeBuildInSystemContract(config *params.ChainConfig, blockNumber *big.I
applySystemContractUpgrade(planckUpgrade[network], blockNumber, statedb, logger)
}
+ if config.IsOnBoneh(blockNumber) {
+ applySystemContractUpgrade(bonehUpgrade[network], blockNumber, statedb, logger)
+ }
+
/*
apply other upgrades
*/
diff --git a/core/types/vote.go b/core/types/vote.go
new file mode 100644
index 0000000000..e631b7294d
--- /dev/null
+++ b/core/types/vote.go
@@ -0,0 +1,92 @@
+package types
+
+import (
+ "sync/atomic"
+
+ "github.com/pkg/errors"
+ "github.com/prysmaticlabs/prysm/v3/crypto/bls"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+const (
+ BLSPublicKeyLength = 48
+ BLSSignatureLength = 96
+
+ MaxAttestationExtraLength = 256
+ NaturallyFinalizedDist = 21 // The distance to naturally finalized a block
+)
+
+type BLSPublicKey [BLSPublicKeyLength]byte
+type BLSSignature [BLSSignatureLength]byte
+type ValidatorsBitSet uint64
+
+// VoteData represents the vote range that validator voted for fast finality.
+type VoteData struct {
+ SourceNumber uint64 // The source block number should be the latest justified block number.
+ SourceHash common.Hash // The block hash of the source block.
+ TargetNumber uint64 // The target block number which validator wants to vote for.
+ TargetHash common.Hash // The block hash of the target block.
+}
+
+// Hash returns the hash of the vote data.
+func (d *VoteData) Hash() common.Hash { return rlpHash(d) }
+
+// VoteEnvelope represents the vote of a single validator.
+type VoteEnvelope struct {
+ VoteAddress BLSPublicKey // The BLS public key of the validator.
+ Signature BLSSignature // Validator's signature for the vote data.
+ Data *VoteData // The vote data for fast finality.
+
+ // caches
+ hash atomic.Value
+}
+
+// VoteAttestation represents the votes of super majority validators.
+type VoteAttestation struct {
+ VoteAddressSet ValidatorsBitSet // The bitset marks the voted validators.
+ AggSignature BLSSignature // The aggregated BLS signature of the voted validators' signatures.
+ Data *VoteData // The vote data for fast finality.
+ Extra []byte // Reserved for future usage.
+}
+
+// Hash returns the vote's hash.
+func (v *VoteEnvelope) Hash() common.Hash {
+ if hash := v.hash.Load(); hash != nil {
+ return hash.(common.Hash)
+ }
+
+ h := v.calcVoteHash()
+ v.hash.Store(h)
+ return h
+}
+
+func (v *VoteEnvelope) calcVoteHash() common.Hash {
+ vote := struct {
+ VoteAddress BLSPublicKey
+ Signature BLSSignature
+ Data *VoteData
+ }{v.VoteAddress, v.Signature, v.Data}
+ return rlpHash(vote)
+}
+
+func (b BLSPublicKey) Bytes() []byte { return b[:] }
+
+// Verify vote using BLS.
+func (vote *VoteEnvelope) Verify() error {
+ blsPubKey, err := bls.PublicKeyFromBytes(vote.VoteAddress[:])
+ if err != nil {
+ return errors.Wrap(err, "convert public key from bytes to bls failed")
+ }
+
+ sig, err := bls.SignatureFromBytes(vote.Signature[:])
+ if err != nil {
+ return errors.Wrap(err, "invalid signature")
+ }
+
+ voteDataHash := vote.Data.Hash()
+ if !sig.Verify(blsPubKey, voteDataHash[:]) {
+ return errors.New("verify bls signature failed.")
+ }
+ return nil
+}
diff --git a/core/vm/contracts.go b/core/vm/contracts.go
index d0f3a1ba03..3db2bf8477 100644
--- a/core/vm/contracts.go
+++ b/core/vm/contracts.go
@@ -22,16 +22,17 @@ import (
"errors"
"math/big"
+ "github.com/prysmaticlabs/prysm/v3/crypto/bls"
+ "golang.org/x/crypto/ripemd160"
+
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/blake2b"
"github.com/ethereum/go-ethereum/crypto/bls12381"
"github.com/ethereum/go-ethereum/crypto/bn256"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
-
- //lint:ignore SA1019 Needed for precompile
- "golang.org/x/crypto/ripemd160"
)
// PrecompiledContract is the basic interface for native Go contracts. The implementation
@@ -140,6 +141,24 @@ var PrecompiledContractsBerlin = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{9}): &blake2F{},
}
+// PrecompiledContractsBoneh contains the default set of pre-compiled Ethereum
+// contracts used in the Boneh release.
+var PrecompiledContractsBoneh = map[common.Address]PrecompiledContract{
+ common.BytesToAddress([]byte{1}): &ecrecover{},
+ common.BytesToAddress([]byte{2}): &sha256hash{},
+ common.BytesToAddress([]byte{3}): &ripemd160hash{},
+ common.BytesToAddress([]byte{4}): &dataCopy{},
+ common.BytesToAddress([]byte{5}): &bigModExp{},
+ common.BytesToAddress([]byte{6}): &bn256AddIstanbul{},
+ common.BytesToAddress([]byte{7}): &bn256ScalarMulIstanbul{},
+ common.BytesToAddress([]byte{8}): &bn256PairingIstanbul{},
+ common.BytesToAddress([]byte{9}): &blake2F{},
+
+ common.BytesToAddress([]byte{100}): &tmHeaderValidate{},
+ common.BytesToAddress([]byte{101}): &iavlMerkleProofValidatePlanck{},
+ common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
+}
+
// PrecompiledContractsBLS contains the set of pre-compiled Ethereum
// contracts specified in EIP-2537. These are exported for testing purposes.
var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
@@ -155,6 +174,7 @@ var PrecompiledContractsBLS = map[common.Address]PrecompiledContract{
}
var (
+ PrecompiledAddressesBoneh []common.Address
PrecompiledAddressesPlanck []common.Address
PrecompiledAddressesMoran []common.Address
PrecompiledAddressesNano []common.Address
@@ -186,11 +206,16 @@ func init() {
for k := range PrecompiledContractsPlanck {
PrecompiledAddressesPlanck = append(PrecompiledAddressesPlanck, k)
}
+ for k := range PrecompiledContractsBoneh {
+ PrecompiledAddressesBoneh = append(PrecompiledAddressesBoneh, k)
+ }
}
// ActivePrecompiles returns the precompiles enabled with the current configuration.
func ActivePrecompiles(rules params.Rules) []common.Address {
switch {
+ case rules.IsBoneh:
+ return PrecompiledAddressesBoneh
case rules.IsPlanck:
return PrecompiledAddressesPlanck
case rules.IsMoran:
@@ -271,6 +296,7 @@ type sha256hash struct{}
func (c *sha256hash) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.Sha256PerWordGas + params.Sha256BaseGas
}
+
func (c *sha256hash) Run(input []byte) ([]byte, error) {
h := sha256.Sum256(input)
return h[:], nil
@@ -286,6 +312,7 @@ type ripemd160hash struct{}
func (c *ripemd160hash) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.Ripemd160PerWordGas + params.Ripemd160BaseGas
}
+
func (c *ripemd160hash) Run(input []byte) ([]byte, error) {
ripemd := ripemd160.New()
ripemd.Write(input)
@@ -302,6 +329,7 @@ type dataCopy struct{}
func (c *dataCopy) RequiredGas(input []byte) uint64 {
return uint64(len(input)+31)/32*params.IdentityPerWordGas + params.IdentityBaseGas
}
+
func (c *dataCopy) Run(in []byte) ([]byte, error) {
return in, nil
}
@@ -402,7 +430,7 @@ func (c *bigModExp) RequiredGas(input []byte) uint64 {
// def mult_complexity(x):
// ceiling(x/8)^2
//
- //where is x is max(length_of_MODULUS, length_of_BASE)
+ // where is x is max(length_of_MODULUS, length_of_BASE)
gas = gas.Add(gas, big7)
gas = gas.Div(gas, big8)
gas.Mul(gas, gas)
@@ -1110,3 +1138,72 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) {
// Encode the G2 point to 256 bytes
return g.EncodePoint(r), nil
}
+
+// blsSignatureVerify implements bls signature verification precompile.
+type blsSignatureVerify struct{}
+
+const (
+ msgHashLength = uint64(32)
+ signatureLength = uint64(96)
+ singleBlsPubkeyLength = uint64(48)
+)
+
+// RequiredGas returns the gas required to execute the pre-compiled contract.
+func (c *blsSignatureVerify) RequiredGas(input []byte) uint64 {
+ msgAndSigLength := msgHashLength + signatureLength
+ inputLen := uint64(len(input))
+ if inputLen <= msgAndSigLength ||
+ (inputLen-msgAndSigLength)%singleBlsPubkeyLength != 0 {
+ return params.BlsSignatureVerifyBaseGas
+ }
+ pubKeyNumber := (inputLen - msgAndSigLength) / singleBlsPubkeyLength
+ return params.BlsSignatureVerifyBaseGas + pubKeyNumber*params.BlsSignatureVerifyPerKeyGas
+}
+
+// Run input:
+// msg | signature | [{bls pubkey}] |
+// 32 bytes | 96 bytes | [{48 bytes}] |
+func (c *blsSignatureVerify) Run(input []byte) ([]byte, error) {
+ msgAndSigLength := msgHashLength + signatureLength
+ inputLen := uint64(len(input))
+ if inputLen <= msgAndSigLength ||
+ (inputLen-msgAndSigLength)%singleBlsPubkeyLength != 0 {
+ log.Debug("blsSignatureVerify input size wrong", "inputLen", inputLen)
+ return nil, ErrExecutionReverted
+ }
+
+ var msg [32]byte
+ msgBytes := getData(input, 0, msgHashLength)
+ copy(msg[:], msgBytes)
+
+ signatureBytes := getData(input, msgHashLength, signatureLength)
+ sig, err := bls.SignatureFromBytes(signatureBytes)
+ if err != nil {
+ log.Debug("blsSignatureVerify invalid signature", "err", err)
+ return nil, ErrExecutionReverted
+ }
+
+ pubKeyNumber := (inputLen - msgAndSigLength) / singleBlsPubkeyLength
+ pubKeys := make([]bls.PublicKey, pubKeyNumber)
+ for i := uint64(0); i < pubKeyNumber; i++ {
+ pubKeyBytes := getData(input, msgAndSigLength+i*singleBlsPubkeyLength, singleBlsPubkeyLength)
+ pubKey, err := bls.PublicKeyFromBytes(pubKeyBytes)
+ if err != nil {
+ log.Debug("blsSignatureVerify invalid pubKey", "err", err)
+ return nil, ErrExecutionReverted
+ }
+ pubKeys[i] = pubKey
+ }
+
+ if pubKeyNumber > 1 {
+ if !sig.FastAggregateVerify(pubKeys, msg) {
+ return big0.Bytes(), nil
+ }
+ } else {
+ if !sig.Verify(pubKeys[0], msgBytes) {
+ return big0.Bytes(), nil
+ }
+ }
+
+ return big1.Bytes(), nil
+}
diff --git a/core/vm/contracts_test.go b/core/vm/contracts_test.go
index aa8d2f1eb3..80505d7e72 100644
--- a/core/vm/contracts_test.go
+++ b/core/vm/contracts_test.go
@@ -65,6 +65,7 @@ var allPrecompiles = map[common.Address]PrecompiledContract{
common.BytesToAddress([]byte{16}): &bls12381Pairing{},
common.BytesToAddress([]byte{17}): &bls12381MapG1{},
common.BytesToAddress([]byte{18}): &bls12381MapG2{},
+ common.BytesToAddress([]byte{102}): &blsSignatureVerify{},
}
// EIP-152 test vectors
@@ -179,7 +180,7 @@ func benchmarkPrecompiled(addr string, test precompiledTest, bench *testing.B) {
// Keep it as uint64, multiply 100 to get two digit float later
mgasps := (100 * 1000 * gasUsed) / elapsed
bench.ReportMetric(float64(mgasps)/100, "mgas/s")
- //Check if it is correct
+ // Check if it is correct
if err != nil {
bench.Error(err)
return
@@ -231,6 +232,16 @@ func BenchmarkPrecompiledIdentity(bench *testing.B) {
benchmarkPrecompiled("04", t, bench)
}
+// Benchmarks the sample inputs from the blsSignatureVerify precompile.
+func BenchmarkPrecompiledBlsSignatureVerify(bench *testing.B) {
+ t := precompiledTest{
+ Input: "f2d8e8e5bf354429e3ce8b97c4e88f7a0bf7bc917e856de762ed6d70dd8ec2d289a04d63285e4b45309e7c180ea82565e375dd62c7b80d957aea4c9b7e16bdb28a0f910036bd3220fe3d7614fb137a8f0a68b3c564ddd214b5041d8f7a124e6e7285ac42635e75eeb9051a052fb500b1c2bc23bd4290db59fc02be11f2b80896b6e22d5b8dd31ba2e49b13cd6be19fcd01c1e23af3e5165d88d8b9deaf38baa77770fa6a358e2eebdffd1bd8a1eb7386",
+ Expected: "01",
+ Name: "",
+ }
+ benchmarkPrecompiled("66", t, bench)
+}
+
// Tests the sample inputs from the ModExp EIP 198.
func TestPrecompiledModExp(t *testing.T) { testJson("modexp", "05", t) }
func BenchmarkPrecompiledModExp(b *testing.B) { benchJson("modexp", "05", b) }
diff --git a/core/vm/evm.go b/core/vm/evm.go
index eb483fd6de..7ad12a8256 100644
--- a/core/vm/evm.go
+++ b/core/vm/evm.go
@@ -52,6 +52,8 @@ type (
func (evm *EVM) precompile(addr common.Address) (PrecompiledContract, bool) {
var precompiles map[common.Address]PrecompiledContract
switch {
+ case evm.chainRules.IsBoneh:
+ precompiles = PrecompiledContractsBoneh
case evm.chainRules.IsPlanck:
precompiles = PrecompiledContractsPlanck
case evm.chainRules.IsMoran:
@@ -256,7 +258,7 @@ func (evm *EVM) Call(caller ContractRef, addr common.Address, input []byte, gas
gas = 0
}
// TODO: consider clearing up unused snapshots:
- //} else {
+ // } else {
// evm.StateDB.DiscardSnapshot(snapshot)
}
return ret, gas, err
diff --git a/core/vote/vote_journal.go b/core/vote/vote_journal.go
new file mode 100644
index 0000000000..3fede24076
--- /dev/null
+++ b/core/vote/vote_journal.go
@@ -0,0 +1,124 @@
+package vote
+
+import (
+ "encoding/json"
+
+ lru "github.com/hashicorp/golang-lru"
+ "github.com/tidwall/wal"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/metrics"
+)
+
+const (
+ maxSizeOfRecentEntry = 512
+)
+
+type VoteJournal struct {
+ journalPath string // file path of disk journal for saving the vote.
+
+ walLog *wal.Log
+
+ voteDataBuffer *lru.Cache
+}
+
+var voteJournalError = metrics.NewRegisteredGauge("voteJournal/local", nil)
+
+func NewVoteJournal(filePath string) (*VoteJournal, error) {
+ walLog, err := wal.Open(filePath, &wal.Options{
+ LogFormat: wal.JSON,
+ SegmentCacheSize: maxSizeOfRecentEntry,
+ })
+ if err != nil {
+ log.Error("Failed to open vote journal", "err", err)
+ return nil, err
+ }
+
+ voteDataBuffer, err := lru.New(maxSizeOfRecentEntry)
+ if err != nil {
+ return nil, err
+ }
+
+ firstIndex, err := walLog.FirstIndex()
+ if err != nil {
+ log.Error("Failed to get first index of votes journal", "err", err)
+ }
+
+ lastIndex, err := walLog.LastIndex()
+ if err != nil {
+ log.Error("Failed to get lastIndex of vote journal", "err", err)
+ return nil, err
+ }
+
+ voteJournal := &VoteJournal{
+ journalPath: filePath,
+ walLog: walLog,
+ }
+
+ // Reload all voteData from journal to lru memory everytime node reboot.
+ for index := firstIndex; index <= lastIndex; index++ {
+ if voteEnvelop, err := voteJournal.ReadVote(index); err == nil && voteEnvelop != nil {
+ voteData := voteEnvelop.Data
+ voteDataBuffer.Add(voteData.TargetNumber, voteData)
+ }
+ }
+ voteJournal.voteDataBuffer = voteDataBuffer
+
+ return voteJournal, nil
+}
+
+func (journal *VoteJournal) WriteVote(voteMessage *types.VoteEnvelope) error {
+ walLog := journal.walLog
+
+ vote, err := json.Marshal(voteMessage)
+ if err != nil {
+ log.Error("Failed to unmarshal vote", "err", err)
+ return err
+ }
+
+ lastIndex, err := walLog.LastIndex()
+ if err != nil {
+ log.Error("Failed to get lastIndex of vote journal", "err", err)
+ return err
+ }
+
+ lastIndex += 1
+ if err = walLog.Write(lastIndex, vote); err != nil {
+ log.Error("Failed to write vote journal", "err", err)
+ return err
+ }
+
+ firstIndex, err := walLog.FirstIndex()
+ if err != nil {
+ log.Error("Failed to get first index of votes journal", "err", err)
+ }
+
+ if lastIndex-firstIndex+1 > maxSizeOfRecentEntry {
+ if err := walLog.TruncateFront(lastIndex - maxSizeOfRecentEntry + 1); err != nil {
+ log.Error("Failed to truncate votes journal", "err", err)
+ }
+ }
+
+ journal.voteDataBuffer.Add(voteMessage.Data.TargetNumber, voteMessage.Data)
+ return nil
+}
+
+func (journal *VoteJournal) ReadVote(index uint64) (*types.VoteEnvelope, error) {
+ voteMessage, err := journal.walLog.Read(index)
+ if err != nil && err != wal.ErrNotFound {
+ log.Error("Failed to read votes journal", "err", err)
+ return nil, err
+ }
+
+ var vote *types.VoteEnvelope
+ if voteMessage != nil {
+ vote = &types.VoteEnvelope{}
+ if err := json.Unmarshal(voteMessage, vote); err != nil {
+ log.Error("Failed to read vote from voteJournal", "err", err)
+ return nil, err
+ }
+ }
+
+ return vote, nil
+}
diff --git a/core/vote/vote_manager.go b/core/vote/vote_manager.go
new file mode 100644
index 0000000000..c35245694d
--- /dev/null
+++ b/core/vote/vote_manager.go
@@ -0,0 +1,219 @@
+package vote
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+// VoteManager will handle the vote produced by self.
+type VoteManager struct {
+ mux *event.TypeMux
+
+ chain *core.BlockChain
+ chainconfig *params.ChainConfig
+
+ chainHeadCh chan core.ChainHeadEvent
+ chainHeadSub event.Subscription
+
+ pool *VotePool
+ signer *VoteSigner
+ journal *VoteJournal
+
+ engine consensus.PoSA
+}
+
+func NewVoteManager(mux *event.TypeMux, chainconfig *params.ChainConfig, chain *core.BlockChain, pool *VotePool, journalPath, blsPasswordPath, blsWalletPath string, engine consensus.PoSA) (*VoteManager, error) {
+ voteManager := &VoteManager{
+ mux: mux,
+
+ chain: chain,
+ chainconfig: chainconfig,
+ chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
+
+ pool: pool,
+ engine: engine,
+ }
+
+ // Create voteSigner.
+ voteSigner, err := NewVoteSigner(blsPasswordPath, blsWalletPath)
+ if err != nil {
+ return nil, err
+ }
+ log.Info("Create voteSigner successfully")
+ voteManager.signer = voteSigner
+
+ // Create voteJournal
+ voteJournal, err := NewVoteJournal(journalPath)
+ if err != nil {
+ return nil, err
+ }
+ log.Info("Create voteJournal successfully")
+ voteManager.journal = voteJournal
+
+ // Subscribe to chain head event.
+ voteManager.chainHeadSub = voteManager.chain.SubscribeChainHeadEvent(voteManager.chainHeadCh)
+
+ go voteManager.loop()
+
+ return voteManager, nil
+}
+
+func (voteManager *VoteManager) loop() {
+ log.Debug("vote manager routine loop started")
+ events := voteManager.mux.Subscribe(downloader.StartEvent{}, downloader.DoneEvent{}, downloader.FailedEvent{})
+ defer func() {
+ log.Debug("vote manager loop defer func occur")
+ if !events.Closed() {
+ log.Debug("event not closed, unsubscribed by vote manager loop")
+ events.Unsubscribe()
+ }
+ }()
+
+ dlEventCh := events.Chan()
+
+ startVote := true
+ for {
+ select {
+ case ev := <-dlEventCh:
+ if ev == nil {
+ log.Debug("dlEvent is nil, continue")
+ continue
+ }
+ switch ev.Data.(type) {
+ case downloader.StartEvent:
+ log.Debug("downloader is in startEvent mode, will not startVote")
+ startVote = false
+ case downloader.FailedEvent:
+ log.Debug("downloader is in FailedEvent mode, set startVote flag as true")
+ startVote = true
+ case downloader.DoneEvent:
+ log.Debug("downloader is in DoneEvent mode, set the startVote flag to true")
+ startVote = true
+ }
+ case cHead := <-voteManager.chainHeadCh:
+ if !startVote {
+ log.Debug("startVote flag is false, continue")
+ continue
+ }
+
+ if cHead.Block == nil {
+ log.Debug("cHead.Block is nil, continue")
+ continue
+ }
+
+ curHead := cHead.Block.Header()
+ // Check if cur validator is within the validatorSet at curHead
+ if !voteManager.engine.IsActiveValidatorAt(voteManager.chain, curHead) {
+ log.Debug("cur validator is not within the validatorSet at curHead")
+ continue
+ }
+
+ // Vote for curBlockHeader block.
+ vote := &types.VoteData{
+ TargetNumber: curHead.Number.Uint64(),
+ TargetHash: curHead.Hash(),
+ }
+ voteMessage := &types.VoteEnvelope{
+ Data: vote,
+ }
+
+ // Put Vote into journal and VotesPool if we are active validator and allow to sign it.
+ if ok, sourceNumber, sourceHash := voteManager.UnderRules(curHead); ok {
+ log.Debug("curHead is underRules for voting")
+ if sourceHash == (common.Hash{}) {
+ log.Debug("sourceHash is empty")
+ continue
+ }
+
+ voteMessage.Data.SourceNumber = sourceNumber
+ voteMessage.Data.SourceHash = sourceHash
+
+ if err := voteManager.signer.SignVote(voteMessage); err != nil {
+ log.Error("Failed to sign vote", "err", err)
+ votesSigningErrorMetric(vote.TargetNumber, vote.TargetHash).Inc(1)
+ continue
+ }
+ if err := voteManager.journal.WriteVote(voteMessage); err != nil {
+ log.Error("Failed to write vote into journal", "err", err)
+ voteJournalError.Inc(1)
+ continue
+ }
+
+ log.Debug("vote manager produced vote", "votedBlockNumber", voteMessage.Data.TargetNumber, "votedBlockHash", voteMessage.Data.TargetHash, "voteMessageHash", voteMessage.Hash())
+ voteManager.pool.PutVote(voteMessage)
+ votesManagerMetric(vote.TargetNumber, vote.TargetHash).Inc(1)
+ }
+ case <-voteManager.chainHeadSub.Err():
+ log.Debug("voteManager subscribed chainHead failed")
+ return
+ }
+ }
+}
+
+// UnderRules checks if the produced header under the following rules:
+// A validator must not publish two distinct votes for the same height. (Rule 1)
+// A validator must not vote within the span of its other votes . (Rule 2)
+// Validators always vote for their canonical chain’s latest block. (Rule 3)
+func (voteManager *VoteManager) UnderRules(header *types.Header) (bool, uint64, common.Hash) {
+ sourceNumber, sourceHash, err := voteManager.engine.GetJustifiedNumberAndHash(voteManager.chain, header)
+ if err != nil {
+ log.Error("failed to get the highest justified number and hash at cur header", "curHeader's BlockNumber", header.Number, "curHeader's BlockHash", header.Hash())
+ return false, 0, common.Hash{}
+ }
+
+ targetNumber := header.Number.Uint64()
+
+ voteDataBuffer := voteManager.journal.voteDataBuffer
+ //Rule 1: A validator must not publish two distinct votes for the same height.
+ if voteDataBuffer.Contains(targetNumber) {
+ log.Debug("err: A validator must not publish two distinct votes for the same height.")
+ return false, 0, common.Hash{}
+ }
+
+ //Rule 2: A validator must not vote within the span of its other votes.
+ for blockNumber := sourceNumber + 1; blockNumber < targetNumber; blockNumber++ {
+ if voteDataBuffer.Contains(blockNumber) {
+ voteData, ok := voteDataBuffer.Get(blockNumber)
+ if !ok {
+ log.Error("Failed to get voteData info from LRU cache.")
+ continue
+ }
+ if voteData.(*types.VoteData).SourceNumber > sourceNumber {
+ log.Debug("error: cur vote is within the span of other votes")
+ return false, 0, common.Hash{}
+ }
+ }
+ }
+ for blockNumber := targetNumber + 1; blockNumber <= targetNumber+upperLimitOfVoteBlockNumber; blockNumber++ {
+ if voteDataBuffer.Contains(blockNumber) {
+ voteData, ok := voteDataBuffer.Get(blockNumber)
+ if !ok {
+ log.Error("Failed to get voteData info from LRU cache.")
+ continue
+ }
+ if voteData.(*types.VoteData).SourceNumber < sourceNumber {
+ log.Debug("error: other votes are within span of cur vote")
+ return false, 0, common.Hash{}
+ }
+ }
+ }
+
+ // Rule 3: Validators always vote for their canonical chain’s latest block.
+ // Since the header subscribed to is the canonical chain, so this rule is satisified by default.
+ log.Debug("All three rules check passed")
+ return true, sourceNumber, sourceHash
+}
+
+// Metrics to monitor if voteManager worked in the expetected logic.
+func votesManagerMetric(blockNumber uint64, blockHash common.Hash) metrics.Gauge {
+ return metrics.GetOrRegisterGauge(fmt.Sprintf("voteManager/blockNumber/%d/blockHash/%s", blockNumber, blockHash), nil)
+}
diff --git a/core/vote/vote_pool.go b/core/vote/vote_pool.go
new file mode 100644
index 0000000000..0e12855b6c
--- /dev/null
+++ b/core/vote/vote_pool.go
@@ -0,0 +1,396 @@
+package vote
+
+import (
+ "container/heap"
+ "sync"
+
+ mapset "github.com/deckarep/golang-set"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+const (
+ maxCurVoteAmountPerBlock = 21
+ maxFutureVoteAmountPerBlock = 50
+
+ voteBufferForPut = 256
+ // votes in the range (currentBlockNum-256,currentBlockNum+11] will be stored
+ lowerLimitOfVoteBlockNumber = 256
+ upperLimitOfVoteBlockNumber = 11 // refer to fetcher.maxUncleDist
+
+ chainHeadChanSize = 10 // chainHeadChanSize is the size of channel listening to ChainHeadEvent.
+)
+
+var (
+ localCurVotesGauge = metrics.NewRegisteredGauge("curVotes/local", nil)
+ localFutureVotesGauge = metrics.NewRegisteredGauge("futureVotes/local", nil)
+
+ localReceivedVotesGauge = metrics.NewRegisteredGauge("receivedVotes/local", nil)
+
+ localCurVotesPqGauge = metrics.NewRegisteredGauge("curVotesPq/local", nil)
+ localFutureVotesPqGauge = metrics.NewRegisteredGauge("futureVotesPq/local", nil)
+)
+
+type VoteBox struct {
+ blockNumber uint64
+ voteMessages []*types.VoteEnvelope
+}
+
+type VotePool struct {
+ chain *core.BlockChain
+ chainconfig *params.ChainConfig
+ mu sync.RWMutex
+
+ votesFeed event.Feed
+ scope event.SubscriptionScope
+
+ receivedVotes mapset.Set
+
+ curVotes map[common.Hash]*VoteBox
+ futureVotes map[common.Hash]*VoteBox
+
+ curVotesPq *votesPriorityQueue
+ futureVotesPq *votesPriorityQueue
+
+ chainHeadCh chan core.ChainHeadEvent
+ chainHeadSub event.Subscription
+
+ votesCh chan *types.VoteEnvelope
+
+ engine consensus.PoSA
+}
+
+type votesPriorityQueue []*types.VoteData
+
+func NewVotePool(chainconfig *params.ChainConfig, chain *core.BlockChain, engine consensus.PoSA) *VotePool {
+ votePool := &VotePool{
+ chain: chain,
+ chainconfig: chainconfig,
+ receivedVotes: mapset.NewSet(),
+ curVotes: make(map[common.Hash]*VoteBox),
+ futureVotes: make(map[common.Hash]*VoteBox),
+ curVotesPq: &votesPriorityQueue{},
+ futureVotesPq: &votesPriorityQueue{},
+ chainHeadCh: make(chan core.ChainHeadEvent, chainHeadChanSize),
+ votesCh: make(chan *types.VoteEnvelope, voteBufferForPut),
+ engine: engine,
+ }
+
+ // Subscribe events from blockchain and start the main event loop.
+ votePool.chainHeadSub = votePool.chain.SubscribeChainHeadEvent(votePool.chainHeadCh)
+
+ go votePool.loop()
+ return votePool
+}
+
+// loop is the vote pool's main even loop, waiting for and reacting to outside blockchain events and votes channel event.
+func (pool *VotePool) loop() {
+ for {
+ select {
+ // Handle ChainHeadEvent.
+ case ev := <-pool.chainHeadCh:
+ if ev.Block != nil {
+ latestBlockNumber := ev.Block.NumberU64()
+ pool.prune(latestBlockNumber)
+ pool.transferVotesFromFutureToCur(ev.Block.Header())
+ }
+ case <-pool.chainHeadSub.Err():
+ return
+
+ // Handle votes channel and put the vote into vote pool.
+ case vote := <-pool.votesCh:
+ pool.putIntoVotePool(vote)
+ }
+ }
+}
+
+func (pool *VotePool) PutVote(vote *types.VoteEnvelope) {
+ pool.votesCh <- vote
+}
+
+func (pool *VotePool) putIntoVotePool(vote *types.VoteEnvelope) bool {
+ targetNumber := vote.Data.TargetNumber
+ targetHash := vote.Data.TargetHash
+ header := pool.chain.CurrentBlock().Header()
+ headNumber := header.Number.Uint64()
+
+ // Make sure in the range (currentHeight-lowerLimitOfVoteBlockNumber, currentHeight+upperLimitOfVoteBlockNumber].
+ if targetNumber+lowerLimitOfVoteBlockNumber-1 < headNumber || targetNumber > headNumber+upperLimitOfVoteBlockNumber {
+ log.Debug("BlockNumber of vote is outside the range of header-256~header+11, will be discarded")
+ return false
+ }
+
+ voteData := &types.VoteData{
+ TargetNumber: targetNumber,
+ TargetHash: targetHash,
+ }
+
+ var votes map[common.Hash]*VoteBox
+ var votesPq *votesPriorityQueue
+ isFutureVote := false
+
+ voteBlock := pool.chain.GetHeaderByHash(targetHash)
+ if voteBlock == nil {
+ votes = pool.futureVotes
+ votesPq = pool.futureVotesPq
+ isFutureVote = true
+ } else {
+ votes = pool.curVotes
+ votesPq = pool.curVotesPq
+ }
+
+ voteHash := vote.Hash()
+ if ok := pool.basicVerify(vote, headNumber, votes, isFutureVote, voteHash); !ok {
+ return false
+ }
+
+ if !isFutureVote {
+ // Verify if the vote comes from valid validators based on voteAddress (BLSPublicKey), only verify curVotes here, will verify futureVotes in transfer process.
+ if pool.engine.VerifyVote(pool.chain, vote) != nil {
+ return false
+ }
+
+ // Send vote for handler usage of broadcasting to peers.
+ voteEv := core.NewVoteEvent{Vote: vote}
+ pool.votesFeed.Send(voteEv)
+ }
+
+ pool.putVote(votes, votesPq, vote, voteData, voteHash, isFutureVote)
+
+ return true
+}
+
+func (pool *VotePool) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription {
+ return pool.scope.Track(pool.votesFeed.Subscribe(ch))
+}
+
+func (pool *VotePool) putVote(m map[common.Hash]*VoteBox, votesPq *votesPriorityQueue, vote *types.VoteEnvelope, voteData *types.VoteData, voteHash common.Hash, isFutureVote bool) {
+ targetHash := vote.Data.TargetHash
+ targetNumber := vote.Data.TargetNumber
+
+ log.Debug("The vote info to put is:", "voteBlockNumber", targetNumber, "voteBlockHash", targetHash)
+
+ pool.mu.Lock()
+ defer pool.mu.Unlock()
+ if _, ok := m[targetHash]; !ok {
+ // Push into votes priorityQueue if not exist in corresponding votes Map.
+ // To be noted: will not put into priorityQueue if exists in map to avoid duplicate element with the same voteData.
+ heap.Push(votesPq, voteData)
+ voteBox := &VoteBox{
+ blockNumber: targetNumber,
+ voteMessages: make([]*types.VoteEnvelope, 0, maxFutureVoteAmountPerBlock),
+ }
+ m[targetHash] = voteBox
+
+ if isFutureVote {
+ localFutureVotesPqGauge.Update(int64(votesPq.Len()))
+ } else {
+ localCurVotesPqGauge.Update(int64(votesPq.Len()))
+ }
+ }
+
+ // Put into corresponding votes map.
+ m[targetHash].voteMessages = append(m[targetHash].voteMessages, vote)
+ // Add into received vote to avoid future duplicated vote comes.
+ pool.receivedVotes.Add(voteHash)
+ log.Debug("VoteHash put into votepool is:", "voteHash", voteHash)
+
+ if isFutureVote {
+ localFutureVotesGauge.Inc(1)
+ } else {
+ localCurVotesGauge.Inc(1)
+ }
+ localReceivedVotesGauge.Update(int64(pool.receivedVotes.Cardinality()))
+}
+
+func (pool *VotePool) transferVotesFromFutureToCur(latestBlockHeader *types.Header) {
+ pool.mu.Lock()
+ defer pool.mu.Unlock()
+
+ futurePq := pool.futureVotesPq
+ latestBlockNumber := latestBlockHeader.Number.Uint64()
+
+ // For vote in the range [,latestBlockNumber-11), transfer to cur if valid.
+ for futurePq.Len() > 0 && futurePq.Peek().TargetNumber+upperLimitOfVoteBlockNumber < latestBlockNumber {
+ blockHash := futurePq.Peek().TargetHash
+ pool.transfer(blockHash)
+ }
+
+ // For vote in the range [latestBlockNumber-11,latestBlockNumber], only transfer the vote inside the local fork.
+ futurePqBuffer := make([]*types.VoteData, 0)
+ for futurePq.Len() > 0 && futurePq.Peek().TargetNumber <= latestBlockNumber {
+ blockHash := futurePq.Peek().TargetHash
+ header := pool.chain.GetHeaderByHash(blockHash)
+ if header == nil {
+ // Put into pq buffer used for later put again into futurePq
+ futurePqBuffer = append(futurePqBuffer, heap.Pop(futurePq).(*types.VoteData))
+ continue
+ }
+ pool.transfer(blockHash)
+ }
+
+ for _, voteData := range futurePqBuffer {
+ heap.Push(futurePq, voteData)
+ }
+}
+
+func (pool *VotePool) transfer(blockHash common.Hash) {
+ curPq, futurePq := pool.curVotesPq, pool.futureVotesPq
+ curVotes, futureVotes := pool.curVotes, pool.futureVotes
+ voteData := heap.Pop(futurePq)
+
+ defer localFutureVotesPqGauge.Update(int64(futurePq.Len()))
+
+ voteBox, ok := futureVotes[blockHash]
+ if !ok {
+ return
+ }
+
+ validVotes := make([]*types.VoteEnvelope, 0, len(voteBox.voteMessages))
+ for _, vote := range voteBox.voteMessages {
+ // Verify if the vote comes from valid validators based on voteAddress (BLSPublicKey).
+ if pool.engine.VerifyVote(pool.chain, vote) != nil {
+ continue
+ }
+
+ // In the process of transfer, send valid vote to votes channel for handler usage
+ voteEv := core.NewVoteEvent{Vote: vote}
+ pool.votesFeed.Send(voteEv)
+ validVotes = append(validVotes, vote)
+ }
+
+ // may len(curVotes[blockHash].voteMessages) extra maxCurVoteAmountPerBlock, but it doesn't matter
+ if _, ok := curVotes[blockHash]; !ok {
+ heap.Push(curPq, voteData)
+ curVotes[blockHash] = &VoteBox{voteBox.blockNumber, validVotes}
+ localCurVotesPqGauge.Update(int64(curPq.Len()))
+ } else {
+ curVotes[blockHash].voteMessages = append(curVotes[blockHash].voteMessages, validVotes...)
+ }
+
+ delete(futureVotes, blockHash)
+
+ localCurVotesGauge.Inc(int64(len(validVotes)))
+ localFutureVotesGauge.Dec(int64(len(voteBox.voteMessages)))
+}
+
+// Prune old data of duplicationSet, curVotePq and curVotesMap.
+func (pool *VotePool) prune(latestBlockNumber uint64) {
+ pool.mu.Lock()
+ defer pool.mu.Unlock()
+ curVotes := pool.curVotes
+ curVotesPq := pool.curVotesPq
+
+ // delete votes in the range [,latestBlockNumber-lowerLimitOfVoteBlockNumber]
+ for curVotesPq.Len() > 0 && curVotesPq.Peek().TargetNumber+lowerLimitOfVoteBlockNumber-1 < latestBlockNumber {
+ // Prune curPriorityQueue.
+ blockHash := heap.Pop(curVotesPq).(*types.VoteData).TargetHash
+ localCurVotesPqGauge.Update(int64(curVotesPq.Len()))
+ if voteBox, ok := curVotes[blockHash]; ok {
+ voteMessages := voteBox.voteMessages
+ // Prune duplicationSet.
+ for _, voteMessage := range voteMessages {
+ voteHash := voteMessage.Hash()
+ pool.receivedVotes.Remove(voteHash)
+ }
+ // Prune curVotes Map.
+ delete(curVotes, blockHash)
+
+ localCurVotesGauge.Dec(int64(len(voteMessages)))
+ localReceivedVotesGauge.Update(int64(pool.receivedVotes.Cardinality()))
+ }
+ }
+}
+
+// GetVotes as batch.
+func (pool *VotePool) GetVotes() []*types.VoteEnvelope {
+ pool.mu.RLock()
+ defer pool.mu.RUnlock()
+
+ votesRes := make([]*types.VoteEnvelope, 0)
+ curVotes := pool.curVotes
+ for _, voteBox := range curVotes {
+ votesRes = append(votesRes, voteBox.voteMessages...)
+ }
+ return votesRes
+}
+
+func (pool *VotePool) FetchVoteByBlockHash(blockHash common.Hash) []*types.VoteEnvelope {
+ pool.mu.RLock()
+ defer pool.mu.RUnlock()
+ if _, ok := pool.curVotes[blockHash]; ok {
+ return pool.curVotes[blockHash].voteMessages
+ }
+ return nil
+}
+
+func (pool *VotePool) basicVerify(vote *types.VoteEnvelope, headNumber uint64, m map[common.Hash]*VoteBox, isFutureVote bool, voteHash common.Hash) bool {
+ targetHash := vote.Data.TargetHash
+ pool.mu.RLock()
+ defer pool.mu.RUnlock()
+
+ // Check duplicate voteMessage firstly.
+ if pool.receivedVotes.Contains(voteHash) {
+ log.Debug("Vote pool already contained the same vote", "voteHash", voteHash)
+ return false
+ }
+
+ // To prevent DOS attacks, make sure no more than 21 votes per blockHash if not futureVotes
+ // and no more than 50 votes per blockHash if futureVotes.
+ maxVoteAmountPerBlock := maxCurVoteAmountPerBlock
+ if isFutureVote {
+ maxVoteAmountPerBlock = maxFutureVoteAmountPerBlock
+ }
+ if voteBox, ok := m[targetHash]; ok {
+ if len(voteBox.voteMessages) >= maxVoteAmountPerBlock {
+ return false
+ }
+ }
+
+ // Verify bls signature.
+ if err := vote.Verify(); err != nil {
+ log.Error("Failed to verify voteMessage", "err", err)
+ return false
+ }
+
+ return true
+}
+
+func (pq votesPriorityQueue) Less(i, j int) bool {
+ return pq[i].TargetNumber < pq[j].TargetNumber
+}
+
+func (pq votesPriorityQueue) Len() int {
+ return len(pq)
+}
+
+func (pq votesPriorityQueue) Swap(i, j int) {
+ pq[i], pq[j] = pq[j], pq[i]
+}
+
+func (pq *votesPriorityQueue) Push(vote interface{}) {
+ curVote := vote.(*types.VoteData)
+ *pq = append(*pq, curVote)
+}
+
+func (pq *votesPriorityQueue) Pop() interface{} {
+ tmp := *pq
+ l := len(tmp)
+ var res interface{} = tmp[l-1]
+ *pq = tmp[:l-1]
+ return res
+}
+
+func (pq *votesPriorityQueue) Peek() *types.VoteData {
+ if pq.Len() == 0 {
+ return nil
+ }
+ return (*pq)[0]
+}
diff --git a/core/vote/vote_pool_test.go b/core/vote/vote_pool_test.go
new file mode 100644
index 0000000000..a1bcd8d232
--- /dev/null
+++ b/core/vote/vote_pool_test.go
@@ -0,0 +1,446 @@
+// 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 .
+
+package vote
+
+import (
+ "container/heap"
+ "context"
+ "encoding/json"
+ "fmt"
+ "io/ioutil"
+ "math/big"
+ "os"
+ "path/filepath"
+ "testing"
+ "time"
+
+ "github.com/google/uuid"
+ "github.com/prysmaticlabs/prysm/v3/crypto/bls"
+ "github.com/prysmaticlabs/prysm/v3/validator/accounts"
+ "github.com/prysmaticlabs/prysm/v3/validator/accounts/iface"
+ "github.com/prysmaticlabs/prysm/v3/validator/keymanager"
+ keystorev4 "github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/consensus"
+ "github.com/ethereum/go-ethereum/consensus/ethash"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/rawdb"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/params"
+)
+
+var (
+ // testKey is a private key to use for funding a tester account.
+ testKey, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
+
+ // testAddr is the Ethereum address of the tester account.
+ testAddr = crypto.PubkeyToAddress(testKey.PublicKey)
+
+ password = "secretPassword"
+
+ timeThreshold = 30
+)
+
+type mockPOSA struct {
+ consensus.PoSA
+}
+
+type mockInvalidPOSA struct {
+ consensus.PoSA
+}
+
+func (p *mockPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) {
+ parentHeader := chain.GetHeaderByHash(header.ParentHash)
+ if parentHeader == nil {
+ return 0, common.Hash{}, fmt.Errorf("unexpected error")
+ }
+ return parentHeader.Number.Uint64(), parentHeader.Hash(), nil
+}
+
+func (p *mockInvalidPOSA) GetJustifiedNumberAndHash(chain consensus.ChainHeaderReader, header *types.Header) (uint64, common.Hash, error) {
+ return 0, common.Hash{}, fmt.Errorf("not supported")
+}
+
+func (m *mockPOSA) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteEnvelope) error {
+ return nil
+}
+
+func (m *mockInvalidPOSA) VerifyVote(chain consensus.ChainHeaderReader, vote *types.VoteEnvelope) error {
+ return nil
+}
+
+func (m *mockPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
+ return true
+}
+
+func (m *mockInvalidPOSA) IsActiveValidatorAt(chain consensus.ChainHeaderReader, header *types.Header) bool {
+ return true
+}
+
+func (pool *VotePool) verifyStructureSizeOfVotePool(receivedVotes, curVotes, futureVotes, curVotesPq, futureVotesPq int) bool {
+ for i := 0; i < timeThreshold; i++ {
+ time.Sleep(1 * time.Second)
+ if pool.receivedVotes.Cardinality() == receivedVotes && len(pool.curVotes) == curVotes && len(pool.futureVotes) == futureVotes && pool.curVotesPq.Len() == curVotesPq && pool.futureVotesPq.Len() == futureVotesPq {
+ return true
+ }
+ }
+ return false
+}
+
+func (journal *VoteJournal) verifyJournal(size, lastLatestVoteNumber int) bool {
+ for i := 0; i < timeThreshold; i++ {
+ time.Sleep(1 * time.Second)
+ lastIndex, _ := journal.walLog.LastIndex()
+ firstIndex, _ := journal.walLog.FirstIndex()
+ if int(lastIndex)-int(firstIndex)+1 == size {
+ return true
+ }
+ lastVote, _ := journal.ReadVote(lastIndex)
+ if lastVote != nil && lastVote.Data.TargetNumber == uint64(lastLatestVoteNumber) {
+ return true
+ }
+ }
+ return false
+}
+
+func TestValidVotePool(t *testing.T) {
+ testVotePool(t, true)
+}
+
+func TestInvalidVotePool(t *testing.T) {
+ testVotePool(t, false)
+}
+
+func testVotePool(t *testing.T, isValidRules bool) {
+ walletPasswordDir, walletDir := setUpKeyManager(t)
+
+ // Create a database pre-initialize with a genesis block
+ db := rawdb.NewMemoryDatabase()
+ (&core.Genesis{
+ Config: params.TestChainConfig,
+ Alloc: core.GenesisAlloc{testAddr: {Balance: big.NewInt(1000000)}},
+ }).MustCommit(db)
+
+ chain, _ := core.NewBlockChain(db, nil, params.TestChainConfig, ethash.NewFullFaker(), vm.Config{}, nil, nil)
+
+ mux := new(event.TypeMux)
+
+ var mockEngine consensus.PoSA
+ if isValidRules {
+ mockEngine = &mockPOSA{}
+ } else {
+ mockEngine = &mockInvalidPOSA{}
+ }
+
+ // Create vote pool
+ votePool := NewVotePool(params.TestChainConfig, chain, mockEngine)
+
+ // Create vote manager
+ // Create a temporary file for the votes journal
+ file, err := ioutil.TempFile("", "")
+ if err != nil {
+ t.Fatalf("failed to create temporary file path: %v", err)
+ }
+ journal := file.Name()
+ defer os.Remove(journal)
+
+ // Clean up the temporary file, we only need the path for now
+ file.Close()
+ os.Remove(journal)
+
+ voteManager, err := NewVoteManager(mux, params.TestChainConfig, chain, votePool, journal, walletPasswordDir, walletDir, mockEngine)
+ if err != nil {
+ t.Fatalf("failed to create vote managers")
+ }
+
+ voteJournal := voteManager.journal
+
+ // Send the done event of downloader
+ time.Sleep(10 * time.Millisecond)
+ mux.Post(downloader.DoneEvent{})
+
+ bs, _ := core.GenerateChain(params.TestChainConfig, chain.Genesis(), ethash.NewFaker(), db, 1, nil)
+ if _, err := chain.InsertChain(bs); err != nil {
+ panic(err)
+ }
+ for i := 0; i < 10; i++ {
+ bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil)
+ if _, err := chain.InsertChain(bs); err != nil {
+ panic(err)
+ }
+ }
+
+ if !isValidRules {
+ if votePool.verifyStructureSizeOfVotePool(11, 11, 0, 11, 0) {
+ t.Fatalf("put vote failed")
+ }
+ return
+ }
+
+ if !votePool.verifyStructureSizeOfVotePool(11, 11, 0, 11, 0) {
+ t.Fatalf("put vote failed")
+ }
+
+ // Verify if votesPq is min heap
+ votesPq := votePool.curVotesPq
+ pqBuffer := make([]*types.VoteData, 0)
+ lastVotedBlockNumber := uint64(0)
+ for votesPq.Len() > 0 {
+ voteData := heap.Pop(votesPq).(*types.VoteData)
+ if voteData.TargetNumber < lastVotedBlockNumber {
+ t.Fatalf("votesPq verification failed")
+ }
+ lastVotedBlockNumber = voteData.TargetNumber
+ pqBuffer = append(pqBuffer, voteData)
+ }
+ for _, voteData := range pqBuffer {
+ heap.Push(votesPq, voteData)
+ }
+
+ // Verify journal
+ if !voteJournal.verifyJournal(11, 11) {
+ t.Fatalf("journal failed")
+ }
+
+ bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil)
+ if _, err := chain.InsertChain(bs); err != nil {
+ panic(err)
+ }
+
+ if !votePool.verifyStructureSizeOfVotePool(12, 12, 0, 12, 0) {
+ t.Fatalf("put vote failed")
+ }
+
+ // Verify journal
+ if !voteJournal.verifyJournal(12, 12) {
+ t.Fatalf("journal failed")
+ }
+
+ for i := 0; i < 256; i++ {
+ bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil)
+ if _, err := chain.InsertChain(bs); err != nil {
+ panic(err)
+ }
+ }
+
+ // Verify journal
+ if !voteJournal.verifyJournal(268, 268) {
+ t.Fatalf("journal failed")
+ }
+
+ // currently chain size is 268, and votePool should be pruned, so vote pool size should be 256!
+ if !votePool.verifyStructureSizeOfVotePool(256, 256, 0, 256, 0) {
+ t.Fatalf("put vote failed")
+ }
+
+ // Test invalid vote whose number larger than latestHeader + 13
+ invalidVote := &types.VoteEnvelope{
+ Data: &types.VoteData{
+ TargetNumber: 1000,
+ },
+ }
+ voteManager.pool.PutVote(invalidVote)
+
+ if !votePool.verifyStructureSizeOfVotePool(256, 256, 0, 256, 0) {
+ t.Fatalf("put vote failed")
+ }
+
+ votes := votePool.GetVotes()
+ if len(votes) != 256 {
+ t.Fatalf("get votes failed")
+ }
+
+ // Verify journal
+ if !voteJournal.verifyJournal(268, 268) {
+ t.Fatalf("journal failed")
+ }
+
+ // Test future votes scenario: votes number within latestBlockHeader ~ latestBlockHeader + 13
+ futureVote := &types.VoteEnvelope{
+ Data: &types.VoteData{
+ TargetNumber: 279,
+ },
+ }
+ if err := voteManager.signer.SignVote(futureVote); err != nil {
+ t.Fatalf("sign vote failed")
+ }
+ voteManager.pool.PutVote(futureVote)
+
+ if !votePool.verifyStructureSizeOfVotePool(257, 256, 1, 256, 1) {
+ t.Fatalf("put vote failed")
+ }
+
+ // Verify journal
+ if !voteJournal.verifyJournal(268, 268) {
+ t.Fatalf("journal failed")
+ }
+
+ // Test duplicate vote case, shouldn'd be put into vote pool
+ duplicateVote := &types.VoteEnvelope{
+ Data: &types.VoteData{
+ TargetNumber: 279,
+ },
+ }
+ if err := voteManager.signer.SignVote(duplicateVote); err != nil {
+ t.Fatalf("sign vote failed")
+ }
+ voteManager.pool.PutVote(duplicateVote)
+
+ if !votePool.verifyStructureSizeOfVotePool(257, 256, 1, 256, 1) {
+ t.Fatalf("put vote failed")
+ }
+
+ // Verify journal
+ if !voteJournal.verifyJournal(268, 268) {
+ t.Fatalf("journal failed")
+ }
+
+ // Test future votes larger than latestBlockNumber + 13 should be rejected
+ futureVote = &types.VoteEnvelope{
+ Data: &types.VoteData{
+ TargetNumber: 282,
+ TargetHash: common.Hash{},
+ },
+ }
+ voteManager.pool.PutVote(futureVote)
+ if !votePool.verifyStructureSizeOfVotePool(257, 256, 1, 256, 1) {
+ t.Fatalf("put vote failed")
+ }
+
+ // Test transfer votes from future to cur, latest block header is #288 after the following generation
+ // For the above BlockNumber 279, it did not have blockHash, should be assigned as well below.
+ curNumber := 268
+ var futureBlockHash common.Hash
+ for i := 0; i < 20; i++ {
+ bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil)
+ curNumber += 1
+ if curNumber == 279 {
+ futureBlockHash = bs[0].Hash()
+ futureVotesMap := votePool.futureVotes
+ voteBox := futureVotesMap[common.Hash{}]
+ futureVotesMap[futureBlockHash] = voteBox
+ delete(futureVotesMap, common.Hash{})
+ futureVotesPq := votePool.futureVotesPq
+ futureVotesPq.Peek().TargetHash = futureBlockHash
+ }
+ if _, err := chain.InsertChain(bs); err != nil {
+ panic(err)
+ }
+ }
+
+ for i := 0; i < timeThreshold; i++ {
+ time.Sleep(1 * time.Second)
+ _, ok := votePool.curVotes[futureBlockHash]
+ if ok && len(votePool.curVotes[futureBlockHash].voteMessages) == 2 {
+ break
+ }
+ }
+ if votePool.curVotes[futureBlockHash] == nil || len(votePool.curVotes[futureBlockHash].voteMessages) != 2 {
+ t.Fatalf("transfer vote failed")
+ }
+
+ // Pruner will keep the size of votePool as latestBlockHeader-255~latestBlockHeader, then final result should be 256!
+ if !votePool.verifyStructureSizeOfVotePool(257, 256, 0, 256, 0) {
+ t.Fatalf("put vote failed")
+ }
+
+ // Verify journal
+ if !voteJournal.verifyJournal(288, 288) {
+ t.Fatalf("journal failed")
+ }
+
+ for i := 0; i < 224; i++ {
+ bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil)
+ if _, err := chain.InsertChain(bs); err != nil {
+ panic(err)
+ }
+ }
+
+ // Verify journal
+ if !voteJournal.verifyJournal(512, 512) {
+ t.Fatalf("journal failed")
+ }
+
+ bs, _ = core.GenerateChain(params.TestChainConfig, bs[len(bs)-1], ethash.NewFaker(), db, 1, nil)
+ if _, err := chain.InsertChain(bs); err != nil {
+ panic(err)
+ }
+
+ // Verify if journal no longer than 512
+ if !voteJournal.verifyJournal(512, 513) {
+ t.Fatalf("journal failed")
+ }
+}
+
+func setUpKeyManager(t *testing.T) (string, string) {
+ walletDir := filepath.Join(t.TempDir(), "wallet")
+ opts := []accounts.Option{}
+ opts = append(opts, accounts.WithWalletDir(walletDir))
+ opts = append(opts, accounts.WithWalletPassword(password))
+ opts = append(opts, accounts.WithKeymanagerType(keymanager.Local))
+ opts = append(opts, accounts.WithSkipMnemonicConfirm(true))
+ acc, err := accounts.NewCLIManager(opts...)
+ if err != nil {
+ t.Fatalf("New Accounts CLI Manager failed: %v.", err)
+ }
+ walletPasswordDir := filepath.Join(t.TempDir(), "password")
+ if err := os.MkdirAll(filepath.Dir(walletPasswordDir), 0700); err != nil {
+ t.Fatalf("failed to create walletPassword dir: %v", err)
+ }
+ if err := ioutil.WriteFile(walletPasswordDir, []byte(password), 0600); err != nil {
+ t.Fatalf("failed to write wallet password dir: %v", err)
+ }
+
+ w, err := acc.WalletCreate(context.Background())
+ if err != nil {
+ t.Fatalf("failed to create wallet: %v", err)
+ }
+ km, _ := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
+ k, _ := km.(keymanager.Importer)
+ secretKey, _ := bls.RandKey()
+ encryptor := keystorev4.New()
+ pubKeyBytes := secretKey.PublicKey().Marshal()
+ cryptoFields, err := encryptor.Encrypt(secretKey.Marshal(), password)
+ if err != nil {
+ t.Fatalf("failed: %v", err)
+ }
+
+ id, _ := uuid.NewRandom()
+ keystore := &keymanager.Keystore{
+ Crypto: cryptoFields,
+ ID: id.String(),
+ Pubkey: fmt.Sprintf("%x", pubKeyBytes),
+ Version: encryptor.Version(),
+ Name: encryptor.Name(),
+ }
+
+ encodedFile, _ := json.MarshalIndent(keystore, "", "\t")
+ keyStoreDir := filepath.Join(t.TempDir(), "keystore")
+ keystoreFile, _ := os.Create(fmt.Sprintf("%s/keystore-%s.json", keyStoreDir, "publichh"))
+ keystoreFile.Write(encodedFile)
+ accounts.ImportAccounts(context.Background(), &accounts.ImportAccountsConfig{
+ Importer: k,
+ Keystores: []*keymanager.Keystore{keystore},
+ AccountPassword: password,
+ })
+ return walletPasswordDir, walletDir
+}
diff --git a/core/vote/vote_signer.go b/core/vote/vote_signer.go
new file mode 100644
index 0000000000..1ea7c95f14
--- /dev/null
+++ b/core/vote/vote_signer.go
@@ -0,0 +1,110 @@
+package vote
+
+import (
+ "context"
+ "fmt"
+ "io/ioutil"
+ "time"
+
+ "github.com/pkg/errors"
+
+ "github.com/prysmaticlabs/prysm/v3/crypto/bls"
+ validatorpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1/validator-client"
+ "github.com/prysmaticlabs/prysm/v3/validator/accounts/iface"
+ "github.com/prysmaticlabs/prysm/v3/validator/accounts/wallet"
+ "github.com/prysmaticlabs/prysm/v3/validator/keymanager"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/metrics"
+)
+
+const (
+ voteSignerTimeout = time.Second * 5
+)
+
+type VoteSigner struct {
+ km *keymanager.IKeymanager
+ pubKey [48]byte
+}
+
+func NewVoteSigner(blsPasswordPath, blsWalletPath string) (*VoteSigner, error) {
+ dirExists, err := wallet.Exists(blsWalletPath)
+ if err != nil {
+ log.Error("Check BLS wallet exists", "err", err)
+ return nil, err
+ }
+ if !dirExists {
+ log.Error("BLS wallet did not exists.")
+ return nil, fmt.Errorf("BLS wallet did not exists.")
+ }
+
+ walletPassword, err := ioutil.ReadFile(blsPasswordPath)
+ if err != nil {
+ log.Error("Read BLS wallet password", "err", err)
+ return nil, err
+ }
+ log.Info("Read BLS wallet password successfully")
+
+ w, err := wallet.OpenWallet(context.Background(), &wallet.Config{
+ WalletDir: blsWalletPath,
+ WalletPassword: string(walletPassword),
+ })
+ if err != nil {
+ log.Error("Open BLS wallet failed", "err", err)
+ return nil, err
+ }
+ log.Info("Open BLS wallet successfully")
+
+ km, err := w.InitializeKeymanager(context.Background(), iface.InitKeymanagerConfig{ListenForChanges: false})
+ if err != nil {
+ log.Error("Initialize key manager failed", "err", err)
+ return nil, err
+ }
+ log.Info("Initialized keymanager successfully")
+
+ ctx, cancel := context.WithTimeout(context.Background(), voteSignerTimeout)
+ defer cancel()
+
+ pubKeys, err := km.FetchValidatingPublicKeys(ctx)
+ if err != nil {
+ return nil, errors.Wrap(err, "could not fetch validating public keys")
+ }
+
+ return &VoteSigner{
+ km: &km,
+ pubKey: pubKeys[0],
+ }, nil
+}
+
+func (signer *VoteSigner) SignVote(vote *types.VoteEnvelope) error {
+ // Sign the vote, fetch the first pubKey as validator's bls public key.
+ pubKey := signer.pubKey
+ blsPubKey, err := bls.PublicKeyFromBytes(pubKey[:])
+ if err != nil {
+ return errors.Wrap(err, "convert public key from bytes to bls failed")
+ }
+
+ voteDataHash := vote.Data.Hash()
+
+ ctx, cancel := context.WithTimeout(context.Background(), voteSignerTimeout)
+ defer cancel()
+
+ signature, err := (*signer.km).Sign(ctx, &validatorpb.SignRequest{
+ PublicKey: pubKey[:],
+ SigningRoot: voteDataHash[:],
+ })
+ if err != nil {
+ return err
+ }
+
+ copy(vote.VoteAddress[:], blsPubKey.Marshal()[:])
+ copy(vote.Signature[:], signature.Marshal()[:])
+ return nil
+}
+
+// Metrics to indicate if there's any failed signing.
+func votesSigningErrorMetric(blockNumber uint64, blockHash common.Hash) metrics.Gauge {
+ return metrics.GetOrRegisterGauge(fmt.Sprintf("voteSigning/blockNumber/%d/blockHash/%s", blockNumber, blockHash), nil)
+}
diff --git a/docker/Dockerfile b/docker/Dockerfile
index b703371707..484a12f45b 100644
--- a/docker/Dockerfile
+++ b/docker/Dockerfile
@@ -1,9 +1,11 @@
FROM golang:1.19-alpine as bsc
-RUN apk add --no-cache make gcc musl-dev linux-headers git bash
+RUN apk add --no-cache make cmake gcc musl-dev linux-headers git bash build-base libc-dev
ADD . /bsc
WORKDIR /bsc
+ENV CGO_CFLAGS="-O -D__BLST_PORTABLE__"
+ENV CGO_CFLAGS_ALLOW="-O -D__BLST_PORTABLE__"
RUN make geth
RUN mv /bsc/build/bin/geth /usr/local/bin/geth
@@ -12,7 +14,7 @@ ENTRYPOINT [ "/usr/local/bin/geth" ]
FROM ethereum/solc:0.6.4-alpine as bsc-genesis
-RUN apk add --d --no-cache ca-certificates npm nodejs bash alpine-sdk
+RUN apk add --no-cache ca-certificates npm nodejs bash alpine-sdk expect
RUN git clone https://github.com/binance-chain/bsc-genesis-contract.git /root/genesis \
&& cd /root/genesis && npm install
diff --git a/docker/Dockerfile.truffle b/docker/Dockerfile.truffle
index 28ab9da393..93675241c2 100644
--- a/docker/Dockerfile.truffle
+++ b/docker/Dockerfile.truffle
@@ -1,6 +1,6 @@
FROM ethereum/solc:0.6.4-alpine
-RUN apk add --d --no-cache ca-certificates npm nodejs bash alpine-sdk git
+RUN apk add --no-cache ca-certificates npm nodejs bash alpine-sdk git
RUN git clone https://github.com/binance-chain/canonical-upgradeable-bep20.git /usr/app/canonical-upgradeable-bep20
diff --git a/eth/api.go b/eth/api.go
index f81dfa922b..f7e16b9d61 100644
--- a/eth/api.go
+++ b/eth/api.go
@@ -282,16 +282,24 @@ func (api *PublicDebugAPI) DumpBlock(blockNr rpc.BlockNumber) (state.Dump, error
_, stateDb := api.eth.miner.Pending()
return stateDb.RawDump(opts), nil
}
- var block *types.Block
+ var header *types.Header
if blockNr == rpc.LatestBlockNumber {
- block = api.eth.blockchain.CurrentBlock()
+ header = api.eth.blockchain.CurrentHeader()
+ } else if blockNr == rpc.FinalizedBlockNumber {
+ header = api.eth.blockchain.CurrentFinalBlock()
+ } else if blockNr == rpc.SafeBlockNumber {
+ header = api.eth.blockchain.CurrentSafeBlock()
} else {
- block = api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
+ block := api.eth.blockchain.GetBlockByNumber(uint64(blockNr))
+ if block == nil {
+ return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
+ }
+ header = block.Header()
}
- if block == nil {
+ if header == nil {
return state.Dump{}, fmt.Errorf("block #%d not found", blockNr)
}
- stateDb, err := api.eth.BlockChain().StateAt(block.Root())
+ stateDb, err := api.eth.BlockChain().StateAt(header.Root)
if err != nil {
return state.Dump{}, err
}
@@ -370,16 +378,24 @@ func (api *PublicDebugAPI) AccountRange(blockNrOrHash rpc.BlockNumberOrHash, sta
// the miner and operate on those
_, stateDb = api.eth.miner.Pending()
} else {
- var block *types.Block
+ var header *types.Header
if number == rpc.LatestBlockNumber {
- block = api.eth.blockchain.CurrentBlock()
+ header = api.eth.blockchain.CurrentHeader()
+ } else if number == rpc.FinalizedBlockNumber {
+ header = api.eth.blockchain.CurrentFinalBlock()
+ } else if number == rpc.SafeBlockNumber {
+ header = api.eth.blockchain.CurrentSafeBlock()
} else {
- block = api.eth.blockchain.GetBlockByNumber(uint64(number))
+ block := api.eth.blockchain.GetBlockByNumber(uint64(number))
+ if block == nil {
+ return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
+ }
+ header = block.Header()
}
- if block == nil {
+ if header == nil {
return state.IteratorDump{}, fmt.Errorf("block #%d not found", number)
}
- stateDb, err = api.eth.BlockChain().StateAt(block.Root())
+ stateDb, err = api.eth.BlockChain().StateAt(header.Root)
if err != nil {
return state.IteratorDump{}, err
}
diff --git a/eth/api_backend.go b/eth/api_backend.go
index 7c0f1f0482..dc48c3f073 100644
--- a/eth/api_backend.go
+++ b/eth/api_backend.go
@@ -19,6 +19,7 @@ package eth
import (
"context"
"errors"
+ "fmt"
"math/big"
"time"
@@ -32,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/state"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/gasprice"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
@@ -70,7 +72,21 @@ func (b *EthAPIBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumb
}
// Otherwise resolve and return the block
if number == rpc.LatestBlockNumber {
- return b.eth.blockchain.CurrentBlock().Header(), nil
+ return b.eth.blockchain.CurrentHeader(), nil
+ }
+ if number == rpc.FinalizedBlockNumber {
+ block := b.eth.blockchain.CurrentFinalBlock()
+ if block != nil {
+ return block, nil
+ }
+ return nil, errors.New("finalized block not found")
+ }
+ if number == rpc.SafeBlockNumber {
+ block := b.eth.blockchain.CurrentSafeBlock()
+ if block != nil {
+ return block, nil
+ }
+ return nil, errors.New("safe block not found")
}
return b.eth.blockchain.GetHeaderByNumber(uint64(number)), nil
}
@@ -106,6 +122,20 @@ func (b *EthAPIBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumbe
if number == rpc.LatestBlockNumber {
return b.eth.blockchain.CurrentBlock(), nil
}
+ if number == rpc.FinalizedBlockNumber {
+ header := b.eth.blockchain.CurrentFinalBlock()
+ if header == nil {
+ return nil, fmt.Errorf("block #%d not found", number)
+ }
+ return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
+ }
+ if number == rpc.SafeBlockNumber {
+ header := b.eth.blockchain.CurrentSafeBlock()
+ if header == nil {
+ return nil, fmt.Errorf("block #%d not found", number)
+ }
+ return b.eth.blockchain.GetBlock(header.Hash(), header.Number.Uint64()), nil
+ }
return b.eth.blockchain.GetBlockByNumber(uint64(number)), nil
}
@@ -227,6 +257,10 @@ func (b *EthAPIBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) e
return b.eth.BlockChain().SubscribeChainHeadEvent(ch)
}
+func (b *EthAPIBackend) SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription {
+ return b.eth.BlockChain().SubscribeFinalizedHeaderEvent(ch)
+}
+
func (b *EthAPIBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
return b.eth.BlockChain().SubscribeChainSideEvent(ch)
}
@@ -281,6 +315,17 @@ func (b *EthAPIBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.S
return b.eth.TxPool().SubscribeNewTxsEvent(ch)
}
+func (b *EthAPIBackend) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription {
+ if b.eth.VotePool() == nil {
+ return nil
+ }
+ return b.eth.VotePool().SubscribeNewVoteEvent(ch)
+}
+
+func (b *EthAPIBackend) Downloader() *downloader.Downloader {
+ return b.eth.Downloader()
+}
+
func (b *EthAPIBackend) SyncProgress() ethereum.SyncProgress {
return b.eth.Downloader().Progress()
}
diff --git a/eth/backend.go b/eth/backend.go
index fc0ca6534c..25d0f908b3 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -39,10 +39,12 @@ import (
"github.com/ethereum/go-ethereum/core/state/pruner"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
+ "github.com/ethereum/go-ethereum/core/vote"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/ethconfig"
"github.com/ethereum/go-ethereum/eth/filters"
"github.com/ethereum/go-ethereum/eth/gasprice"
+ "github.com/ethereum/go-ethereum/eth/protocols/bsc"
"github.com/ethereum/go-ethereum/eth/protocols/diff"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
@@ -77,6 +79,7 @@ type Ethereum struct {
ethDialCandidates enode.Iterator
snapDialCandidates enode.Iterator
trustDialCandidates enode.Iterator
+ bscDialCandidates enode.Iterator
merger *consensus.Merger
// DB interfaces
@@ -104,6 +107,8 @@ type Ethereum struct {
lock sync.RWMutex // Protects the variadic fields (e.g. gas price and etherbase)
shutdownTracker *shutdowncheck.ShutdownTracker // Tracks if and when the node has shutdown ungracefully
+
+ votePool *vote.VotePool
}
// New creates a new Ethereum object (including the
@@ -244,6 +249,30 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}
eth.txPool = core.NewTxPool(config.TxPool, chainConfig, eth.blockchain)
+ conf := stack.Config()
+ blsPasswordPath := stack.ResolvePath(conf.BLSPasswordFile)
+ blsWalletPath := stack.ResolvePath(conf.BLSWalletDir)
+ voteJournalPath := stack.ResolvePath(conf.VoteJournalDir)
+
+ // Create voteManager instance
+ if posa, ok := eth.engine.(consensus.PoSA); ok {
+ // Create votePool instance
+ votePool := vote.NewVotePool(chainConfig, eth.blockchain, posa)
+ eth.votePool = votePool
+ if parlia, ok := eth.engine.(*parlia.Parlia); ok {
+ parlia.VotePool = votePool
+ } else {
+ return nil, fmt.Errorf("Engine is not Parlia type")
+ }
+ log.Info("Create votePool successfully")
+
+ if _, err := vote.NewVoteManager(eth.EventMux(), chainConfig, eth.blockchain, votePool, voteJournalPath, blsPasswordPath, blsWalletPath, posa); err != nil {
+ log.Error("Failed to Initialize voteManager", "err", err)
+ return nil, err
+ }
+ log.Info("Create voteManager successfully")
+ }
+
// Permit the downloader to use the trie cache allowance during fast sync
cacheLimit := cacheConfig.TrieCleanLimit + cacheConfig.TrieDirtyLimit + cacheConfig.SnapshotLimit
checkpoint := config.Checkpoint
@@ -269,6 +298,9 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
}); err != nil {
return nil, err
}
+ if eth.votePool != nil {
+ eth.handler.votepool = eth.votePool
+ }
eth.miner = miner.New(eth, &config.Miner, chainConfig, eth.EventMux(), eth.engine, eth.isLocalBlock)
eth.miner.SetExtra(makeExtraData(config.Miner.ExtraData))
@@ -293,6 +325,10 @@ func New(stack *node.Node, config *ethconfig.Config) (*Ethereum, error) {
if err != nil {
return nil, err
}
+ eth.bscDialCandidates, err = dnsclient.NewIterator(eth.config.BscDiscoveryURLs...)
+ if err != nil {
+ return nil, err
+ }
// Start the RPC service
eth.netRPCService = ethapi.NewPublicNetAPI(eth.p2pServer, config.NetworkId)
@@ -558,6 +594,7 @@ func (s *Ethereum) Miner() *miner.Miner { return s.miner }
func (s *Ethereum) AccountManager() *accounts.Manager { return s.accountManager }
func (s *Ethereum) BlockChain() *core.BlockChain { return s.blockchain }
func (s *Ethereum) TxPool() *core.TxPool { return s.txPool }
+func (s *Ethereum) VotePool() *vote.VotePool { return s.votePool }
func (s *Ethereum) EventMux() *event.TypeMux { return s.eventMux }
func (s *Ethereum) Engine() consensus.Engine { return s.engine }
func (s *Ethereum) ChainDb() ethdb.Database { return s.chainDb }
@@ -587,6 +624,9 @@ func (s *Ethereum) Protocols() []p2p.Protocol {
if s.config.EnableTrustProtocol {
protos = append(protos, trust.MakeProtocols((*trustHandler)(s.handler), s.snapDialCandidates)...)
}
+ if !s.config.DisableBscProtocol {
+ protos = append(protos, bsc.MakeProtocols((*bscHandler)(s.handler), s.bscDialCandidates)...)
+ }
return protos
}
@@ -621,6 +661,7 @@ func (s *Ethereum) Stop() error {
s.ethDialCandidates.Close()
s.snapDialCandidates.Close()
s.trustDialCandidates.Close()
+ s.bscDialCandidates.Close()
s.handler.Stop()
// Then stop everything else.
diff --git a/eth/downloader/downloader.go b/eth/downloader/downloader.go
index a5ac153afc..70dc7e15b9 100644
--- a/eth/downloader/downloader.go
+++ b/eth/downloader/downloader.go
@@ -374,8 +374,8 @@ func (d *Downloader) UnregisterPeer(id string) error {
return nil
}
-// Synchronise tries to sync up our local block chain with a remote peer, both
-// adding various sanity checks as well as wrapping it with various log entries.
+// Synchronise tries to sync up our local blockchain with a remote peer, both
+// adding various sanity checks and wrapping it with various log entries.
func (d *Downloader) Synchronise(id string, head common.Hash, td *big.Int, mode SyncMode) error {
err := d.synchronise(id, head, td, mode)
diff --git a/eth/ethconfig/config.go b/eth/ethconfig/config.go
index 8d032260a7..29bb597410 100644
--- a/eth/ethconfig/config.go
+++ b/eth/ethconfig/config.go
@@ -144,12 +144,14 @@ type Config struct {
EthDiscoveryURLs []string
SnapDiscoveryURLs []string
TrustDiscoveryURLs []string
+ BscDiscoveryURLs []string
NoPruning bool // Whether to disable pruning and flush everything to disk
DirectBroadcast bool
DisableSnapProtocol bool //Whether disable snap protocol
DisableDiffProtocol bool //Whether disable diff protocol
EnableTrustProtocol bool //Whether enable trust protocol
+ DisableBscProtocol bool //Whether disable bsc protocol
DiffSync bool // Whether support diff sync
PipeCommit bool
RangeLimit bool
diff --git a/eth/ethconfig/gen_config.go b/eth/ethconfig/gen_config.go
index c0d44ce141..13891c04c9 100644
--- a/eth/ethconfig/gen_config.go
+++ b/eth/ethconfig/gen_config.go
@@ -18,64 +18,66 @@ import (
// MarshalTOML marshals as TOML.
func (c Config) MarshalTOML() (interface{}, error) {
type Config struct {
- Genesis *core.Genesis `toml:",omitempty"`
- NetworkId uint64
- SyncMode downloader.SyncMode
- DisablePeerTxBroadcast bool
- EthDiscoveryURLs []string
- SnapDiscoveryURLs []string
- TrustDiscoveryURLs []string
- NoPruning bool
- NoPrefetch bool
- DirectBroadcast bool
- DisableSnapProtocol bool
- DisableDiffProtocol bool
- EnableTrustProtocol bool
- DiffSync bool
- RangeLimit bool
- TxLookupLimit uint64 `toml:",omitempty"`
- Whitelist map[uint64]common.Hash `toml:"-"`
- LightServ int `toml:",omitempty"`
- LightIngress int `toml:",omitempty"`
- LightEgress int `toml:",omitempty"`
- LightPeers int `toml:",omitempty"`
- LightNoPrune bool `toml:",omitempty"`
- LightNoSyncServe bool `toml:",omitempty"`
- SyncFromCheckpoint bool `toml:",omitempty"`
- UltraLightServers []string `toml:",omitempty"`
- UltraLightFraction int `toml:",omitempty"`
- UltraLightOnlyAnnounce bool `toml:",omitempty"`
- SkipBcVersionCheck bool `toml:"-"`
- DatabaseHandles int `toml:"-"`
- DatabaseCache int
- DatabaseFreezer string
- DatabaseDiff string
- TrieCleanCache int
- TrieCleanCacheJournal string `toml:",omitempty"`
- TrieCleanCacheRejournal time.Duration `toml:",omitempty"`
- TrieDirtyCache int
- TrieTimeout time.Duration
- SnapshotCache int
- TriesInMemory uint64
- TriesVerifyMode core.VerifyMode
- Preimages bool
- PersistDiff bool
- DiffBlock uint64 `toml:",omitempty"`
- PruneAncientData bool
- Miner miner.Config
- Ethash ethash.Config `toml:",omitempty"`
- TxPool core.TxPoolConfig
- GPO gasprice.Config
- EnablePreimageRecording bool
- DocRoot string `toml:"-"`
- EWASMInterpreter string
- EVMInterpreter string
- RPCGasCap uint64
- RPCEVMTimeout time.Duration
- RPCTxFeeCap float64
- Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
- CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
- OverrideBerlin *big.Int `toml:",omitempty"`
+ Genesis *core.Genesis `toml:",omitempty"`
+ NetworkId uint64
+ SyncMode downloader.SyncMode
+ DisablePeerTxBroadcast bool
+ EthDiscoveryURLs []string
+ SnapDiscoveryURLs []string
+ TrustDiscoveryURLs []string
+ BscDiscoveryURLs []string
+ NoPruning bool
+ NoPrefetch bool
+ DirectBroadcast bool
+ DisableSnapProtocol bool
+ DisableDiffProtocol bool
+ EnableTrustProtocol bool
+ DisableBscProtocol bool
+ DiffSync bool
+ RangeLimit bool
+ TxLookupLimit uint64 `toml:",omitempty"`
+ Whitelist map[uint64]common.Hash `toml:"-"`
+ LightServ int `toml:",omitempty"`
+ LightIngress int `toml:",omitempty"`
+ LightEgress int `toml:",omitempty"`
+ LightPeers int `toml:",omitempty"`
+ LightNoPrune bool `toml:",omitempty"`
+ LightNoSyncServe bool `toml:",omitempty"`
+ SyncFromCheckpoint bool `toml:",omitempty"`
+ UltraLightServers []string `toml:",omitempty"`
+ UltraLightFraction int `toml:",omitempty"`
+ UltraLightOnlyAnnounce bool `toml:",omitempty"`
+ SkipBcVersionCheck bool `toml:"-"`
+ DatabaseHandles int `toml:"-"`
+ DatabaseCache int
+ DatabaseFreezer string
+ DatabaseDiff string
+ TrieCleanCache int
+ TrieCleanCacheJournal string `toml:",omitempty"`
+ TrieCleanCacheRejournal time.Duration `toml:",omitempty"`
+ TrieDirtyCache int
+ TrieTimeout time.Duration
+ SnapshotCache int
+ TriesInMemory uint64
+ TriesVerifyMode core.VerifyMode
+ Preimages bool
+ PersistDiff bool
+ DiffBlock uint64 `toml:",omitempty"`
+ PruneAncientData bool
+ Miner miner.Config
+ Ethash ethash.Config `toml:",omitempty"`
+ TxPool core.TxPoolConfig
+ GPO gasprice.Config
+ EnablePreimageRecording bool
+ DocRoot string `toml:"-"`
+ EWASMInterpreter string
+ EVMInterpreter string
+ RPCGasCap uint64
+ RPCEVMTimeout time.Duration
+ RPCTxFeeCap float64
+ Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
+ CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
+ OverrideBerlin *big.Int `toml:",omitempty"`
OverrideArrowGlacier *big.Int `toml:",omitempty"`
OverrideTerminalTotalDifficulty *big.Int `toml:",omitempty"`
}
@@ -87,11 +89,13 @@ func (c Config) MarshalTOML() (interface{}, error) {
enc.EthDiscoveryURLs = c.EthDiscoveryURLs
enc.SnapDiscoveryURLs = c.SnapDiscoveryURLs
enc.TrustDiscoveryURLs = c.TrustDiscoveryURLs
+ enc.BscDiscoveryURLs = c.BscDiscoveryURLs
enc.NoPruning = c.NoPruning
enc.DirectBroadcast = c.DirectBroadcast
enc.DisableSnapProtocol = c.DisableSnapProtocol
enc.DisableDiffProtocol = c.DisableDiffProtocol
enc.EnableTrustProtocol = c.EnableTrustProtocol
+ enc.DisableBscProtocol = c.DisableBscProtocol
enc.DiffSync = c.DiffSync
enc.RangeLimit = c.RangeLimit
enc.TxLookupLimit = c.TxLookupLimit
@@ -145,64 +149,66 @@ func (c Config) MarshalTOML() (interface{}, error) {
// UnmarshalTOML unmarshals from TOML.
func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
type Config struct {
- Genesis *core.Genesis `toml:",omitempty"`
- NetworkId *uint64
- SyncMode *downloader.SyncMode
- DisablePeerTxBroadcast *bool
- EthDiscoveryURLs []string
- SnapDiscoveryURLs []string
- TrustDiscoveryURLs []string
- NoPruning *bool
- NoPrefetch *bool
- DirectBroadcast *bool
- DisableSnapProtocol *bool
- DisableDiffProtocol *bool
- EnableTrustProtocol *bool
- DiffSync *bool
- RangeLimit *bool
- TxLookupLimit *uint64 `toml:",omitempty"`
- Whitelist map[uint64]common.Hash `toml:"-"`
- LightServ *int `toml:",omitempty"`
- LightIngress *int `toml:",omitempty"`
- LightEgress *int `toml:",omitempty"`
- LightPeers *int `toml:",omitempty"`
- LightNoPrune *bool `toml:",omitempty"`
- LightNoSyncServe *bool `toml:",omitempty"`
- SyncFromCheckpoint *bool `toml:",omitempty"`
- UltraLightServers []string `toml:",omitempty"`
- UltraLightFraction *int `toml:",omitempty"`
- UltraLightOnlyAnnounce *bool `toml:",omitempty"`
- SkipBcVersionCheck *bool `toml:"-"`
- DatabaseHandles *int `toml:"-"`
- DatabaseCache *int
- DatabaseFreezer *string
- DatabaseDiff *string
- PersistDiff *bool
- DiffBlock *uint64 `toml:",omitempty"`
- PruneAncientData *bool
- TrieCleanCache *int
- TrieCleanCacheJournal *string `toml:",omitempty"`
- TrieCleanCacheRejournal *time.Duration `toml:",omitempty"`
- TrieDirtyCache *int
- TrieTimeout *time.Duration
- SnapshotCache *int
- TriesInMemory *uint64
- TriesVerifyMode *core.VerifyMode
- Preimages *bool
- Miner *miner.Config
- Ethash *ethash.Config `toml:",omitempty"`
- TxPool *core.TxPoolConfig
- GPO *gasprice.Config
- EnablePreimageRecording *bool
- DocRoot *string `toml:"-"`
- EWASMInterpreter *string
- EVMInterpreter *string
- RPCGasCap *uint64
+ Genesis *core.Genesis `toml:",omitempty"`
+ NetworkId *uint64
+ SyncMode *downloader.SyncMode
+ DisablePeerTxBroadcast *bool
+ EthDiscoveryURLs []string
+ SnapDiscoveryURLs []string
+ TrustDiscoveryURLs []string
+ BscDiscoveryURLs []string
+ NoPruning *bool
+ NoPrefetch *bool
+ DirectBroadcast *bool
+ DisableSnapProtocol *bool
+ DisableDiffProtocol *bool
+ EnableTrustProtocol *bool
+ DisableBscProtocol *bool
+ DiffSync *bool
+ RangeLimit *bool
+ TxLookupLimit *uint64 `toml:",omitempty"`
+ Whitelist map[uint64]common.Hash `toml:"-"`
+ LightServ *int `toml:",omitempty"`
+ LightIngress *int `toml:",omitempty"`
+ LightEgress *int `toml:",omitempty"`
+ LightPeers *int `toml:",omitempty"`
+ LightNoPrune *bool `toml:",omitempty"`
+ LightNoSyncServe *bool `toml:",omitempty"`
+ SyncFromCheckpoint *bool `toml:",omitempty"`
+ UltraLightServers []string `toml:",omitempty"`
+ UltraLightFraction *int `toml:",omitempty"`
+ UltraLightOnlyAnnounce *bool `toml:",omitempty"`
+ SkipBcVersionCheck *bool `toml:"-"`
+ DatabaseHandles *int `toml:"-"`
+ DatabaseCache *int
+ DatabaseFreezer *string
+ DatabaseDiff *string
+ PersistDiff *bool
+ DiffBlock *uint64 `toml:",omitempty"`
+ PruneAncientData *bool
+ TrieCleanCache *int
+ TrieCleanCacheJournal *string `toml:",omitempty"`
+ TrieCleanCacheRejournal *time.Duration `toml:",omitempty"`
+ TrieDirtyCache *int
+ TrieTimeout *time.Duration
+ SnapshotCache *int
+ TriesInMemory *uint64
+ TriesVerifyMode *core.VerifyMode
+ Preimages *bool
+ Miner *miner.Config
+ Ethash *ethash.Config `toml:",omitempty"`
+ TxPool *core.TxPoolConfig
+ GPO *gasprice.Config
+ EnablePreimageRecording *bool
+ DocRoot *string `toml:"-"`
+ EWASMInterpreter *string
+ EVMInterpreter *string
+ RPCGasCap *uint64
RPCEVMTimeout *time.Duration
- RPCTxFeeCap *float64
- Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
- CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
- OverrideBerlin *big.Int `toml:",omitempty"`
+ RPCTxFeeCap *float64
+ Checkpoint *params.TrustedCheckpoint `toml:",omitempty"`
+ CheckpointOracle *params.CheckpointOracleConfig `toml:",omitempty"`
+ OverrideBerlin *big.Int `toml:",omitempty"`
OverrideArrowGlacier *big.Int `toml:",omitempty"`
OverrideTerminalTotalDifficulty *big.Int `toml:",omitempty"`
}
@@ -231,6 +237,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.TrustDiscoveryURLs != nil {
c.TrustDiscoveryURLs = dec.TrustDiscoveryURLs
}
+ if dec.BscDiscoveryURLs != nil {
+ c.BscDiscoveryURLs = dec.BscDiscoveryURLs
+ }
if dec.NoPruning != nil {
c.NoPruning = *dec.NoPruning
}
@@ -246,6 +255,9 @@ func (c *Config) UnmarshalTOML(unmarshal func(interface{}) error) error {
if dec.EnableTrustProtocol != nil {
c.EnableTrustProtocol = *dec.EnableTrustProtocol
}
+ if dec.DisableBscProtocol != nil {
+ c.DisableBscProtocol = *dec.DisableBscProtocol
+ }
if dec.DiffSync != nil {
c.DiffSync = *dec.DiffSync
}
diff --git a/eth/fetcher/tx_fetcher.go b/eth/fetcher/tx_fetcher.go
index 6cdb5b8804..20eaada986 100644
--- a/eth/fetcher/tx_fetcher.go
+++ b/eth/fetcher/tx_fetcher.go
@@ -261,7 +261,7 @@ func (f *TxFetcher) Notify(peer string, hashes []common.Hash) error {
// Enqueue imports a batch of received transaction into the transaction pool
// and the fetcher. This method may be called by both transaction broadcasts and
// direct request replies. The differentiation is important so the fetcher can
-// re-shedule missing transactions as soon as possible.
+// re-schedule missing transactions as soon as possible.
func (f *TxFetcher) Enqueue(peer string, txs []*types.Transaction, direct bool) error {
// Keep track of all the propagated transactions
if direct {
diff --git a/eth/filters/api.go b/eth/filters/api.go
index 56ee044274..0cacd2cf39 100644
--- a/eth/filters/api.go
+++ b/eth/filters/api.go
@@ -171,6 +171,68 @@ func (api *PublicFilterAPI) NewPendingTransactions(ctx context.Context) (*rpc.Su
return rpcSub, nil
}
+// NewVotesFilter creates a filter that fetches votes that entered the vote pool.
+// It is part of the filter package since polling goes with eth_getFilterChanges.
+func (api *PublicFilterAPI) NewVotesFilter() rpc.ID {
+ var (
+ votes = make(chan *types.VoteEnvelope)
+ voteSub = api.events.SubscribeNewVotes(votes)
+ )
+ api.filtersMu.Lock()
+ api.filters[voteSub.ID] = &filter{typ: VotesSubscription, deadline: time.NewTimer(api.timeout), hashes: make([]common.Hash, 0), s: voteSub}
+ api.filtersMu.Unlock()
+
+ gopool.Submit(func() {
+ for {
+ select {
+ case vote := <-votes:
+ api.filtersMu.Lock()
+ if f, found := api.filters[voteSub.ID]; found {
+ f.hashes = append(f.hashes, vote.Hash())
+ }
+ api.filtersMu.Unlock()
+ case <-voteSub.Err():
+ api.filtersMu.Lock()
+ delete(api.filters, voteSub.ID)
+ api.filtersMu.Unlock()
+ return
+ }
+ }
+ })
+
+ return voteSub.ID
+}
+
+// NewVotes creates a subscription that is triggered each time a vote enters the vote pool.
+func (api *PublicFilterAPI) NewVotes(ctx context.Context) (*rpc.Subscription, error) {
+ notifier, supported := rpc.NotifierFromContext(ctx)
+ if !supported {
+ return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported
+ }
+
+ rpcSub := notifier.CreateSubscription()
+
+ gopool.Submit(func() {
+ votes := make(chan *types.VoteEnvelope, 128)
+ voteSub := api.events.SubscribeNewVotes(votes)
+
+ for {
+ select {
+ case vote := <-votes:
+ notifier.Notify(rpcSub.ID, vote)
+ case <-rpcSub.Err():
+ voteSub.Unsubscribe()
+ return
+ case <-notifier.Closed():
+ voteSub.Unsubscribe()
+ return
+ }
+ }
+ })
+
+ return rpcSub, nil
+}
+
// NewBlockFilter creates a filter that fetches blocks that are imported into the chain.
// It is part of the filter package since polling goes with eth_getFilterChanges.
//
@@ -236,6 +298,68 @@ func (api *PublicFilterAPI) NewHeads(ctx context.Context) (*rpc.Subscription, er
return rpcSub, nil
}
+// NewFinalizedHeaderFilter creates a filter that fetches finalized headers that are reached.
+func (api *PublicFilterAPI) NewFinalizedHeaderFilter() rpc.ID {
+ var (
+ headers = make(chan *types.Header)
+ headerSub = api.events.SubscribeNewFinalizedHeaders(headers)
+ )
+
+ api.filtersMu.Lock()
+ api.filters[headerSub.ID] = &filter{typ: FinalizedHeadersSubscription, deadline: time.NewTimer(api.timeout), hashes: make([]common.Hash, 0), s: headerSub}
+ api.filtersMu.Unlock()
+
+ gopool.Submit(func() {
+ for {
+ select {
+ case h := <-headers:
+ api.filtersMu.Lock()
+ if f, found := api.filters[headerSub.ID]; found {
+ f.hashes = append(f.hashes, h.Hash())
+ }
+ api.filtersMu.Unlock()
+ case <-headerSub.Err():
+ api.filtersMu.Lock()
+ delete(api.filters, headerSub.ID)
+ api.filtersMu.Unlock()
+ return
+ }
+ }
+ })
+
+ return headerSub.ID
+}
+
+// NewFinalizedHeaders send a notification each time a new finalized header is reached.
+func (api *PublicFilterAPI) NewFinalizedHeaders(ctx context.Context) (*rpc.Subscription, error) {
+ notifier, supported := rpc.NotifierFromContext(ctx)
+ if !supported {
+ return &rpc.Subscription{}, rpc.ErrNotificationsUnsupported
+ }
+
+ rpcSub := notifier.CreateSubscription()
+
+ gopool.Submit(func() {
+ headers := make(chan *types.Header)
+ headersSub := api.events.SubscribeNewFinalizedHeaders(headers)
+
+ for {
+ select {
+ case h := <-headers:
+ notifier.Notify(rpcSub.ID, h)
+ case <-rpcSub.Err():
+ headersSub.Unsubscribe()
+ return
+ case <-notifier.Closed():
+ headersSub.Unsubscribe()
+ return
+ }
+ }
+ })
+
+ return rpcSub, nil
+}
+
// Logs creates a subscription that fires for all new log that match the given filter criteria.
func (api *PublicFilterAPI) Logs(ctx context.Context, crit FilterCriteria) (*rpc.Subscription, error) {
notifier, supported := rpc.NotifierFromContext(ctx)
@@ -427,7 +551,7 @@ func (api *PublicFilterAPI) GetFilterChanges(id rpc.ID) (interface{}, error) {
f.deadline.Reset(api.timeout)
switch f.typ {
- case PendingTransactionsSubscription, BlocksSubscription:
+ case PendingTransactionsSubscription, BlocksSubscription, VotesSubscription:
hashes := f.hashes
f.hashes = nil
return returnHashes(hashes), nil
diff --git a/eth/filters/filter.go b/eth/filters/filter.go
index 2762993dad..40668cb2ee 100644
--- a/eth/filters/filter.go
+++ b/eth/filters/filter.go
@@ -19,7 +19,6 @@ package filters
import (
"context"
"errors"
- "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -43,9 +42,11 @@ type Backend interface {
SubscribeNewTxsEvent(chan<- core.NewTxsEvent) event.Subscription
SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription
+ SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription
SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription
SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription
SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription
+ SubscribeNewVoteEvent(chan<- core.NewVoteEvent) event.Subscription
BloomStatus() (uint64, uint64)
ServiceFilter(ctx context.Context, session *bloombits.MatcherSession)
@@ -148,23 +149,44 @@ func (f *Filter) Logs(ctx context.Context) ([]*types.Log, error) {
return nil, nil
}
var (
- head = header.Number.Uint64()
- end = uint64(f.end)
+ err error
+ head = header.Number.Int64()
pending = f.end == rpc.PendingBlockNumber.Int64()
)
- if f.begin == rpc.LatestBlockNumber.Int64() {
- f.begin = int64(head)
+ resolveSpecial := func(number int64) (int64, error) {
+ var hdr *types.Header
+ switch number {
+ case rpc.LatestBlockNumber.Int64():
+ return head, nil
+ case rpc.PendingBlockNumber.Int64():
+ // we should return head here since we've already captured
+ // that we need to get the pending logs in the pending boolean above
+ return head, nil
+ case rpc.FinalizedBlockNumber.Int64():
+ hdr, _ = f.backend.HeaderByNumber(ctx, rpc.FinalizedBlockNumber)
+ if hdr == nil {
+ return 0, errors.New("finalized header not found")
+ }
+ case rpc.SafeBlockNumber.Int64():
+ hdr, _ = f.backend.HeaderByNumber(ctx, rpc.SafeBlockNumber)
+ if hdr == nil {
+ return 0, errors.New("safe header not found")
+ }
+ default:
+ return number, nil
+ }
+ return hdr.Number.Int64(), nil
}
- if f.end == rpc.LatestBlockNumber.Int64() || f.end == rpc.PendingBlockNumber.Int64() {
- end = head
+ if f.begin, err = resolveSpecial(f.begin); err != nil {
+ return nil, err
}
- if f.rangeLimit && (int64(end)-f.begin) > maxFilterBlockRange {
- return nil, fmt.Errorf("exceed maximum block range: %d", maxFilterBlockRange)
+ if f.end, err = resolveSpecial(f.end); err != nil {
+ return nil, err
}
// Gather all indexed logs, and finish with non indexed ones
var (
logs []*types.Log
- err error
+ end = uint64(f.end)
size, sections = f.backend.BloomStatus()
)
if indexed := sections * size; indexed > uint64(f.begin) {
diff --git a/eth/filters/filter_system.go b/eth/filters/filter_system.go
index 12f037d0f9..bf461a1c5c 100644
--- a/eth/filters/filter_system.go
+++ b/eth/filters/filter_system.go
@@ -52,7 +52,11 @@ const (
PendingTransactionsSubscription
// BlocksSubscription queries hashes for blocks that are imported
BlocksSubscription
- // LastSubscription keeps track of the last index
+ // VotesSubscription queries vote hashes for votes entering the vote pool
+ VotesSubscription
+ // FinalizedHeadersSubscription queries hashes for finalized headers that are reached
+ FinalizedHeadersSubscription
+ // LastIndexSubscription keeps track of the last index
LastIndexSubscription
)
@@ -66,18 +70,25 @@ const (
logsChanSize = 10
// chainEvChanSize is the size of channel listening to ChainEvent.
chainEvChanSize = 10
+ // finalizedHeaderEvChanSize is the size of channel listening to FinalizedHeaderEvent.
+ finalizedHeaderEvChanSize = 10
+ // voteChanSize is the size of channel listening to NewVoteEvent.
+ // The number is referenced from the size of vote pool.
+ voteChanSize = 256
)
type subscription struct {
- id rpc.ID
- typ Type
- created time.Time
- logsCrit ethereum.FilterQuery
- logs chan []*types.Log
- hashes chan []common.Hash
- headers chan *types.Header
- installed chan struct{} // closed when the filter is installed
- err chan error // closed when the filter is uninstalled
+ id rpc.ID
+ typ Type
+ created time.Time
+ logsCrit ethereum.FilterQuery
+ logs chan []*types.Log
+ hashes chan []common.Hash
+ headers chan *types.Header
+ finalizedHeaders chan *types.Header
+ votes chan *types.VoteEnvelope
+ installed chan struct{} // closed when the filter is installed
+ err chan error // closed when the filter is uninstalled
}
// EventSystem creates subscriptions, processes events and broadcasts them to the
@@ -88,20 +99,24 @@ type EventSystem struct {
lastHead *types.Header
// Subscriptions
- txsSub event.Subscription // Subscription for new transaction event
- logsSub event.Subscription // Subscription for new log event
- rmLogsSub event.Subscription // Subscription for removed log event
- pendingLogsSub event.Subscription // Subscription for pending log event
- chainSub event.Subscription // Subscription for new chain event
+ txsSub event.Subscription // Subscription for new transaction event
+ logsSub event.Subscription // Subscription for new log event
+ rmLogsSub event.Subscription // Subscription for removed log event
+ pendingLogsSub event.Subscription // Subscription for pending log event
+ chainSub event.Subscription // Subscription for new chain event
+ finalizedHeaderSub event.Subscription // Subscription for new finalized header
+ voteSub event.Subscription // Subscription for new vote event
// Channels
- install chan *subscription // install filter for event notification
- uninstall chan *subscription // remove filter for event notification
- txsCh chan core.NewTxsEvent // Channel to receive new transactions event
- logsCh chan []*types.Log // Channel to receive new log event
- pendingLogsCh chan []*types.Log // Channel to receive new log event
- rmLogsCh chan core.RemovedLogsEvent // Channel to receive removed log event
- chainCh chan core.ChainEvent // Channel to receive new chain event
+ install chan *subscription // install filter for event notification
+ uninstall chan *subscription // remove filter for event notification
+ txsCh chan core.NewTxsEvent // Channel to receive new transactions event
+ logsCh chan []*types.Log // Channel to receive new log event
+ pendingLogsCh chan []*types.Log // Channel to receive new log event
+ rmLogsCh chan core.RemovedLogsEvent // Channel to receive removed log event
+ chainCh chan core.ChainEvent // Channel to receive new chain event
+ finalizedHeaderCh chan core.FinalizedHeaderEvent // Channel to receive new finalized header event
+ voteCh chan core.NewVoteEvent // Channel to receive new vote event
}
// NewEventSystem creates a new manager that listens for event on the given mux,
@@ -112,15 +127,17 @@ type EventSystem struct {
// or by stopping the given mux.
func NewEventSystem(backend Backend, lightMode bool) *EventSystem {
m := &EventSystem{
- backend: backend,
- lightMode: lightMode,
- install: make(chan *subscription),
- uninstall: make(chan *subscription),
- txsCh: make(chan core.NewTxsEvent, txChanSize),
- logsCh: make(chan []*types.Log, logsChanSize),
- rmLogsCh: make(chan core.RemovedLogsEvent, rmLogsChanSize),
- pendingLogsCh: make(chan []*types.Log, logsChanSize),
- chainCh: make(chan core.ChainEvent, chainEvChanSize),
+ backend: backend,
+ lightMode: lightMode,
+ install: make(chan *subscription),
+ uninstall: make(chan *subscription),
+ txsCh: make(chan core.NewTxsEvent, txChanSize),
+ logsCh: make(chan []*types.Log, logsChanSize),
+ rmLogsCh: make(chan core.RemovedLogsEvent, rmLogsChanSize),
+ pendingLogsCh: make(chan []*types.Log, logsChanSize),
+ chainCh: make(chan core.ChainEvent, chainEvChanSize),
+ finalizedHeaderCh: make(chan core.FinalizedHeaderEvent, finalizedHeaderEvChanSize),
+ voteCh: make(chan core.NewVoteEvent, voteChanSize),
}
// Subscribe events
@@ -129,11 +146,16 @@ func NewEventSystem(backend Backend, lightMode bool) *EventSystem {
m.rmLogsSub = m.backend.SubscribeRemovedLogsEvent(m.rmLogsCh)
m.chainSub = m.backend.SubscribeChainEvent(m.chainCh)
m.pendingLogsSub = m.backend.SubscribePendingLogsEvent(m.pendingLogsCh)
+ m.finalizedHeaderSub = m.backend.SubscribeFinalizedHeaderEvent(m.finalizedHeaderCh)
+ m.voteSub = m.backend.SubscribeNewVoteEvent(m.voteCh)
// Make sure none of the subscriptions are empty
if m.txsSub == nil || m.logsSub == nil || m.rmLogsSub == nil || m.chainSub == nil || m.pendingLogsSub == nil {
log.Crit("Subscribe for event system failed")
}
+ if m.voteSub == nil || m.finalizedHeaderSub == nil {
+ log.Warn("Subscribe for vote or finalized header event failed")
+ }
go m.eventLoop()
return m
@@ -167,6 +189,7 @@ func (sub *Subscription) Unsubscribe() {
case <-sub.f.logs:
case <-sub.f.hashes:
case <-sub.f.headers:
+ case <-sub.f.votes:
}
}
@@ -234,6 +257,7 @@ func (es *EventSystem) subscribeMinedPendingLogs(crit ethereum.FilterQuery, logs
logs: logs,
hashes: make(chan []common.Hash),
headers: make(chan *types.Header),
+ votes: make(chan *types.VoteEnvelope),
installed: make(chan struct{}),
err: make(chan error),
}
@@ -251,6 +275,7 @@ func (es *EventSystem) subscribeLogs(crit ethereum.FilterQuery, logs chan []*typ
logs: logs,
hashes: make(chan []common.Hash),
headers: make(chan *types.Header),
+ votes: make(chan *types.VoteEnvelope),
installed: make(chan struct{}),
err: make(chan error),
}
@@ -268,6 +293,7 @@ func (es *EventSystem) subscribePendingLogs(crit ethereum.FilterQuery, logs chan
logs: logs,
hashes: make(chan []common.Hash),
headers: make(chan *types.Header),
+ votes: make(chan *types.VoteEnvelope),
installed: make(chan struct{}),
err: make(chan error),
}
@@ -284,6 +310,24 @@ func (es *EventSystem) SubscribeNewHeads(headers chan *types.Header) *Subscripti
logs: make(chan []*types.Log),
hashes: make(chan []common.Hash),
headers: headers,
+ votes: make(chan *types.VoteEnvelope),
+ installed: make(chan struct{}),
+ err: make(chan error),
+ }
+ return es.subscribe(sub)
+}
+
+// SubscribeNewFinalizedHeaders creates a subscription that writes the finalized header of a block that is
+// reached recently.
+func (es *EventSystem) SubscribeNewFinalizedHeaders(headers chan *types.Header) *Subscription {
+ sub := &subscription{
+ id: rpc.NewID(),
+ typ: FinalizedHeadersSubscription,
+ created: time.Now(),
+ logs: make(chan []*types.Log),
+ hashes: make(chan []common.Hash),
+ headers: headers,
+ votes: make(chan *types.VoteEnvelope),
installed: make(chan struct{}),
err: make(chan error),
}
@@ -300,6 +344,24 @@ func (es *EventSystem) SubscribePendingTxs(hashes chan []common.Hash) *Subscript
logs: make(chan []*types.Log),
hashes: hashes,
headers: make(chan *types.Header),
+ votes: make(chan *types.VoteEnvelope),
+ installed: make(chan struct{}),
+ err: make(chan error),
+ }
+ return es.subscribe(sub)
+}
+
+// SubscribeNewVotes creates a subscription that writes transaction hashes for
+// transactions that enter the transaction pool.
+func (es *EventSystem) SubscribeNewVotes(votes chan *types.VoteEnvelope) *Subscription {
+ sub := &subscription{
+ id: rpc.NewID(),
+ typ: VotesSubscription,
+ created: time.Now(),
+ logs: make(chan []*types.Log),
+ hashes: make(chan []common.Hash),
+ headers: make(chan *types.Header),
+ votes: votes,
installed: make(chan struct{}),
err: make(chan error),
}
@@ -351,6 +413,12 @@ func (es *EventSystem) handleTxsEvent(filters filterIndex, ev core.NewTxsEvent)
}
}
+func (es *EventSystem) handleVoteEvent(filters filterIndex, ev core.NewVoteEvent) {
+ for _, f := range filters[VotesSubscription] {
+ f.votes <- ev.Vote
+ }
+}
+
func (es *EventSystem) handleChainEvent(filters filterIndex, ev core.ChainEvent) {
for _, f := range filters[BlocksSubscription] {
f.headers <- ev.Block.Header()
@@ -366,6 +434,12 @@ func (es *EventSystem) handleChainEvent(filters filterIndex, ev core.ChainEvent)
}
}
+func (es *EventSystem) handleFinalizedHeaderEvent(filters filterIndex, ev core.FinalizedHeaderEvent) {
+ for _, f := range filters[FinalizedHeadersSubscription] {
+ f.headers <- ev.Header
+ }
+}
+
func (es *EventSystem) lightFilterNewHead(newHeader *types.Header, callBack func(*types.Header, bool)) {
oldh := es.lastHead
es.lastHead = newHeader
@@ -448,6 +522,10 @@ func (es *EventSystem) eventLoop() {
es.rmLogsSub.Unsubscribe()
es.pendingLogsSub.Unsubscribe()
es.chainSub.Unsubscribe()
+ es.finalizedHeaderSub.Unsubscribe()
+ if es.voteSub != nil {
+ es.voteSub.Unsubscribe()
+ }
}()
index := make(filterIndex)
@@ -455,6 +533,10 @@ func (es *EventSystem) eventLoop() {
index[i] = make(map[rpc.ID]*subscription)
}
+ var voteSubErr <-chan error
+ if es.voteSub != nil {
+ voteSubErr = es.voteSub.Err()
+ }
for {
select {
case ev := <-es.txsCh:
@@ -467,6 +549,10 @@ func (es *EventSystem) eventLoop() {
es.handlePendingLogs(index, ev)
case ev := <-es.chainCh:
es.handleChainEvent(index, ev)
+ case ev := <-es.finalizedHeaderCh:
+ es.handleFinalizedHeaderEvent(index, ev)
+ case ev := <-es.voteCh:
+ es.handleVoteEvent(index, ev)
case f := <-es.install:
if f.typ == MinedAndPendingLogsSubscription {
@@ -497,6 +583,10 @@ func (es *EventSystem) eventLoop() {
return
case <-es.chainSub.Err():
return
+ case <-es.finalizedHeaderSub.Err():
+ return
+ case <-voteSubErr:
+ return
}
}
}
diff --git a/eth/filters/filter_system_test.go b/eth/filters/filter_system_test.go
index 7435a19e86..737eaa17c7 100644
--- a/eth/filters/filter_system_test.go
+++ b/eth/filters/filter_system_test.go
@@ -18,6 +18,7 @@ package filters
import (
"context"
+ "errors"
"fmt"
"math/big"
"math/rand"
@@ -44,14 +45,16 @@ var (
)
type testBackend struct {
- mux *event.TypeMux
- db ethdb.Database
- sections uint64
- txFeed event.Feed
- logsFeed event.Feed
- rmLogsFeed event.Feed
- pendingLogsFeed event.Feed
- chainFeed event.Feed
+ mux *event.TypeMux
+ db ethdb.Database
+ sections uint64
+ txFeed event.Feed
+ logsFeed event.Feed
+ rmLogsFeed event.Feed
+ pendingLogsFeed event.Feed
+ chainFeed event.Feed
+ finalizedHeaderFeed event.Feed
+ voteFeed event.Feed
}
func (b *testBackend) ChainDb() ethdb.Database {
@@ -63,14 +66,19 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, blockNr rpc.BlockNumbe
hash common.Hash
num uint64
)
- if blockNr == rpc.LatestBlockNumber {
+ switch blockNr {
+ case rpc.LatestBlockNumber:
hash = rawdb.ReadHeadBlockHash(b.db)
number := rawdb.ReadHeaderNumber(b.db, hash)
if number == nil {
return nil, nil
}
num = *number
- } else {
+ case rpc.FinalizedBlockNumber:
+ return nil, errors.New("finalized block not found")
+ case rpc.SafeBlockNumber:
+ return nil, errors.New("safe block not found")
+ default:
num = uint64(blockNr)
hash = rawdb.ReadCanonicalHash(b.db, num)
}
@@ -130,6 +138,14 @@ func (b *testBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subsc
return b.chainFeed.Subscribe(ch)
}
+func (b *testBackend) SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription {
+ return b.finalizedHeaderFeed.Subscribe(ch)
+}
+
+func (b *testBackend) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription {
+ return b.voteFeed.Subscribe(ch)
+}
+
func (b *testBackend) BloomStatus() (uint64, uint64) {
return params.BloomBitsBlocks, b.sections
}
@@ -735,3 +751,79 @@ func flattenLogs(pl [][]*types.Log) []*types.Log {
}
return logs
}
+
+func TestVoteSubscription(t *testing.T) {
+ t.Parallel()
+
+ var (
+ db = rawdb.NewMemoryDatabase()
+ backend = &testBackend{db: db}
+ api = NewPublicFilterAPI(backend, false, deadline, false)
+ votes = []*types.VoteEnvelope{
+ &types.VoteEnvelope{
+ VoteAddress: types.BLSPublicKey{},
+ Signature: types.BLSSignature{},
+ Data: &types.VoteData{
+ SourceNumber: uint64(0),
+ SourceHash: common.BytesToHash(common.Hex2Bytes(string(rune(0)))),
+ TargetNumber: uint64(1),
+ TargetHash: common.BytesToHash(common.Hex2Bytes(string(rune(1)))),
+ },
+ },
+ &types.VoteEnvelope{
+ VoteAddress: types.BLSPublicKey{},
+ Signature: types.BLSSignature{},
+ Data: &types.VoteData{
+ SourceNumber: uint64(0),
+ SourceHash: common.BytesToHash(common.Hex2Bytes(string(rune(0)))),
+ TargetNumber: uint64(2),
+ TargetHash: common.BytesToHash(common.Hex2Bytes(string(rune(2)))),
+ },
+ },
+ &types.VoteEnvelope{
+ VoteAddress: types.BLSPublicKey{},
+ Signature: types.BLSSignature{},
+ Data: &types.VoteData{
+ SourceNumber: uint64(0),
+ SourceHash: common.BytesToHash(common.Hex2Bytes(string(rune(0)))),
+ TargetNumber: uint64(3),
+ TargetHash: common.BytesToHash(common.Hex2Bytes(string(rune(3)))),
+ },
+ },
+ &types.VoteEnvelope{
+ VoteAddress: types.BLSPublicKey{},
+ Signature: types.BLSSignature{},
+ Data: &types.VoteData{
+ SourceNumber: uint64(0),
+ SourceHash: common.BytesToHash(common.Hex2Bytes(string(rune(0)))),
+ TargetNumber: uint64(4),
+ TargetHash: common.BytesToHash(common.Hex2Bytes(string(rune(4)))),
+ },
+ },
+ }
+ )
+
+ chan0 := make(chan *types.VoteEnvelope)
+ sub0 := api.events.SubscribeNewVotes(chan0)
+
+ go func() { // simulate client
+ i := 0
+ for i != len(votes) {
+ vote := <-chan0
+ if votes[i].Hash() != vote.Hash() {
+ t.Errorf("sub received invalid hash on index %d, want %x, got %x", i, votes[i].Hash(), vote.Hash())
+ }
+ i++
+ }
+
+ sub0.Unsubscribe()
+ }()
+
+ time.Sleep(1 * time.Second)
+ for _, v := range votes {
+ ev := core.NewVoteEvent{Vote: v}
+ backend.voteFeed.Send(ev)
+ }
+
+ <-sub0.Err()
+}
diff --git a/eth/gasprice/feehistory.go b/eth/gasprice/feehistory.go
index 78bade5ae8..ae7d0069a1 100644
--- a/eth/gasprice/feehistory.go
+++ b/eth/gasprice/feehistory.go
@@ -137,44 +137,68 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
// also returned if requested and available.
// Note: an error is only returned if retrieving the head header has failed. If there are no
// retrievable blocks in the specified range then zero block count is returned with no error.
-func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.BlockNumber, blocks int) (*types.Block, []*types.Receipt, uint64, int, error) {
+func (oracle *Oracle) resolveBlockRange(ctx context.Context, reqEnd rpc.BlockNumber, blocks int) (*types.Block, []*types.Receipt, uint64, int, error) {
var (
- headBlock rpc.BlockNumber
+ headBlock *types.Header
pendingBlock *types.Block
pendingReceipts types.Receipts
+ err error
)
- // query either pending block or head header and set headBlock
- if lastBlock == rpc.PendingBlockNumber {
- if pendingBlock, pendingReceipts = oracle.backend.PendingBlockAndReceipts(); pendingBlock != nil {
- lastBlock = rpc.BlockNumber(pendingBlock.NumberU64())
- headBlock = lastBlock - 1
- } else {
- // pending block not supported by backend, process until latest block
- lastBlock = rpc.LatestBlockNumber
- blocks--
- if blocks == 0 {
- return nil, nil, 0, 0, nil
+
+ // Get the chain's current head.
+ if headBlock, err = oracle.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber); err != nil {
+ return nil, nil, 0, 0, err
+ }
+ head := rpc.BlockNumber(headBlock.Number.Uint64())
+
+ // Fail if request block is beyond the chain's current head.
+ if head < reqEnd {
+ return nil, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", errRequestBeyondHead, reqEnd, head)
+ }
+
+ // Resolve block tag.
+ if reqEnd < 0 {
+ var (
+ resolved *types.Header
+ err error
+ )
+ switch reqEnd {
+ case rpc.PendingBlockNumber:
+ if pendingBlock, pendingReceipts = oracle.backend.PendingBlockAndReceipts(); pendingBlock != nil {
+ resolved = pendingBlock.Header()
+ } else {
+ // Pending block not supported by backend, process only until latest block.
+ resolved = headBlock
+
+ // Update total blocks to return to account for this.
+ blocks--
}
+ case rpc.LatestBlockNumber:
+ // Retrieved above.
+ resolved = headBlock
+ case rpc.SafeBlockNumber:
+ resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.SafeBlockNumber)
+ case rpc.FinalizedBlockNumber:
+ resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.FinalizedBlockNumber)
+ case rpc.EarliestBlockNumber:
+ resolved, err = oracle.backend.HeaderByNumber(ctx, rpc.EarliestBlockNumber)
}
- }
- if pendingBlock == nil {
- // if pending block is not fetched then we retrieve the head header to get the head block number
- if latestHeader, err := oracle.backend.HeaderByNumber(ctx, rpc.LatestBlockNumber); err == nil && latestHeader != nil {
- headBlock = rpc.BlockNumber(latestHeader.Number.Uint64())
- } else {
+ if resolved == nil || err != nil {
return nil, nil, 0, 0, err
}
+ // Absolute number resolved.
+ reqEnd = rpc.BlockNumber(resolved.Number.Uint64())
}
- if lastBlock == rpc.LatestBlockNumber {
- lastBlock = headBlock
- } else if pendingBlock == nil && lastBlock > headBlock {
- return nil, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", errRequestBeyondHead, lastBlock, headBlock)
+
+ // If there are no blocks to return, short circuit.
+ if blocks == 0 {
+ return nil, nil, 0, 0, nil
}
- // ensure not trying to retrieve before genesis
- if rpc.BlockNumber(blocks) > lastBlock+1 {
- blocks = int(lastBlock + 1)
+ // Ensure not trying to retrieve before genesis.
+ if uint64(reqEnd+1) < uint64(blocks) {
+ blocks = int(reqEnd + 1)
}
- return pendingBlock, pendingReceipts, uint64(lastBlock), blocks, nil
+ return pendingBlock, pendingReceipts, uint64(reqEnd), blocks, nil
}
// FeeHistory returns data relevant for fee estimation based on the specified range of blocks.
diff --git a/eth/gasprice/feehistory_test.go b/eth/gasprice/feehistory_test.go
index c259eb0acf..25a685effc 100644
--- a/eth/gasprice/feehistory_test.go
+++ b/eth/gasprice/feehistory_test.go
@@ -50,6 +50,8 @@ func TestFeeHistory(t *testing.T) {
{false, 1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 1, nil},
{true, 1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 2, nil},
{true, 1000, 1000, 2, rpc.PendingBlockNumber, []float64{0, 10}, 32, 2, nil},
+ // {false, 1000, 1000, 2, rpc.FinalizedBlockNumber, []float64{0, 10}, 24, 2, nil},
+ // {false, 1000, 1000, 2, rpc.SafeBlockNumber, []float64{0, 10}, 24, 2, nil},
}
for i, c := range cases {
config := Config{
diff --git a/eth/gasprice/gasprice_test.go b/eth/gasprice/gasprice_test.go
index 01edde38ce..a6f0f53643 100644
--- a/eth/gasprice/gasprice_test.go
+++ b/eth/gasprice/gasprice_test.go
@@ -18,6 +18,7 @@ package gasprice
import (
"context"
+ "errors"
"math"
"math/big"
"testing"
@@ -45,6 +46,15 @@ func (b *testBackend) HeaderByNumber(ctx context.Context, number rpc.BlockNumber
if number > testHead {
return nil, nil
}
+ if number == rpc.EarliestBlockNumber {
+ number = 0
+ }
+ if number == rpc.FinalizedBlockNumber {
+ return b.chain.CurrentFinalBlock(), nil
+ }
+ if number == rpc.SafeBlockNumber {
+ return b.chain.CurrentSafeBlock(), nil
+ }
if number == rpc.LatestBlockNumber {
number = testHead
}
@@ -62,6 +72,23 @@ func (b *testBackend) BlockByNumber(ctx context.Context, number rpc.BlockNumber)
if number > testHead {
return nil, nil
}
+ if number == rpc.EarliestBlockNumber {
+ number = 0
+ }
+ if number == rpc.FinalizedBlockNumber {
+ header := b.chain.CurrentFinalBlock()
+ if header == nil {
+ return nil, errors.New("finalized block not found")
+ }
+ number = rpc.BlockNumber(header.Number.Uint64())
+ }
+ if number == rpc.SafeBlockNumber {
+ header := b.chain.CurrentSafeBlock()
+ if header == nil {
+ return nil, errors.New("safe block not found")
+ }
+ number = rpc.BlockNumber(header.Number.Uint64())
+ }
if number == rpc.LatestBlockNumber {
number = testHead
}
@@ -109,6 +136,8 @@ func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBacke
config.LondonBlock = londonBlock
config.ArrowGlacierBlock = londonBlock
config.GibbsBlock = nil
+ config.BonehBlock = nil
+ config.LynnBlock = nil
engine := ethash.NewFaker()
db := rawdb.NewMemoryDatabase()
genesis, err := gspec.Commit(db)
diff --git a/eth/handler.go b/eth/handler.go
index 19de9ad872..92e2b78f10 100644
--- a/eth/handler.go
+++ b/eth/handler.go
@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth/downloader"
"github.com/ethereum/go-ethereum/eth/fetcher"
+ "github.com/ethereum/go-ethereum/eth/protocols/bsc"
"github.com/ethereum/go-ethereum/eth/protocols/diff"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
@@ -49,6 +50,12 @@ const (
// txChanSize is the size of channel listening to NewTxsEvent.
// The number is referenced from the size of tx pool.
txChanSize = 4096
+
+ // voteChanSize is the size of channel listening to NewVotesEvent.
+ voteChanSize = 256
+
+ // deltaTdThreshold is the threshold of TD difference for peers to broadcast votes.
+ deltaTdThreshold = 20
)
var (
@@ -82,12 +89,24 @@ type txPool interface {
SubscribeReannoTxsEvent(chan<- core.ReannoTxsEvent) event.Subscription
}
+// votePool defines the methods needed from a votes pool implementation to
+// support all the operations needed by the Ethereum chain protocols.
+type votePool interface {
+ PutVote(vote *types.VoteEnvelope)
+ GetVotes() []*types.VoteEnvelope
+
+ // SubscribeNewVoteEvent should return an event subscription of
+ // NewVotesEvent and send events to the given channel.
+ SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription
+}
+
// handlerConfig is the collection of initialization parameters to create a full
// node network handler.
type handlerConfig struct {
- Database ethdb.Database // Database for direct sync insertions
- Chain *core.BlockChain // Blockchain to serve data from
- TxPool txPool // Transaction pool to propagate from
+ Database ethdb.Database // Database for direct sync insertions
+ Chain *core.BlockChain // Blockchain to serve data from
+ TxPool txPool // Transaction pool to propagate from
+ VotePool votePool
Merger *consensus.Merger // The manager for eth1/2 transition
Network uint64 // Network identifier to adfvertise
Sync downloader.SyncMode // Whether to snap or full sync
@@ -116,6 +135,7 @@ type handler struct {
database ethdb.Database
txpool txPool
+ votepool votePool
chain *core.BlockChain
maxPeers int
@@ -131,6 +151,8 @@ type handler struct {
reannoTxsCh chan core.ReannoTxsEvent
reannoTxsSub event.Subscription
minedBlockSub *event.TypeMuxSubscription
+ voteCh chan core.NewVoteEvent
+ votesSub event.Subscription
whitelist map[uint64]common.Hash
@@ -158,6 +180,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
eventMux: config.EventMux,
database: config.Database,
txpool: config.TxPool,
+ votepool: config.VotePool,
chain: config.Chain,
peers: config.PeerSet,
merger: config.Merger,
@@ -306,7 +329,7 @@ func newHandler(config *handlerConfig) (*handler, error) {
}
// runEthPeer registers an eth peer into the joint eth/snap peerset, adds it to
-// various subsistems and starts handling messages.
+// various subsystems and starts handling messages.
func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
// If the peer has a `snap` extension, wait for it to connect so we can have
// a uniform initialization/teardown mechanism
@@ -325,6 +348,11 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
peer.Log().Error("Trust extension barrier failed", "err", err)
return err
}
+ bsc, err := h.peers.waitBscExtension(peer)
+ if err != nil {
+ peer.Log().Error("Bsc extension barrier failed", "err", err)
+ return err
+ }
// TODO(karalabe): Not sure why this is needed
if !h.chainSync.handlePeerEvent(peer) {
return p2p.DiscQuitting
@@ -365,7 +393,7 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
peer.Log().Debug("Ethereum peer connected", "name", peer.Name())
// Register the peer locally
- if err := h.peers.registerPeer(peer, snap, diff, trust); err != nil {
+ if err := h.peers.registerPeer(peer, snap, diff, trust, bsc); err != nil {
peer.Log().Error("Ethereum peer registration failed", "err", err)
return err
}
@@ -388,9 +416,12 @@ func (h *handler) runEthPeer(peer *eth.Peer, handler eth.Handler) error {
}
h.chainSync.handlePeerEvent(peer)
- // Propagate existing transactions. new transactions appearing
+ // Propagate existing transactions and votes. new transactions and votes appearing
// after this will be sent via broadcasts.
h.syncTransactions(peer)
+ if h.votepool != nil && p.bscExt != nil {
+ h.syncVotes(p.bscExt)
+ }
// Create a notification channel for pending requests if the peer goes down
dead := make(chan struct{})
@@ -540,6 +571,21 @@ func (h *handler) runTrustExtension(peer *trust.Peer, handler trust.Handler) err
return handler(peer)
}
+// runBscExtension registers a `bsc` peer into the joint eth/bsc peerset and
+// starts handling inbound messages. As `bsc` is only a satellite protocol to
+// `eth`, all subsystem registrations and lifecycle management will be done by
+// the main `eth` handler to prevent strange races.
+func (h *handler) runBscExtension(peer *bsc.Peer, handler bsc.Handler) error {
+ h.peerWG.Add(1)
+ defer h.peerWG.Done()
+
+ if err := h.peers.registerBscExtension(peer); err != nil {
+ peer.Log().Error("Bsc extension registration failed", "err", err)
+ return err
+ }
+ return handler(peer)
+}
+
// removePeer requests disconnection of a peer.
func (h *handler) removePeer(id string) {
peer := h.peers.peer(id)
@@ -589,6 +635,14 @@ func (h *handler) Start(maxPeers int) {
h.txsSub = h.txpool.SubscribeNewTxsEvent(h.txsCh)
go h.txBroadcastLoop()
+ // broadcast votes
+ if h.votepool != nil {
+ h.wg.Add(1)
+ h.voteCh = make(chan core.NewVoteEvent, voteChanSize)
+ h.votesSub = h.votepool.SubscribeNewVoteEvent(h.voteCh)
+ go h.voteBroadcastLoop()
+ }
+
// announce local pending transactions again
h.wg.Add(1)
h.reannoTxsCh = make(chan core.ReannoTxsEvent, txChanSize)
@@ -609,6 +663,9 @@ func (h *handler) Stop() {
h.txsSub.Unsubscribe() // quits txBroadcastLoop
h.reannoTxsSub.Unsubscribe() // quits txReannounceLoop
h.minedBlockSub.Unsubscribe() // quits blockBroadcastLoop
+ if h.votepool != nil {
+ h.votesSub.Unsubscribe() // quits voteBroadcastLoop
+ }
// Quit chainSync and txsync64.
// After this is done, no new peers will be accepted.
@@ -671,7 +728,7 @@ func (h *handler) BroadcastBlock(block *types.Block, propagate bool) {
log.Trace("Propagated block", "hash", hash, "recipients", len(transfer), "duration", common.PrettyDuration(time.Since(block.ReceivedAt)))
return
}
- // Otherwise if the block is indeed in out own chain, announce it
+ // Otherwise if the block is indeed in our own chain, announce it
if h.chain.HasBlock(hash, block.NumberU64()) {
for _, peer := range peers {
peer.AsyncSendNewBlockHash(block)
@@ -741,6 +798,37 @@ func (h *handler) ReannounceTransactions(txs types.Transactions) {
"announce packs", peersCount, "announced hashes", peersCount*uint(len(hashes)))
}
+// BroadcastVote will propagate a batch of votes to all peers
+// which are not known to already have the given vote.
+func (h *handler) BroadcastVote(vote *types.VoteEnvelope) {
+ var (
+ directCount int // Count of announcements made
+ directPeers int
+
+ voteMap = make(map[*ethPeer]*types.VoteEnvelope) // Set peer->hash to transfer directly
+ )
+
+ // Broadcast vote to a batch of peers not knowing about it
+ peers := h.peers.peersWithoutVote(vote.Hash())
+ headBlock := h.chain.CurrentBlock()
+ currentTD := h.chain.GetTd(headBlock.Hash(), headBlock.NumberU64())
+ for _, peer := range peers {
+ _, peerTD := peer.Head()
+ deltaTD := new(big.Int).Abs(new(big.Int).Sub(currentTD, peerTD))
+ if deltaTD.Cmp(big.NewInt(deltaTdThreshold)) < 1 && peer.bscExt != nil {
+ voteMap[peer] = vote
+ }
+ }
+
+ for peer, _vote := range voteMap {
+ directPeers++
+ directCount += 1
+ votes := []*types.VoteEnvelope{_vote}
+ peer.bscExt.AsyncSendVotes(votes)
+ }
+ log.Debug("Vote broadcast", "vote packs", directPeers, "broadcast vote", directCount)
+}
+
// minedBroadcastLoop sends mined blocks to connected peers.
func (h *handler) minedBroadcastLoop() {
defer h.wg.Done()
@@ -778,3 +866,16 @@ func (h *handler) txReannounceLoop() {
}
}
}
+
+// voteBroadcastLoop announces new vote to connected peers.
+func (h *handler) voteBroadcastLoop() {
+ defer h.wg.Done()
+ for {
+ select {
+ case event := <-h.voteCh:
+ h.BroadcastVote(event.Vote)
+ case <-h.votesSub.Err():
+ return
+ }
+ }
+}
diff --git a/eth/handler_bsc.go b/eth/handler_bsc.go
new file mode 100644
index 0000000000..59943aadab
--- /dev/null
+++ b/eth/handler_bsc.go
@@ -0,0 +1,68 @@
+package eth
+
+import (
+ "fmt"
+
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth/protocols/bsc"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+)
+
+// bscHandler implements the bsc.Backend interface to handle the various network
+// packets that are sent as broadcasts.
+type bscHandler handler
+
+func (h *bscHandler) Chain() *core.BlockChain { return h.chain }
+
+// RunPeer is invoked when a peer joins on the `bsc` protocol.
+func (h *bscHandler) RunPeer(peer *bsc.Peer, hand bsc.Handler) error {
+ if err := peer.Handshake(); err != nil {
+ // ensure that waitBscExtension receives the exit signal normally
+ // otherwise, can't graceful shutdown
+ ps := h.peers
+ id := peer.ID()
+
+ // Ensure nobody can double connect
+ ps.lock.Lock()
+ if wait, ok := ps.bscWait[id]; ok {
+ delete(ps.bscWait, id)
+ wait <- peer
+ }
+ ps.lock.Unlock()
+ return err
+ }
+ return (*handler)(h).runBscExtension(peer, hand)
+}
+
+// PeerInfo retrieves all known `bsc` information about a peer.
+func (h *bscHandler) PeerInfo(id enode.ID) interface{} {
+ if p := h.peers.peer(id.String()); p != nil && p.bscExt != nil {
+ return p.bscExt.info()
+ }
+ return nil
+}
+
+// Handle is invoked from a peer's message handler when it receives a new remote
+// message that the handler couldn't consume and serve itself.
+func (h *bscHandler) Handle(peer *bsc.Peer, packet bsc.Packet) error {
+ // DeliverSnapPacket is invoked from a peer's message handler when it transmits a
+ // data packet for the local node to consume.
+ switch packet := packet.(type) {
+ case *bsc.VotesPacket:
+ return h.handleVotesBroadcast(peer, packet.Votes)
+
+ default:
+ return fmt.Errorf("unexpected bsc packet type: %T", packet)
+ }
+}
+
+// handleVotesBroadcast is invoked from a peer's message handler when it transmits a
+// votes broadcast for the local node to process.
+func (h *bscHandler) handleVotesBroadcast(peer *bsc.Peer, votes []*types.VoteEnvelope) error {
+ // Try to put votes into votepool
+ for _, vote := range votes {
+ h.votepool.PutVote(vote)
+ }
+ return nil
+}
diff --git a/eth/handler_bsc_test.go b/eth/handler_bsc_test.go
new file mode 100644
index 0000000000..932826a886
--- /dev/null
+++ b/eth/handler_bsc_test.go
@@ -0,0 +1,276 @@
+package eth
+
+import (
+ "fmt"
+ "testing"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/core/forkid"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/eth/protocols/bsc"
+ "github.com/ethereum/go-ethereum/eth/protocols/eth"
+ "github.com/ethereum/go-ethereum/event"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+)
+
+type testBscHandler struct {
+ voteBroadcasts event.Feed
+}
+
+func (h *testBscHandler) Chain() *core.BlockChain { panic("no backing chain") }
+func (h *testBscHandler) RunPeer(peer *bsc.Peer, handler bsc.Handler) error {
+ panic("not used in tests")
+}
+func (h *testBscHandler) PeerInfo(enode.ID) interface{} { panic("not used in tests") }
+func (h *testBscHandler) Handle(peer *bsc.Peer, packet bsc.Packet) error {
+ switch packet := packet.(type) {
+ case *bsc.VotesPacket:
+ h.voteBroadcasts.Send(packet.Votes)
+ return nil
+
+ default:
+ panic(fmt.Sprintf("unexpected bsc packet type in tests: %T", packet))
+ }
+}
+
+func TestSendVotes67(t *testing.T) { testSendVotes(t, eth.ETH67) }
+
+func testSendVotes(t *testing.T, protocol uint) {
+ t.Parallel()
+
+ // Create a message handler and fill the pool with big votes
+ handler := newTestHandler()
+ defer handler.close()
+
+ insert := make([]*types.VoteEnvelope, 100)
+ for index := range insert {
+ vote := types.VoteEnvelope{
+ VoteAddress: types.BLSPublicKey{},
+ Signature: types.BLSSignature{},
+ Data: &types.VoteData{
+ SourceNumber: uint64(0),
+ SourceHash: common.BytesToHash(common.Hex2Bytes(string(rune(0)))),
+ TargetNumber: uint64(index),
+ TargetHash: common.BytesToHash(common.Hex2Bytes(string(rune(index)))),
+ },
+ }
+ insert[index] = &vote
+ go handler.votepool.PutVote(&vote)
+ }
+ time.Sleep(250 * time.Millisecond) // Wait until vote events get out of the system (can't use events, vote broadcaster races with peer join)
+
+ protos := []p2p.Protocol{
+ {
+ Name: "eth",
+ Version: eth.ETH66,
+ },
+ {
+ Name: "eth",
+ Version: eth.ETH67,
+ },
+ {
+ Name: "bsc",
+ Version: bsc.Bsc1,
+ },
+ }
+ caps := []p2p.Cap{
+ {
+ Name: "eth",
+ Version: eth.ETH66,
+ },
+ {
+ Name: "eth",
+ Version: eth.ETH67,
+ },
+ {
+ Name: "bsc",
+ Version: bsc.Bsc1,
+ },
+ }
+
+ // Create a source handler to send messages through and a sink peer to receive them
+ p2pEthSrc, p2pEthSink := p2p.MsgPipe()
+ defer p2pEthSrc.Close()
+ defer p2pEthSink.Close()
+
+ localEth := eth.NewPeer(protocol, p2p.NewPeerWithProtocols(enode.ID{1}, protos, "", caps), p2pEthSrc, nil)
+ remoteEth := eth.NewPeer(protocol, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", caps), p2pEthSink, nil)
+ defer localEth.Close()
+ defer remoteEth.Close()
+
+ p2pBscSrc, p2pBscSink := p2p.MsgPipe()
+ defer p2pBscSrc.Close()
+ defer p2pBscSink.Close()
+
+ localBsc := bsc.NewPeer(bsc.Bsc1, p2p.NewPeerWithProtocols(enode.ID{1}, protos, "", caps), p2pBscSrc)
+ remoteBsc := bsc.NewPeer(bsc.Bsc1, p2p.NewPeerWithProtocols(enode.ID{3}, protos, "", caps), p2pBscSink)
+ defer localBsc.Close()
+ defer remoteBsc.Close()
+
+ go func(p *bsc.Peer) {
+ (*bscHandler)(handler.handler).RunPeer(p, func(peer *bsc.Peer) error {
+ return bsc.Handle((*bscHandler)(handler.handler), peer)
+ })
+ }(localBsc)
+
+ time.Sleep(200 * time.Millisecond)
+ remoteBsc.Handshake()
+
+ time.Sleep(200 * time.Millisecond)
+ go func(p *eth.Peer) {
+ handler.handler.runEthPeer(p, func(peer *eth.Peer) error {
+ return eth.Handle((*ethHandler)(handler.handler), peer)
+ })
+ }(localEth)
+
+ // Run the handshake locally to avoid spinning up a source handler
+ var (
+ genesis = handler.chain.Genesis()
+ head = handler.chain.CurrentBlock()
+ td = handler.chain.GetTd(head.Hash(), head.NumberU64())
+ )
+ time.Sleep(200 * time.Millisecond)
+ if err := remoteEth.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain), nil); err != nil {
+ t.Fatalf("failed to run protocol handshake: %d", err)
+ }
+ // After the handshake completes, the source handler should stream the sink
+ // the votes, subscribe to all inbound network events
+ backend := new(testBscHandler)
+ bcasts := make(chan []*types.VoteEnvelope)
+ bcastSub := backend.voteBroadcasts.Subscribe(bcasts)
+ defer bcastSub.Unsubscribe()
+
+ go bsc.Handle(backend, remoteBsc)
+
+ // Make sure we get all the votes on the correct channels
+ seen := make(map[common.Hash]struct{})
+ for len(seen) < len(insert) {
+ votes := <-bcasts
+ for _, vote := range votes {
+ if _, ok := seen[vote.Hash()]; ok {
+ t.Errorf("duplicate vote broadcast: %x", vote.Hash())
+ }
+ seen[vote.Hash()] = struct{}{}
+ }
+ }
+ for _, vote := range insert {
+ if _, ok := seen[vote.Hash()]; !ok {
+ t.Errorf("missing vote: %x", vote.Hash())
+ }
+ }
+
+}
+
+func TestRecvVotes67(t *testing.T) { testRecvVotes(t, eth.ETH67) }
+
+func testRecvVotes(t *testing.T, protocol uint) {
+ t.Parallel()
+
+ // Create a message handler and fill the pool with big votes
+ handler := newTestHandler()
+ defer handler.close()
+
+ protos := []p2p.Protocol{
+ {
+ Name: "eth",
+ Version: eth.ETH66,
+ },
+ {
+ Name: "eth",
+ Version: eth.ETH67,
+ },
+ {
+ Name: "bsc",
+ Version: bsc.Bsc1,
+ },
+ }
+ caps := []p2p.Cap{
+ {
+ Name: "eth",
+ Version: eth.ETH66,
+ },
+ {
+ Name: "eth",
+ Version: eth.ETH67,
+ },
+ {
+ Name: "bsc",
+ Version: bsc.Bsc1,
+ },
+ }
+
+ // Create a source handler to send messages through and a sink peer to receive them
+ p2pEthSrc, p2pEthSink := p2p.MsgPipe()
+ defer p2pEthSrc.Close()
+ defer p2pEthSink.Close()
+
+ localEth := eth.NewPeer(protocol, p2p.NewPeerWithProtocols(enode.ID{1}, protos, "", caps), p2pEthSrc, nil)
+ remoteEth := eth.NewPeer(protocol, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", caps), p2pEthSink, nil)
+ defer localEth.Close()
+ defer remoteEth.Close()
+
+ p2pBscSrc, p2pBscSink := p2p.MsgPipe()
+ defer p2pBscSrc.Close()
+ defer p2pBscSink.Close()
+
+ localBsc := bsc.NewPeer(bsc.Bsc1, p2p.NewPeerWithProtocols(enode.ID{1}, protos, "", caps), p2pBscSrc)
+ remoteBsc := bsc.NewPeer(bsc.Bsc1, p2p.NewPeerWithProtocols(enode.ID{3}, protos, "", caps), p2pBscSink)
+ defer localBsc.Close()
+ defer remoteBsc.Close()
+
+ go func(p *bsc.Peer) {
+ (*bscHandler)(handler.handler).RunPeer(p, func(peer *bsc.Peer) error {
+ return bsc.Handle((*bscHandler)(handler.handler), peer)
+ })
+ }(localBsc)
+
+ time.Sleep(200 * time.Millisecond)
+ remoteBsc.Handshake()
+
+ time.Sleep(200 * time.Millisecond)
+ go func(p *eth.Peer) {
+ handler.handler.runEthPeer(p, func(peer *eth.Peer) error {
+ return eth.Handle((*ethHandler)(handler.handler), peer)
+ })
+ }(localEth)
+
+ // Run the handshake locally to avoid spinning up a source handler
+ var (
+ genesis = handler.chain.Genesis()
+ head = handler.chain.CurrentBlock()
+ td = handler.chain.GetTd(head.Hash(), head.NumberU64())
+ )
+ time.Sleep(200 * time.Millisecond)
+ if err := remoteEth.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain), nil); err != nil {
+ t.Fatalf("failed to run protocol handshake: %d", err)
+ }
+
+ votesCh := make(chan core.NewVoteEvent)
+ sub := handler.votepool.SubscribeNewVoteEvent(votesCh)
+ defer sub.Unsubscribe()
+ // Send the vote to the sink and verify that it's added to the vote pool
+ vote := types.VoteEnvelope{
+ VoteAddress: types.BLSPublicKey{},
+ Signature: types.BLSSignature{},
+ Data: &types.VoteData{
+ SourceNumber: uint64(0),
+ SourceHash: common.BytesToHash(common.Hex2Bytes(string(rune(0)))),
+ TargetNumber: uint64(1),
+ TargetHash: common.BytesToHash(common.Hex2Bytes(string(rune(1)))),
+ },
+ }
+
+ remoteBsc.AsyncSendVotes([]*types.VoteEnvelope{&vote})
+ time.Sleep(100 * time.Millisecond)
+ select {
+ case event := <-votesCh:
+ if event.Vote.Hash() != vote.Hash() {
+ t.Errorf("added wrong vote hash: got %v, want %v", event.Vote.Hash(), vote.Hash())
+ }
+ case <-time.After(2 * time.Second):
+ t.Errorf("no NewVotesEvent received within 2 seconds")
+ }
+}
diff --git a/eth/handler_diff_test.go b/eth/handler_diff_test.go
index 0956459d98..06d16b4116 100644
--- a/eth/handler_diff_test.go
+++ b/eth/handler_diff_test.go
@@ -84,11 +84,13 @@ func newTestBackendWithGenerator(blocks int) *testBackend {
panic(err)
}
txpool := newTestTxPool()
+ votepool := newTestVotePool()
handler, _ := newHandler(&handlerConfig{
Database: db,
Chain: chain,
TxPool: txpool,
+ VotePool: votepool,
Network: 1,
Sync: downloader.FullSync,
BloomCache: 1,
diff --git a/eth/handler_eth.go b/eth/handler_eth.go
index 8f01cf528c..f7e3fba880 100644
--- a/eth/handler_eth.go
+++ b/eth/handler_eth.go
@@ -76,6 +76,7 @@ func (h *ethHandler) Handle(peer *eth.Peer, packet eth.Packet) error {
case *eth.PooledTransactionsPacket:
return h.txFetcher.Enqueue(peer.ID(), *packet, true)
+
default:
return fmt.Errorf("unexpected eth packet type: %T", packet)
}
diff --git a/eth/handler_eth_test.go b/eth/handler_eth_test.go
index 74db6668c3..de57e475c4 100644
--- a/eth/handler_eth_test.go
+++ b/eth/handler_eth_test.go
@@ -33,6 +33,7 @@ import (
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/core/vm"
"github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/eth/protocols/bsc"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/p2p"
@@ -90,11 +91,25 @@ func testForkIDSplit(t *testing.T, protocol uint) {
configNoFork = ¶ms.ChainConfig{HomesteadBlock: big.NewInt(1)}
configProFork = ¶ms.ChainConfig{
- HomesteadBlock: big.NewInt(1),
- EIP150Block: big.NewInt(2),
- EIP155Block: big.NewInt(2),
- EIP158Block: big.NewInt(2),
- ByzantiumBlock: big.NewInt(3),
+ HomesteadBlock: big.NewInt(1),
+ EIP150Block: big.NewInt(2),
+ EIP155Block: big.NewInt(2),
+ EIP158Block: big.NewInt(2),
+ ByzantiumBlock: big.NewInt(3),
+ ConstantinopleBlock: big.NewInt(4),
+ PetersburgBlock: big.NewInt(4),
+ IstanbulBlock: big.NewInt(4),
+ MuirGlacierBlock: big.NewInt(4),
+ RamanujanBlock: big.NewInt(4),
+ NielsBlock: big.NewInt(4),
+ MirrorSyncBlock: big.NewInt(4),
+ BrunoBlock: big.NewInt(4),
+ EulerBlock: big.NewInt(5),
+ GibbsBlock: big.NewInt(5),
+ NanoBlock: big.NewInt(5),
+ MoranBlock: big.NewInt(5),
+ BonehBlock: big.NewInt(6),
+ LynnBlock: big.NewInt(6),
}
dbNoFork = rawdb.NewMemoryDatabase()
dbProFork = rawdb.NewMemoryDatabase()
@@ -115,6 +130,7 @@ func testForkIDSplit(t *testing.T, protocol uint) {
Database: dbNoFork,
Chain: chainNoFork,
TxPool: newTestTxPool(),
+ VotePool: newTestVotePool(),
Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()),
Network: 1,
Sync: downloader.FullSync,
@@ -124,6 +140,7 @@ func testForkIDSplit(t *testing.T, protocol uint) {
Database: dbProFork,
Chain: chainProFork,
TxPool: newTestTxPool(),
+ VotePool: newTestVotePool(),
Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()),
Network: 1,
Sync: downloader.FullSync,
@@ -230,7 +247,7 @@ func testForkIDSplit(t *testing.T, protocol uint) {
t.Fatalf("fork ID rejection didn't happen")
}
}
- case <-time.After(250 * time.Millisecond):
+ case <-time.After(10000 * time.Millisecond):
t.Fatalf("split peers not rejected")
}
}
@@ -239,7 +256,63 @@ func testForkIDSplit(t *testing.T, protocol uint) {
// Tests that received transactions are added to the local pool.
func TestRecvTransactions66(t *testing.T) { testRecvTransactions(t, eth.ETH66) }
-func TestWaitDiffExtensionTimout(t *testing.T) {
+func testRecvTransactions(t *testing.T, protocol uint) {
+ t.Parallel()
+
+ // Create a message handler, configure it to accept transactions and watch them
+ handler := newTestHandler()
+ defer handler.close()
+
+ handler.handler.acceptTxs = 1 // mark synced to accept transactions
+
+ txs := make(chan core.NewTxsEvent)
+ sub := handler.txpool.SubscribeNewTxsEvent(txs)
+ defer sub.Unsubscribe()
+
+ // Create a source peer to send messages through and a sink handler to receive them
+ p2pSrc, p2pSink := p2p.MsgPipe()
+ defer p2pSrc.Close()
+ defer p2pSink.Close()
+
+ src := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{1}, "", nil, p2pSrc), p2pSrc, handler.txpool)
+ sink := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{2}, "", nil, p2pSink), p2pSink, handler.txpool)
+ defer src.Close()
+ defer sink.Close()
+
+ go handler.handler.runEthPeer(sink, func(peer *eth.Peer) error {
+ return eth.Handle((*ethHandler)(handler.handler), peer)
+ })
+ // Run the handshake locally to avoid spinning up a source handler
+ var (
+ genesis = handler.chain.Genesis()
+ head = handler.chain.CurrentBlock()
+ td = handler.chain.GetTd(head.Hash(), head.NumberU64())
+ )
+ if err := src.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain), nil); err != nil {
+ t.Fatalf("failed to run protocol handshake")
+ }
+ // Send the transaction to the sink and verify that it's added to the tx pool
+ tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil)
+ tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
+
+ if err := src.SendTransactions([]*types.Transaction{tx}); err != nil {
+ t.Fatalf("failed to send transaction: %v", err)
+ }
+ select {
+ case event := <-txs:
+ if len(event.Txs) != 1 {
+ t.Errorf("wrong number of added transactions: got %d, want 1", len(event.Txs))
+ } else if event.Txs[0].Hash() != tx.Hash() {
+ t.Errorf("added wrong tx hash: got %v, want %v", event.Txs[0].Hash(), tx.Hash())
+ }
+ case <-time.After(2 * time.Second):
+ t.Errorf("no NewTxsEvent received within 2 seconds")
+ }
+}
+
+func TestWaitDiffExtensionTimout67(t *testing.T) { testWaitDiffExtensionTimout(t, eth.ETH67) }
+
+func testWaitDiffExtensionTimout(t *testing.T, protocol uint) {
t.Parallel()
// Create a message handler, configure it to accept transactions and watch them
@@ -257,7 +330,7 @@ func TestWaitDiffExtensionTimout(t *testing.T) {
},
}
- sink := eth.NewPeer(eth.ETH67, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", []p2p.Cap{
+ sink := eth.NewPeer(protocol, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", []p2p.Cap{
{
Name: "diff",
Version: 1,
@@ -274,7 +347,9 @@ func TestWaitDiffExtensionTimout(t *testing.T) {
}
}
-func TestWaitSnapExtensionTimout(t *testing.T) {
+func TestWaitSnapExtensionTimout67(t *testing.T) { testWaitSnapExtensionTimout(t, eth.ETH67) }
+
+func testWaitSnapExtensionTimout(t *testing.T, protocol uint) {
t.Parallel()
// Create a message handler, configure it to accept transactions and watch them
@@ -292,7 +367,7 @@ func TestWaitSnapExtensionTimout(t *testing.T) {
},
}
- sink := eth.NewPeer(eth.ETH67, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", []p2p.Cap{
+ sink := eth.NewPeer(protocol, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", []p2p.Cap{
{
Name: "snap",
Version: 1,
@@ -309,57 +384,40 @@ func TestWaitSnapExtensionTimout(t *testing.T) {
}
}
-func testRecvTransactions(t *testing.T, protocol uint) {
+func TestWaitBscExtensionTimout67(t *testing.T) { testWaitBscExtensionTimout(t, eth.ETH67) }
+
+func testWaitBscExtensionTimout(t *testing.T, protocol uint) {
t.Parallel()
// Create a message handler, configure it to accept transactions and watch them
handler := newTestHandler()
defer handler.close()
- handler.handler.acceptTxs = 1 // mark synced to accept transactions
-
- txs := make(chan core.NewTxsEvent)
- sub := handler.txpool.SubscribeNewTxsEvent(txs)
- defer sub.Unsubscribe()
-
// Create a source peer to send messages through and a sink handler to receive them
- p2pSrc, p2pSink := p2p.MsgPipe()
- defer p2pSrc.Close()
+ _, p2pSink := p2p.MsgPipe()
defer p2pSink.Close()
- src := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{1}, "", nil, p2pSrc), p2pSrc, handler.txpool)
- sink := eth.NewPeer(protocol, p2p.NewPeerPipe(enode.ID{2}, "", nil, p2pSink), p2pSink, handler.txpool)
- defer src.Close()
+ protos := []p2p.Protocol{
+ {
+ Name: "bsc",
+ Version: bsc.Bsc1,
+ },
+ }
+
+ sink := eth.NewPeer(protocol, p2p.NewPeerWithProtocols(enode.ID{2}, protos, "", []p2p.Cap{
+ {
+ Name: "bsc",
+ Version: bsc.Bsc1,
+ },
+ }), p2pSink, nil)
defer sink.Close()
- go handler.handler.runEthPeer(sink, func(peer *eth.Peer) error {
+ err := handler.handler.runEthPeer(sink, func(peer *eth.Peer) error {
return eth.Handle((*ethHandler)(handler.handler), peer)
})
- // Run the handshake locally to avoid spinning up a source handler
- var (
- genesis = handler.chain.Genesis()
- head = handler.chain.CurrentBlock()
- td = handler.chain.GetTd(head.Hash(), head.NumberU64())
- )
- if err := src.Handshake(1, td, head.Hash(), genesis.Hash(), forkid.NewIDWithChain(handler.chain), forkid.NewFilter(handler.chain), nil); err != nil {
- t.Fatalf("failed to run protocol handshake")
- }
- // Send the transaction to the sink and verify that it's added to the tx pool
- tx := types.NewTransaction(0, common.Address{}, big.NewInt(0), 100000, big.NewInt(0), nil)
- tx, _ = types.SignTx(tx, types.HomesteadSigner{}, testKey)
- if err := src.SendTransactions([]*types.Transaction{tx}); err != nil {
- t.Fatalf("failed to send transaction: %v", err)
- }
- select {
- case event := <-txs:
- if len(event.Txs) != 1 {
- t.Errorf("wrong number of added transactions: got %d, want 1", len(event.Txs))
- } else if event.Txs[0].Hash() != tx.Hash() {
- t.Errorf("added wrong tx hash: got %v, want %v", event.Txs[0].Hash(), tx.Hash())
- }
- case <-time.After(2 * time.Second):
- t.Errorf("no NewTxsEvent received within 2 seconds")
+ if err == nil || err.Error() != "peer wait timeout" {
+ t.Fatalf("error should be `peer wait timeout`")
}
}
diff --git a/eth/handler_test.go b/eth/handler_test.go
index 4d4c11592c..b38248e47b 100644
--- a/eth/handler_test.go
+++ b/eth/handler_test.go
@@ -136,10 +136,11 @@ func (p *testTxPool) SubscribeReannoTxsEvent(ch chan<- core.ReannoTxsEvent) even
// preinitialized with some sane testing defaults and the transaction pool mocked
// out.
type testHandler struct {
- db ethdb.Database
- chain *core.BlockChain
- txpool *testTxPool
- handler *handler
+ db ethdb.Database
+ chain *core.BlockChain
+ txpool *testTxPool
+ votepool *testVotePool
+ handler *handler
}
// newTestHandler creates a new handler for testing purposes with no blocks.
@@ -164,12 +165,14 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
panic(err)
}
txpool := newTestTxPool()
+ votepool := newTestVotePool()
handler, _ := newHandler(&handlerConfig{
Database: db,
Chain: chain,
TxPool: txpool,
Merger: consensus.NewMerger(rawdb.NewMemoryDatabase()),
+ VotePool: votepool,
Network: 1,
Sync: downloader.SnapSync,
BloomCache: 1,
@@ -177,10 +180,11 @@ func newTestHandlerWithBlocks(blocks int) *testHandler {
handler.Start(1000)
return &testHandler{
- db: db,
- chain: chain,
- txpool: txpool,
- handler: handler,
+ db: db,
+ chain: chain,
+ txpool: txpool,
+ votepool: votepool,
+ handler: handler,
}
}
@@ -189,3 +193,45 @@ func (b *testHandler) close() {
b.handler.Stop()
b.chain.Stop()
}
+
+// newTestVotePool creates a mock vote pool.
+type testVotePool struct {
+ pool map[common.Hash]*types.VoteEnvelope // Hash map of collected votes
+
+ voteFeed event.Feed // Notification feed to allow waiting for inclusion
+ lock sync.RWMutex // Protects the vote pool
+}
+
+// newTestVotePool creates a mock vote pool.
+func newTestVotePool() *testVotePool {
+ return &testVotePool{
+ pool: make(map[common.Hash]*types.VoteEnvelope),
+ }
+}
+
+func (t *testVotePool) PutVote(vote *types.VoteEnvelope) {
+ t.lock.Lock()
+ defer t.lock.Unlock()
+
+ t.pool[vote.Hash()] = vote
+ t.voteFeed.Send(core.NewVoteEvent{Vote: vote})
+}
+
+func (t *testVotePool) FetchVoteByBlockHash(blockHash common.Hash) []*types.VoteEnvelope {
+ panic("implement me")
+}
+
+func (t *testVotePool) GetVotes() []*types.VoteEnvelope {
+ t.lock.RLock()
+ defer t.lock.RUnlock()
+
+ votes := make([]*types.VoteEnvelope, 0, len(t.pool))
+ for _, vote := range t.pool {
+ votes = append(votes, vote)
+ }
+ return votes
+}
+
+func (t *testVotePool) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription {
+ return t.voteFeed.Subscribe(ch)
+}
diff --git a/eth/peer.go b/eth/peer.go
index 802d1e5aac..77a150434c 100644
--- a/eth/peer.go
+++ b/eth/peer.go
@@ -20,6 +20,7 @@ import (
"math/big"
"time"
+ "github.com/ethereum/go-ethereum/eth/protocols/bsc"
"github.com/ethereum/go-ethereum/eth/protocols/trust"
"github.com/ethereum/go-ethereum/eth/protocols/diff"
@@ -41,6 +42,7 @@ type ethPeer struct {
snapExt *snapPeer // Satellite `snap` connection
diffExt *diffPeer
trustExt *trustPeer
+ bscExt *bscPeer // Satellite `bsc` connection
syncDrop *time.Timer // Connection dropper if `eth` sync progress isn't validated in time
snapWait chan struct{} // Notification channel for snap connections
@@ -76,6 +78,12 @@ type trustPeerInfo struct {
Version uint `json:"version"` // Trust protocol version negotiated
}
+// bscPeerInfo represents a short summary of the `bsc` sub-protocol metadata known
+// about a connected peer.
+type bscPeerInfo struct {
+ Version uint `json:"version"` // bsc protocol version negotiated
+}
+
// snapPeer is a wrapper around snap.Peer to maintain a few extra metadata.
type snapPeer struct {
*snap.Peer
@@ -91,6 +99,11 @@ type trustPeer struct {
*trust.Peer
}
+// bscPeer is a wrapper around bsc.Peer to maintain a few extra metadata.
+type bscPeer struct {
+ *bsc.Peer
+}
+
// info gathers and returns some `diff` protocol metadata known about a peer.
func (p *diffPeer) info() *diffPeerInfo {
return &diffPeerInfo{
@@ -112,3 +125,10 @@ func (p *trustPeer) info() *trustPeerInfo {
Version: p.Version(),
}
}
+
+// info gathers and returns some `bsc` protocol metadata known about a peer.
+func (p *bscPeer) info() *bscPeerInfo {
+ return &bscPeerInfo{
+ Version: p.Version(),
+ }
+}
diff --git a/eth/peerset.go b/eth/peerset.go
index 6484dae8dd..6a84449fe1 100644
--- a/eth/peerset.go
+++ b/eth/peerset.go
@@ -25,6 +25,7 @@ import (
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/eth/downloader"
+ "github.com/ethereum/go-ethereum/eth/protocols/bsc"
"github.com/ethereum/go-ethereum/eth/protocols/diff"
"github.com/ethereum/go-ethereum/eth/protocols/eth"
"github.com/ethereum/go-ethereum/eth/protocols/snap"
@@ -59,6 +60,10 @@ var (
// errTrustWithoutEth is returned if a peer attempts to connect only on the
// trust protocol without advertising the eth main protocol.
errTrustWithoutEth = errors.New("peer connected on trust without compatible eth support")
+
+ // errBscWithoutEth is returned if a peer attempts to connect only on the
+ // bsc protocol without advertising the eth main protocol.
+ errBscWithoutEth = errors.New("peer connected on bsc without compatible eth support")
)
const (
@@ -82,6 +87,9 @@ type peerSet struct {
trustWait map[string]chan *trust.Peer // Peers connected on `eth` waiting for their trust extension
trustPend map[string]*trust.Peer // Peers connected on the `trust` protocol, but not yet on `eth`
+ bscWait map[string]chan *bsc.Peer // Peers connected on `eth` waiting for their bsc extension
+ bscPend map[string]*bsc.Peer // Peers connected on the `bsc` protocol, but not yet on `eth`
+
lock sync.RWMutex
closed bool
}
@@ -96,6 +104,8 @@ func newPeerSet() *peerSet {
diffPend: make(map[string]*diff.Peer),
trustWait: make(map[string]chan *trust.Peer),
trustPend: make(map[string]*trust.Peer),
+ bscWait: make(map[string]chan *bsc.Peer),
+ bscPend: make(map[string]*bsc.Peer),
}
}
@@ -193,6 +203,36 @@ func (ps *peerSet) registerTrustExtension(peer *trust.Peer) error {
return nil
}
+// registerBscExtension unblocks an already connected `eth` peer waiting for its
+// `bsc` extension, or if no such peer exists, tracks the extension for the time
+// being until the `eth` main protocol starts looking for it.
+func (ps *peerSet) registerBscExtension(peer *bsc.Peer) error {
+ // Reject the peer if it advertises `bsc` without `eth` as `bsc` is only a
+ // satellite protocol meaningful with the chain selection of `eth`
+ if !peer.RunningCap(eth.ProtocolName, eth.ProtocolVersions) {
+ return errBscWithoutEth
+ }
+ // Ensure nobody can double connect
+ ps.lock.Lock()
+ defer ps.lock.Unlock()
+
+ id := peer.ID()
+ if _, ok := ps.peers[id]; ok {
+ return errPeerAlreadyRegistered // avoid connections with the same id as existing ones
+ }
+ if _, ok := ps.bscPend[id]; ok {
+ return errPeerAlreadyRegistered // avoid connections with the same id as pending ones
+ }
+ // Inject the peer into an `eth` counterpart is available, otherwise save for later
+ if wait, ok := ps.bscWait[id]; ok {
+ delete(ps.bscWait, id)
+ wait <- peer
+ return nil
+ }
+ ps.bscPend[id] = peer
+ return nil
+}
+
// waitExtensions blocks until all satellite protocols are connected and tracked
// by the peerset.
func (ps *peerSet) waitSnapExtension(peer *eth.Peer) (*snap.Peer, error) {
@@ -326,6 +366,49 @@ func (ps *peerSet) waitTrustExtension(peer *eth.Peer) (*trust.Peer, error) {
}
}
+// waitBscExtension blocks until all satellite protocols are connected and tracked
+// by the peerset.
+func (ps *peerSet) waitBscExtension(peer *eth.Peer) (*bsc.Peer, error) {
+ // If the peer does not support a compatible `bsc`, don't wait
+ if !peer.RunningCap(bsc.ProtocolName, bsc.ProtocolVersions) {
+ return nil, nil
+ }
+ // Ensure nobody can double connect
+ ps.lock.Lock()
+
+ id := peer.ID()
+ if _, ok := ps.peers[id]; ok {
+ ps.lock.Unlock()
+ return nil, errPeerAlreadyRegistered // avoid connections with the same id as existing ones
+ }
+ if _, ok := ps.bscWait[id]; ok {
+ ps.lock.Unlock()
+ return nil, errPeerAlreadyRegistered // avoid connections with the same id as pending ones
+ }
+ // If `bsc` already connected, retrieve the peer from the pending set
+ if bsc, ok := ps.bscPend[id]; ok {
+ delete(ps.bscPend, id)
+
+ ps.lock.Unlock()
+ return bsc, nil
+ }
+ // Otherwise wait for `bsc` to connect concurrently
+ wait := make(chan *bsc.Peer)
+ ps.bscWait[id] = wait
+ ps.lock.Unlock()
+
+ select {
+ case peer := <-wait:
+ return peer, nil
+
+ case <-time.After(extensionWaitTimeout):
+ ps.lock.Lock()
+ delete(ps.bscWait, id)
+ ps.lock.Unlock()
+ return nil, errPeerWaitTimeout
+ }
+}
+
func (ps *peerSet) GetDiffPeer(pid string) downloader.IDiffPeer {
if p := ps.peer(pid); p != nil && p.diffExt != nil {
return p.diffExt
@@ -349,7 +432,7 @@ func (ps *peerSet) GetVerifyPeers() []core.VerifyPeer {
// registerPeer injects a new `eth` peer into the working set, or returns an error
// if the peer is already known.
-func (ps *peerSet) registerPeer(peer *eth.Peer, ext *snap.Peer, diffExt *diff.Peer, trustExt *trust.Peer) error {
+func (ps *peerSet) registerPeer(peer *eth.Peer, ext *snap.Peer, diffExt *diff.Peer, trustExt *trust.Peer, bscExt *bsc.Peer) error {
// Start tracking the new peer
ps.lock.Lock()
defer ps.lock.Unlock()
@@ -374,6 +457,9 @@ func (ps *peerSet) registerPeer(peer *eth.Peer, ext *snap.Peer, diffExt *diff.Pe
if trustExt != nil {
eth.trustExt = &trustPeer{trustExt}
}
+ if bscExt != nil {
+ eth.bscExt = &bscPeer{bscExt}
+ }
ps.peers[id] = eth
return nil
}
@@ -420,7 +506,7 @@ func (ps *peerSet) headPeers(num uint) []*ethPeer {
}
// peersWithoutBlock retrieves a list of peers that do not have a given block in
-// their set of known hashes so it might be propagated to them.
+// their set of known hashes, so it might be propagated to them.
func (ps *peerSet) peersWithoutBlock(hash common.Hash) []*ethPeer {
ps.lock.RLock()
defer ps.lock.RUnlock()
@@ -449,6 +535,21 @@ func (ps *peerSet) peersWithoutTransaction(hash common.Hash) []*ethPeer {
return list
}
+// peersWithoutVote retrieves a list of peers that do not have a given
+// vote in their set of known hashes.
+func (ps *peerSet) peersWithoutVote(hash common.Hash) []*ethPeer {
+ ps.lock.RLock()
+ defer ps.lock.RUnlock()
+
+ list := make([]*ethPeer, 0, len(ps.peers))
+ for _, p := range ps.peers {
+ if p.bscExt != nil && !p.bscExt.KnownVote(hash) {
+ list = append(list, p)
+ }
+ }
+ return list
+}
+
// len returns if the current number of `eth` peers in the set. Since the `snap`
// peers are tied to the existence of an `eth` connection, that will always be a
// subset of `eth`.
diff --git a/eth/protocols/bsc/discovery.go b/eth/protocols/bsc/discovery.go
new file mode 100644
index 0000000000..6a4fac346e
--- /dev/null
+++ b/eth/protocols/bsc/discovery.go
@@ -0,0 +1,16 @@
+package bsc
+
+import (
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// enrEntry is the ENR entry which advertises `bsc` protocol on the discovery.
+type enrEntry struct {
+ // Ignore additional fields (for forward compatibility).
+ Rest []rlp.RawValue `rlp:"tail"`
+}
+
+// ENRKey implements enr.Entry.
+func (e enrEntry) ENRKey() string {
+ return "bsc"
+}
diff --git a/eth/protocols/bsc/handler.go b/eth/protocols/bsc/handler.go
new file mode 100644
index 0000000000..e993f255f3
--- /dev/null
+++ b/eth/protocols/bsc/handler.go
@@ -0,0 +1,145 @@
+package bsc
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/ethereum/go-ethereum/core"
+ "github.com/ethereum/go-ethereum/metrics"
+ "github.com/ethereum/go-ethereum/p2p"
+ "github.com/ethereum/go-ethereum/p2p/enode"
+ "github.com/ethereum/go-ethereum/p2p/enr"
+)
+
+// Handler is a callback to invoke from an outside runner after the boilerplate
+// exchanges have passed.
+type Handler func(peer *Peer) error
+
+type Backend interface {
+ // Chain retrieves the blockchain object to serve data.
+ Chain() *core.BlockChain
+
+ // RunPeer is invoked when a peer joins on the `bsc` protocol. The handler
+ // should do any peer maintenance work, handshakes and validations. If all
+ // is passed, control should be given back to the `handler` to process the
+ // inbound messages going forward.
+ RunPeer(peer *Peer, handler Handler) error
+
+ // PeerInfo retrieves all known `bsc` information about a peer.
+ PeerInfo(id enode.ID) interface{}
+
+ // Handle is a callback to be invoked when a data packet is received from
+ // the remote peer. Only packets not consumed by the protocol handler will
+ // be forwarded to the backend.
+ Handle(peer *Peer, packet Packet) error
+}
+
+// MakeProtocols constructs the P2P protocol definitions for `bsc`.
+func MakeProtocols(backend Backend, dnsdisc enode.Iterator) []p2p.Protocol {
+ // Filter the discovery iterator for nodes advertising vote support.
+ dnsdisc = enode.Filter(dnsdisc, func(n *enode.Node) bool {
+ var vote enrEntry
+ return n.Load(&vote) == nil
+ })
+
+ protocols := make([]p2p.Protocol, len(ProtocolVersions))
+ for i, version := range ProtocolVersions {
+ version := version // Closure
+
+ protocols[i] = p2p.Protocol{
+ Name: ProtocolName,
+ Version: version,
+ Length: protocolLengths[version],
+ Run: func(p *p2p.Peer, rw p2p.MsgReadWriter) error {
+ peer := NewPeer(version, p, rw)
+ defer peer.Close()
+
+ return backend.RunPeer(peer, func(peer *Peer) error {
+ return Handle(backend, peer)
+ })
+ },
+ NodeInfo: func() interface{} {
+ return nodeInfo(backend.Chain())
+ },
+ PeerInfo: func(id enode.ID) interface{} {
+ return backend.PeerInfo(id)
+ },
+ Attributes: []enr.Entry{&enrEntry{}},
+ DialCandidates: dnsdisc,
+ }
+ }
+ return protocols
+}
+
+// Handle is the callback invoked to manage the life cycle of a `bsc` peer.
+// When this function terminates, the peer is disconnected.
+func Handle(backend Backend, peer *Peer) error {
+ for {
+ if err := handleMessage(backend, peer); err != nil {
+ peer.Log().Debug("Message handling failed in `bsc`", "err", err)
+ return err
+ }
+ }
+}
+
+type msgHandler func(backend Backend, msg Decoder, peer *Peer) error
+type Decoder interface {
+ Decode(val interface{}) error
+}
+
+var bsc1 = map[uint64]msgHandler{
+ VotesMsg: handleVotes,
+}
+
+// handleMessage is invoked whenever an inbound message is received from a
+// remote peer on the `bsc` protocol. The remote connection is torn down upon
+// returning any error.
+func handleMessage(backend Backend, peer *Peer) error {
+ // Read the next message from the remote peer, and ensure it's fully consumed
+ msg, err := peer.rw.ReadMsg()
+ if err != nil {
+ return err
+ }
+ if msg.Size > maxMessageSize {
+ return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize)
+ }
+ defer msg.Discard()
+
+ var handlers = bsc1
+
+ // Track the amount of time it takes to serve the request and run the handler
+ if metrics.Enabled {
+ h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code)
+ defer func(start time.Time) {
+ sampler := func() metrics.Sample {
+ return metrics.ResettingSample(
+ metrics.NewExpDecaySample(1028, 0.015),
+ )
+ }
+ metrics.GetOrRegisterHistogramLazy(h, nil, sampler).Update(time.Since(start).Microseconds())
+ }(time.Now())
+ }
+ if handler := handlers[msg.Code]; handler != nil {
+ return handler(backend, msg, peer)
+ }
+ return fmt.Errorf("%w: %v", errInvalidMsgCode, msg.Code)
+}
+
+func handleVotes(backend Backend, msg Decoder, peer *Peer) error {
+ ann := new(VotesPacket)
+ if err := msg.Decode(ann); err != nil {
+ return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
+ }
+ // Schedule all the unknown hashes for retrieval
+ peer.markVotes(ann.Votes)
+ return backend.Handle(peer, ann)
+}
+
+// NodeInfo represents a short summary of the `bsc` sub-protocol metadata
+// known about the host peer.
+type NodeInfo struct{}
+
+// nodeInfo retrieves some `bsc` protocol metadata about the running host node.
+func nodeInfo(_ *core.BlockChain) *NodeInfo {
+ return &NodeInfo{}
+}
diff --git a/eth/protocols/bsc/handshake.go b/eth/protocols/bsc/handshake.go
new file mode 100644
index 0000000000..c8e74f3d12
--- /dev/null
+++ b/eth/protocols/bsc/handshake.go
@@ -0,0 +1,68 @@
+package bsc
+
+import (
+ "fmt"
+ "time"
+
+ "github.com/ethereum/go-ethereum/common/gopool"
+ "github.com/ethereum/go-ethereum/p2p"
+)
+
+const (
+ // handshakeTimeout is the maximum allowed time for the `bsc` handshake to
+ // complete before dropping the connection as malicious.
+ handshakeTimeout = 5 * time.Second
+)
+
+// Handshake executes the bsc protocol handshake,
+func (p *Peer) Handshake() error {
+ // Send out own handshake in a new thread
+ errc := make(chan error, 2)
+
+ var cap BscCapPacket // safe to read after two values have been received from errc
+
+ gopool.Submit(func() {
+ errc <- p2p.Send(p.rw, BscCapMsg, &BscCapPacket{
+ ProtocolVersion: p.version,
+ Extra: defaultExtra,
+ })
+ })
+ gopool.Submit(func() {
+ errc <- p.readCap(&cap)
+ })
+ timeout := time.NewTimer(handshakeTimeout)
+ defer timeout.Stop()
+ for i := 0; i < 2; i++ {
+ select {
+ case err := <-errc:
+ if err != nil {
+ return err
+ }
+ case <-timeout.C:
+ return p2p.DiscReadTimeout
+ }
+ }
+ return nil
+}
+
+// readCap reads the remote handshake message.
+func (p *Peer) readCap(cap *BscCapPacket) error {
+ msg, err := p.rw.ReadMsg()
+ if err != nil {
+ return err
+ }
+ if msg.Code != BscCapMsg {
+ return fmt.Errorf("%w: first msg has code %x (!= %x)", errNoBscCapMsg, msg.Code, BscCapMsg)
+ }
+ if msg.Size > maxMessageSize {
+ return fmt.Errorf("%w: %v > %v", errMsgTooLarge, msg.Size, maxMessageSize)
+ }
+ // Decode the handshake and make sure everything matches
+ if err := msg.Decode(cap); err != nil {
+ return fmt.Errorf("%w: message %v: %v", errDecode, msg, err)
+ }
+ if cap.ProtocolVersion != p.version {
+ return fmt.Errorf("%w: %d (!= %d)", errProtocolVersionMismatch, cap.ProtocolVersion, p.version)
+ }
+ return nil
+}
diff --git a/eth/protocols/bsc/peer.go b/eth/protocols/bsc/peer.go
new file mode 100644
index 0000000000..e66ab2a6b3
--- /dev/null
+++ b/eth/protocols/bsc/peer.go
@@ -0,0 +1,157 @@
+package bsc
+
+import (
+ mapset "github.com/deckarep/golang-set"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/log"
+ "github.com/ethereum/go-ethereum/p2p"
+)
+
+const (
+ // maxKnownVotes is the maximum vote hashes to keep in the known list
+ // before starting to randomly evict them.
+ maxKnownVotes = 5376
+)
+
+// max is a helper function which returns the larger of the two given integers.
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+// Peer is a collection of relevant information we have about a `bsc` peer.
+type Peer struct {
+ id string // Unique ID for the peer, cached
+ knownVotes *knownCache // Set of vote hashes known to be known by this peer
+ voteBroadcast chan []*types.VoteEnvelope // Channel used to queue votes propagation requests
+
+ *p2p.Peer // The embedded P2P package peer
+ rw p2p.MsgReadWriter // Input/output streams for bsc
+ version uint // Protocol version negotiated
+ logger log.Logger // Contextual logger with the peer id injected
+ term chan struct{} // Termination channel to stop the broadcasters
+}
+
+// NewPeer create a wrapper for a network connection and negotiated protocol
+// version.
+func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter) *Peer {
+ id := p.ID().String()
+ peer := &Peer{
+ id: id,
+ knownVotes: newKnownCache(maxKnownVotes),
+ voteBroadcast: make(chan []*types.VoteEnvelope),
+ Peer: p,
+ rw: rw,
+ version: version,
+ logger: log.New("peer", id[:8]),
+ term: make(chan struct{}),
+ }
+ go peer.broadcastVotes()
+ return peer
+}
+
+// ID retrieves the peer's unique identifier.
+func (p *Peer) ID() string {
+ return p.id
+}
+
+// Version retrieves the peer's negotiated `bsc` protocol version.
+func (p *Peer) Version() uint {
+ return p.version
+}
+
+// Log overrides the P2P logget with the higher level one containing only the id.
+func (p *Peer) Log() log.Logger {
+ return p.logger
+}
+
+// Close signals the broadcast goroutine to terminate. Only ever call this if
+// you created the peer yourself via NewPeer. Otherwise let whoever created it
+// clean it up!
+func (p *Peer) Close() {
+ close(p.term)
+}
+
+// KnownVote returns whether peer is known to already have a vote.
+func (p *Peer) KnownVote(hash common.Hash) bool {
+ return p.knownVotes.contains(hash)
+}
+
+// markVotes marks votes as known for the peer, ensuring that they
+// will never be repropagated to this particular peer.
+func (p *Peer) markVotes(votes []*types.VoteEnvelope) {
+ for _, vote := range votes {
+ if !p.knownVotes.contains(vote.Hash()) {
+ // If we reached the memory allowance, drop a previously known vote hash
+ p.knownVotes.add(vote.Hash())
+ }
+ }
+}
+
+// sendVotes propagates a batch of votes to the remote peer.
+func (p *Peer) sendVotes(votes []*types.VoteEnvelope) error {
+ // Mark all the votes as known, but ensure we don't overflow our limits
+ p.markVotes(votes)
+ return p2p.Send(p.rw, VotesMsg, &VotesPacket{votes})
+}
+
+// AsyncSendVotes queues a batch of vote hashes for propagation to a remote peer. If
+// the peer's broadcast queue is full, the event is silently dropped.
+func (p *Peer) AsyncSendVotes(votes []*types.VoteEnvelope) {
+ select {
+ case p.voteBroadcast <- votes:
+ case <-p.term:
+ p.Log().Debug("Dropping vote propagation", "count", len(votes))
+ }
+}
+
+// broadcastVotes is a write loop that schedules votes broadcasts
+// to the remote peer. The goal is to have an async writer that does not lock up
+// node internals and at the same time rate limits queued data.
+func (p *Peer) broadcastVotes() {
+ for {
+ select {
+ case votes := <-p.voteBroadcast:
+ if err := p.sendVotes(votes); err != nil {
+ return
+ }
+ p.Log().Trace("Sent votes", "count", len(votes))
+
+ case <-p.term:
+ return
+ }
+ }
+}
+
+// knownCache is a cache for known hashes.
+type knownCache struct {
+ hashes mapset.Set
+ max int
+}
+
+// newKnownCache creates a new knownCache with a max capacity.
+func newKnownCache(max int) *knownCache {
+ return &knownCache{
+ max: max,
+ hashes: mapset.NewSet(),
+ }
+}
+
+// add adds a list of elements to the set.
+func (k *knownCache) add(hashes ...common.Hash) {
+ for k.hashes.Cardinality() > max(0, k.max-len(hashes)) {
+ k.hashes.Pop()
+ }
+ for _, hash := range hashes {
+ k.hashes.Add(hash)
+ }
+}
+
+// contains returns whether the given item is in the set.
+func (k *knownCache) contains(hash common.Hash) bool {
+ return k.hashes.Contains(hash)
+}
diff --git a/eth/protocols/bsc/protocol.go b/eth/protocols/bsc/protocol.go
new file mode 100644
index 0000000000..a063531f07
--- /dev/null
+++ b/eth/protocols/bsc/protocol.go
@@ -0,0 +1,66 @@
+package bsc
+
+import (
+ "errors"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// Constants to match up protocol versions and messages
+const (
+ Bsc1 = 1
+)
+
+// ProtocolName is the official short name of the `bsc` protocol used during
+// devp2p capability negotiation.
+const ProtocolName = "bsc"
+
+// ProtocolVersions are the supported versions of the `bsc` protocol (first
+// is primary).
+var ProtocolVersions = []uint{Bsc1}
+
+// protocolLengths are the number of implemented message corresponding to
+// different protocol versions.
+var protocolLengths = map[uint]uint64{Bsc1: 2}
+
+// maxMessageSize is the maximum cap on the size of a protocol message.
+const maxMessageSize = 10 * 1024 * 1024
+
+const (
+ BscCapMsg = 0x00 // bsc capability msg used upon handshake
+ VotesMsg = 0x01
+)
+
+var defaultExtra = []byte{0x00}
+
+var (
+ errNoBscCapMsg = errors.New("no bsc capability message")
+ errMsgTooLarge = errors.New("message too long")
+ errDecode = errors.New("invalid message")
+ errInvalidMsgCode = errors.New("invalid message code")
+ errProtocolVersionMismatch = errors.New("protocol version mismatch")
+)
+
+// Packet represents a p2p message in the `bsc` protocol.
+type Packet interface {
+ Name() string // Name returns a string corresponding to the message type.
+ Kind() byte // Kind returns the message type.
+}
+
+// BscCapPacket is the network packet for bsc capability message.
+type BscCapPacket struct {
+ ProtocolVersion uint
+ Extra rlp.RawValue // for extension
+}
+
+// VotesPacket is the network packet for votes record.
+type VotesPacket struct {
+ Votes []*types.VoteEnvelope
+}
+
+func (*BscCapPacket) Name() string { return "BscCap" }
+func (*BscCapPacket) Kind() byte { return BscCapMsg }
+
+func (*VotesPacket) Name() string { return "Votes" }
+func (*VotesPacket) Kind() byte { return VotesMsg }
diff --git a/eth/protocols/bsc/protocol_test.go b/eth/protocols/bsc/protocol_test.go
new file mode 100644
index 0000000000..8597021411
--- /dev/null
+++ b/eth/protocols/bsc/protocol_test.go
@@ -0,0 +1,132 @@
+package bsc
+
+import (
+ "bytes"
+ "encoding/hex"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// TestBsc1Messages tests the encoding of defined Bsc1 messages
+func TestBsc1Messages(t *testing.T) {
+ var (
+ BLSPublicKey = "b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bc"
+ voteDataSet = []types.VoteData{
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 1,
+ TargetHash: common.HexToHash("0xd0bc67b50915467ada963c35ee00950f664788e47da8139d8c178653171034f1"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 2,
+ TargetHash: common.HexToHash("0xc2d18d5a59d65da573f70c4d30448482418894e018b0d189db24ea4fd02d7aa1"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 4,
+ TargetHash: common.HexToHash("0xbd1bdaf8a8f5c00c464df2856a9e2ef23b8dcc906e6490d3cd295ebb5eb124c3"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 8,
+ TargetHash: common.HexToHash("0x3073782ecabb5ef0673e95962273482347a2c7b30a0a7124c664443d0a43f1e1"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 16,
+ TargetHash: common.HexToHash("0xc119833266327fd7e0cd929c6a847ae7d1689df5066dfdde2e52f51c0ecbcc3f"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 32,
+ TargetHash: common.HexToHash("0x3b5650bcb98381e463871a15a3f601cdc26843d76f4d3461333d7feae38a1786"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 64,
+ TargetHash: common.HexToHash("0x5e38b4d98904178d60d58f5bc1687b0c7df114a51f2007d3ee3e6e732539f130"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 128,
+ TargetHash: common.HexToHash("0xa4a64a7d511d3ff6982b5a79e9a485508477b98996c570a220f9daea0c7682f8"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 256,
+ TargetHash: common.HexToHash("0xd313672c2653fc13e75a9dafdcee93f444caf2cffb04585d3e306fd15418b7e2"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 512,
+ TargetHash: common.HexToHash("0x3c5fe2e5439ca7a7f1a3de7d5c0914c37261451c87654397dd45f207109839ae"),
+ },
+ {
+ SourceNumber: 0,
+ SourceHash: common.HexToHash("0x6d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34"),
+ TargetNumber: 1024,
+ TargetHash: common.HexToHash("0x088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043b"),
+ },
+ }
+ signatures = []string{
+ "91f8a39f99a0b3632d248e635ab0e7b5ff68071fa4def5c2df9f249db7d393c0ba89eb28a65f2a6ba836baddb961b9c312c70a87d130edf944b340649218335c91078cce808da75ff69f673bab3ecdf068c33b1ab147c54298056b19e9cc625d",
+ "a56cd257f9a4b4830c9bfadaa751c7b1d4e9c6899127c145987a55a7cfa0d1b7d114cb2523ea4e2efee0326cfc5a1cd912eaf7f0c4c0be3193677284533f1709fbd75471a9fb22aea358cdbf2e900628d7c504ce7245e8af6fdd1039dfa3c0bd",
+ "893f8aff7fc523a7aff006aaba71fbde5f1eee1f4683d405892ffb9ab9282a5dae01054210ff6873ee76f86b9afdef2e128932b26696e3f7e1de7fe7d3fdd1c41273912ff5d1002cba176dbf84e1fe2edb60b114129b89e1329a03f7d9843d04",
+ "b3585bf55f1e0d8bc0f544a386e6fc4ec37de52330f69b450f579050acda6279a8a38172ed2f01dfdb57cf7dd2a314970aa8a3168234cbd29adfc6a0efd080f57d7e195dafbf5b6db087e8b943aa634f797f8f6d4e5bf04681d7ce2218e59465",
+ "9366e823b456049cd10ed1aa8f02a58ce2fa4caea7e8c776d6aec9c42f4263b40b0f2d76cc55a598b378381f32ef33520d47e28707027c25e38eb971cddb379e0ded5e814ce70108d65855084a11484fd08447520b7ce79ac1e680020b243747",
+ "aafd383c9537d750358ea077d45476cf6c1541e717c690ebe5dc5442c2af732fba17b45c60b2c49de94f5121f318b6ae021c56ae06588c6552f1d5b87a166cb8050f287b528b20556033603f6a6649ccec4792c86ae5f6353cf6b7527ac40127",
+ "90d9dc467a64fe7852b2e0117806409a8f12a036849d69396282088f8d86adb3adcd46b1fde51b4630a6b64c2f8652f30a46609c49b33f50c9f4641e30900ee420f9b81b2ad59a2376dcf4e065ecf832fbf738ad5b73becd2f7add27e6c14d5f",
+ "8f7d6bc28626dc143208aaa7b97146510f01b1a108dead65f8fddf0ec07835bca91081f9e759656d52dd7d4adaac14220c8c62aa1dd09151fe8000ce4347b100ac496593058ae11b40c74b3049d38076d07301c9dc9586baf93d9c81b4e5d424",
+ "b6c17077217baa5930fb04e14b6ba7203b3c854e8f1363b48ad753d96db1b4ffed36d60d8b67e86f7f76504f0abefff80ed1e4f11ff192dbfc26a0f059f7b9f66f9e883fef208cc3f58c7ce49d8e854cf8a0e48c59c7407ebfe946cfd62bf3be",
+ "979b1d101e51731749c72fb160dd1245d69ebd6ca81c0519464d3bca9ec3db493cf4b45ebbb7f60fbd12f0705bd788000558bdedc335cedac2100169965b2794fae8a386b2e9ece86ea6952fadeb8501d9aad00e091713cc06d30c5885c3ecf0",
+ "8d035b04d8ef6c13117acc1ed9d0586a141f123494f21eeaaead5dd9f623933541b293eef403d2f3e8ede84f9dfe3dc10cbd3fa6bdf3e977dcf2d18a4dca84f8bd9b24fca8e7de4180b9aa6208ad6e756b1c81e98afc8e6994824b5c076857f8",
+ }
+
+ votesSet []*types.VoteEnvelope
+ )
+
+ // Init the vote data, taken from a local node
+ pubKeyBytes, _ := hex.DecodeString(BLSPublicKey)
+ {
+ for i, voteData := range voteDataSet {
+ vote := new(types.VoteEnvelope)
+ voteAddress := new(types.BLSPublicKey)
+ signature := new(types.BLSSignature)
+ sigBytes, _ := hex.DecodeString(signatures[i])
+ copy(voteAddress[:], pubKeyBytes)
+ copy(signature[:], sigBytes)
+ vote.VoteAddress = *voteAddress
+ vote.Signature = *signature
+ vote.Data = &voteData
+ votesSet = append(votesSet, vote)
+ }
+ }
+
+ for i, tc := range []struct {
+ message interface{}
+ want []byte
+ }{
+ {
+ VotesPacket{votesSet},
+ common.FromHex("f90982f9097ff8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb86091f8a39f99a0b3632d248e635ab0e7b5ff68071fa4def5c2df9f249db7d393c0ba89eb28a65f2a6ba836baddb961b9c312c70a87d130edf944b340649218335c91078cce808da75ff69f673bab3ecdf068c33b1ab147c54298056b19e9cc625df84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb860a56cd257f9a4b4830c9bfadaa751c7b1d4e9c6899127c145987a55a7cfa0d1b7d114cb2523ea4e2efee0326cfc5a1cd912eaf7f0c4c0be3193677284533f1709fbd75471a9fb22aea358cdbf2e900628d7c504ce7245e8af6fdd1039dfa3c0bdf84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb860893f8aff7fc523a7aff006aaba71fbde5f1eee1f4683d405892ffb9ab9282a5dae01054210ff6873ee76f86b9afdef2e128932b26696e3f7e1de7fe7d3fdd1c41273912ff5d1002cba176dbf84e1fe2edb60b114129b89e1329a03f7d9843d04f84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb860b3585bf55f1e0d8bc0f544a386e6fc4ec37de52330f69b450f579050acda6279a8a38172ed2f01dfdb57cf7dd2a314970aa8a3168234cbd29adfc6a0efd080f57d7e195dafbf5b6db087e8b943aa634f797f8f6d4e5bf04681d7ce2218e59465f84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb8609366e823b456049cd10ed1aa8f02a58ce2fa4caea7e8c776d6aec9c42f4263b40b0f2d76cc55a598b378381f32ef33520d47e28707027c25e38eb971cddb379e0ded5e814ce70108d65855084a11484fd08447520b7ce79ac1e680020b243747f84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb860aafd383c9537d750358ea077d45476cf6c1541e717c690ebe5dc5442c2af732fba17b45c60b2c49de94f5121f318b6ae021c56ae06588c6552f1d5b87a166cb8050f287b528b20556033603f6a6649ccec4792c86ae5f6353cf6b7527ac40127f84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb86090d9dc467a64fe7852b2e0117806409a8f12a036849d69396282088f8d86adb3adcd46b1fde51b4630a6b64c2f8652f30a46609c49b33f50c9f4641e30900ee420f9b81b2ad59a2376dcf4e065ecf832fbf738ad5b73becd2f7add27e6c14d5ff84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb8608f7d6bc28626dc143208aaa7b97146510f01b1a108dead65f8fddf0ec07835bca91081f9e759656d52dd7d4adaac14220c8c62aa1dd09151fe8000ce4347b100ac496593058ae11b40c74b3049d38076d07301c9dc9586baf93d9c81b4e5d424f84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb860b6c17077217baa5930fb04e14b6ba7203b3c854e8f1363b48ad753d96db1b4ffed36d60d8b67e86f7f76504f0abefff80ed1e4f11ff192dbfc26a0f059f7b9f66f9e883fef208cc3f58c7ce49d8e854cf8a0e48c59c7407ebfe946cfd62bf3bef84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb860979b1d101e51731749c72fb160dd1245d69ebd6ca81c0519464d3bca9ec3db493cf4b45ebbb7f60fbd12f0705bd788000558bdedc335cedac2100169965b2794fae8a386b2e9ece86ea6952fadeb8501d9aad00e091713cc06d30c5885c3ecf0f84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043bf8dbb0b32d4d46a7127dcc865f0d30f2ee3dcd5983b686f4e3a9202afc8b608652001c9938906ae1ff1417486096e32511f1bcb8608d035b04d8ef6c13117acc1ed9d0586a141f123494f21eeaaead5dd9f623933541b293eef403d2f3e8ede84f9dfe3dc10cbd3fa6bdf3e977dcf2d18a4dca84f8bd9b24fca8e7de4180b9aa6208ad6e756b1c81e98afc8e6994824b5c076857f8f84680a06d3c66c5357ec91d5c43af47e234a939b22557cbb552dc45bebbceeed90fbe34820400a0088eeeb07acff0db3ae2585195e9fd23bdf54b55077cab87d1632b08dd2c043b"),
+ },
+ } {
+ if have, _ := rlp.EncodeToBytes(tc.message); !bytes.Equal(have, tc.want) {
+ t.Errorf("test %d, type %T, have\n\t%x\nwant\n\t%x", i, tc.message, have, tc.want)
+ }
+ }
+}
diff --git a/eth/protocols/diff/handler.go b/eth/protocols/diff/handler.go
index 18ec4e2541..4bbf24f6fe 100644
--- a/eth/protocols/diff/handler.go
+++ b/eth/protocols/diff/handler.go
@@ -101,7 +101,7 @@ func handleMessage(backend Backend, peer *Peer) error {
}
defer msg.Discard()
start := time.Now()
- // Track the emount of time it takes to serve the request and run the handler
+ // Track the amount of time it takes to serve the request and run the handler
if metrics.Enabled {
h := fmt.Sprintf("%s/%s/%d/%#02x", p2p.HandleHistName, ProtocolName, peer.Version(), msg.Code)
defer func(start time.Time) {
diff --git a/eth/protocols/eth/handler.go b/eth/protocols/eth/handler.go
index 81d45d8b8f..9eb949f139 100644
--- a/eth/protocols/eth/handler.go
+++ b/eth/protocols/eth/handler.go
@@ -195,9 +195,6 @@ func handleMessage(backend Backend, peer *Peer) error {
defer msg.Discard()
var handlers = eth66
- //if peer.Version() >= ETH67 { // Left in as a sample when new protocol is added
- // handlers = eth67
- //}
// Track the amount of time it takes to serve the request and run the handler
if metrics.Enabled {
diff --git a/eth/protocols/eth/handler_test.go b/eth/protocols/eth/handler_test.go
index 55e612b801..b12be49bbf 100644
--- a/eth/protocols/eth/handler_test.go
+++ b/eth/protocols/eth/handler_test.go
@@ -94,8 +94,8 @@ func (b *testBackend) Chain() *core.BlockChain { return b.chain }
func (b *testBackend) TxPool() TxPool { return b.txpool }
func (b *testBackend) RunPeer(peer *Peer, handler Handler) error {
- // Normally the backend would do peer mainentance and handshakes. All that
- // is omitted and we will just give control back to the handler.
+ // Normally the backend would do peer maintenance and handshakes. All that
+ // is omitted, and we will just give control back to the handler.
return handler(peer)
}
func (b *testBackend) PeerInfo(enode.ID) interface{} { panic("not implemented") }
@@ -247,7 +247,7 @@ func testGetBlockHeaders(t *testing.T, protocol uint) {
backend.chain.GetBlockByNumber(1).Hash(),
},
},
- // Check that non existing headers aren't returned
+ // Check that non-existing headers aren't returned
{
&GetBlockHeadersPacket{Origin: HashOrNumber{Hash: unknown}, Amount: 1},
[]common.Hash{},
diff --git a/eth/protocols/eth/peer.go b/eth/protocols/eth/peer.go
index 8bf973f9c3..b39aa56eee 100644
--- a/eth/protocols/eth/peer.go
+++ b/eth/protocols/eth/peer.go
@@ -122,7 +122,6 @@ func NewPeer(version uint, p *p2p.Peer, rw p2p.MsgReadWriter, txpool TxPool) *Pe
go peer.broadcastTransactions()
go peer.announceTransactions()
go peer.dispatcher()
-
return peer
}
@@ -149,7 +148,7 @@ func (p *Peer) ID() string {
return p.id
}
-// Version retrieves the peer's negoatiated `eth` protocol version.
+// Version retrieves the peer's negotiated `eth` protocol version.
func (p *Peer) Version() uint {
return p.version
}
@@ -324,6 +323,11 @@ func (p *Peer) AsyncSendNewBlock(block *types.Block, td *big.Int) {
}
}
+// SendBlockHeaders sends a batch of block headers to the remote peer.
+func (p *Peer) SendBlockHeaders(headers []*types.Header) error {
+ return p2p.Send(p.rw, BlockHeadersMsg, BlockHeadersPacket(headers))
+}
+
// ReplyBlockHeaders is the eth/66 version of SendBlockHeaders.
func (p *Peer) ReplyBlockHeadersRLP(id uint64, headers []rlp.RawValue) error {
return p2p.Send(p.rw, BlockHeadersMsg, &BlockHeadersRLPPacket66{
diff --git a/eth/protocols/eth/protocol.go b/eth/protocols/eth/protocol.go
index 66ff9220cc..3e171d6f3e 100644
--- a/eth/protocols/eth/protocol.go
+++ b/eth/protocols/eth/protocol.go
@@ -202,7 +202,7 @@ func (hn *HashOrNumber) DecodeRLP(s *rlp.Stream) error {
// BlockHeadersPacket represents a block header response.
type BlockHeadersPacket []*types.Header
-// BlockHeadersPacket represents a block header response over eth/66.
+// BlockHeadersPacket66 represents a block header response over eth/66.
type BlockHeadersPacket66 struct {
RequestId uint64
BlockHeadersPacket
@@ -240,7 +240,7 @@ func (request *NewBlockPacket) sanityCheck() error {
// GetBlockBodiesPacket represents a block body query.
type GetBlockBodiesPacket []common.Hash
-// GetBlockBodiesPacket represents a block body query over eth/66.
+// GetBlockBodiesPacket66 represents a block body query over eth/66.
type GetBlockBodiesPacket66 struct {
RequestId uint64
GetBlockBodiesPacket
@@ -249,7 +249,7 @@ type GetBlockBodiesPacket66 struct {
// BlockBodiesPacket is the network packet for block content distribution.
type BlockBodiesPacket []*BlockBody
-// BlockBodiesPacket is the network packet for block content distribution over eth/66.
+// BlockBodiesPacket66 is the network packet for block content distribution over eth/66.
type BlockBodiesPacket66 struct {
RequestId uint64
BlockBodiesPacket
@@ -288,7 +288,7 @@ func (p *BlockBodiesPacket) Unpack() ([][]*types.Transaction, [][]*types.Header)
// GetNodeDataPacket represents a trie node data query.
type GetNodeDataPacket []common.Hash
-// GetNodeDataPacket represents a trie node data query over eth/66.
+// GetNodeDataPacket66 represents a trie node data query over eth/66.
type GetNodeDataPacket66 struct {
RequestId uint64
GetNodeDataPacket
@@ -297,7 +297,7 @@ type GetNodeDataPacket66 struct {
// NodeDataPacket is the network packet for trie node data distribution.
type NodeDataPacket [][]byte
-// NodeDataPacket is the network packet for trie node data distribution over eth/66.
+// NodeDataPacket66 is the network packet for trie node data distribution over eth/66.
type NodeDataPacket66 struct {
RequestId uint64
NodeDataPacket
@@ -306,7 +306,7 @@ type NodeDataPacket66 struct {
// GetReceiptsPacket represents a block receipts query.
type GetReceiptsPacket []common.Hash
-// GetReceiptsPacket represents a block receipts query over eth/66.
+// GetReceiptsPacket66 represents a block receipts query over eth/66.
type GetReceiptsPacket66 struct {
RequestId uint64
GetReceiptsPacket
@@ -315,7 +315,7 @@ type GetReceiptsPacket66 struct {
// ReceiptsPacket is the network packet for block receipts distribution.
type ReceiptsPacket [][]*types.Receipt
-// ReceiptsPacket is the network packet for block receipts distribution over eth/66.
+// ReceiptsPacket66 is the network packet for block receipts distribution over eth/66.
type ReceiptsPacket66 struct {
RequestId uint64
ReceiptsPacket
@@ -324,7 +324,7 @@ type ReceiptsPacket66 struct {
// ReceiptsRLPPacket is used for receipts, when we already have it encoded
type ReceiptsRLPPacket []rlp.RawValue
-// ReceiptsPacket66 is the eth-66 version of ReceiptsRLPPacket
+// ReceiptsRLPPacket66 is the eth-66 version of ReceiptsRLPPacket
type ReceiptsRLPPacket66 struct {
RequestId uint64
ReceiptsRLPPacket
@@ -344,13 +344,13 @@ type GetPooledTransactionsPacket66 struct {
// PooledTransactionsPacket is the network packet for transaction distribution.
type PooledTransactionsPacket []*types.Transaction
-// PooledTransactionsPacket is the network packet for transaction distribution over eth/66.
+// PooledTransactionsPacket66 is the network packet for transaction distribution over eth/66.
type PooledTransactionsPacket66 struct {
RequestId uint64
PooledTransactionsPacket
}
-// PooledTransactionsPacket is the network packet for transaction distribution, used
+// PooledTransactionsRLPPacket is the network packet for transaction distribution, used
// in the cases we already have them in rlp-encoded form
type PooledTransactionsRLPPacket []rlp.RawValue
diff --git a/eth/sync.go b/eth/sync.go
index 22e2b293fe..a32d305c77 100644
--- a/eth/sync.go
+++ b/eth/sync.go
@@ -60,6 +60,15 @@ func (h *handler) syncTransactions(p *eth.Peer) {
p.AsyncSendPooledTransactionHashes(hashes)
}
+// syncVotes starts sending all currently pending votes to the given peer.
+func (h *handler) syncVotes(p *bscPeer) {
+ votes := h.votepool.GetVotes()
+ if len(votes) == 0 {
+ return
+ }
+ p.AsyncSendVotes(votes)
+}
+
// chainSyncer coordinates blockchain sync components.
type chainSyncer struct {
handler *handler
diff --git a/eth/tracers/js/tracer_test.go b/eth/tracers/js/tracer_test.go
index 4389004dcc..b58b5ae94a 100644
--- a/eth/tracers/js/tracer_test.go
+++ b/eth/tracers/js/tracer_test.go
@@ -103,15 +103,15 @@ func TestTracer(t *testing.T) {
{ // tests that we don't panic on bad arguments to memory access
code: "{depths: [], step: function(log) { this.depths.push(log.memory.slice(-1,-2)); }, fault: function() {}, result: function() { return this.depths; }}",
want: ``,
- fail: "Tracer accessed out of bound memory: offset -1, end -2 at step (:1:53(15)) in server-side tracer function 'step'",
+ fail: "Tracer accessed out of bound memory: offset -1, end -2 at step (:1:53(13)) in server-side tracer function 'step'",
}, { // tests that we don't panic on bad arguments to stack peeks
code: "{depths: [], step: function(log) { this.depths.push(log.stack.peek(-1)); }, fault: function() {}, result: function() { return this.depths; }}",
want: ``,
- fail: "Tracer accessed out of bound stack: size 0, index -1 at step (:1:53(13)) in server-side tracer function 'step'",
+ fail: "Tracer accessed out of bound stack: size 0, index -1 at step (:1:53(11)) in server-side tracer function 'step'",
}, { // tests that we don't panic on bad arguments to memory getUint
code: "{ depths: [], step: function(log, db) { this.depths.push(log.memory.getUint(-64));}, fault: function() {}, result: function() { return this.depths; }}",
want: ``,
- fail: "Tracer accessed out of bound memory: available 0, offset -64, size 32 at step (:1:58(13)) in server-side tracer function 'step'",
+ fail: "Tracer accessed out of bound memory: available 0, offset -64, size 32 at step (:1:58(11)) in server-side tracer function 'step'",
}, { // tests some general counting
code: "{count: 0, step: function() { this.count += 1; }, fault: function() {}, result: function() { return this.count; }}",
want: `3`,
diff --git a/ethclient/ethclient.go b/ethclient/ethclient.go
index db388a3d9d..7e6333739f 100644
--- a/ethclient/ethclient.go
+++ b/ethclient/ethclient.go
@@ -370,6 +370,17 @@ func (ec *Client) SubscribeNewHead(ctx context.Context, ch chan<- *types.Header)
return ec.c.EthSubscribe(ctx, ch, "newHeads")
}
+// SubscribeNewFinalizedHeader subscribes to notifications about the current blockchain finalized header
+// on the given channel.
+func (ec *Client) SubscribeNewFinalizedHeader(ctx context.Context, ch chan<- *types.Header) (ethereum.Subscription, error) {
+ return ec.c.EthSubscribe(ctx, ch, "newFinalizedHeaders")
+}
+
+// SubscribeNewVotes subscribes to notifications about the new votes into vote pool
+func (ec *Client) SubscribeNewVotes(ctx context.Context, ch chan<- *types.VoteEnvelope) (ethereum.Subscription, error) {
+ return ec.c.EthSubscribe(ctx, ch, "newVotes")
+}
+
// State Access
// NetworkID returns the network ID (also known as the chain ID) for this chain.
@@ -579,6 +590,14 @@ func toBlockNumArg(number *big.Int) string {
if number.Cmp(pending) == 0 {
return "pending"
}
+ finalized := big.NewInt(int64(rpc.FinalizedBlockNumber))
+ if number.Cmp(finalized) == 0 {
+ return "finalized"
+ }
+ safe := big.NewInt(int64(rpc.SafeBlockNumber))
+ if number.Cmp(safe) == 0 {
+ return "safe"
+ }
return hexutil.EncodeBig(number)
}
diff --git a/ethclient/gethclient/gethclient.go b/ethclient/gethclient/gethclient.go
index 7af2bf45d7..3795b182e1 100644
--- a/ethclient/gethclient/gethclient.go
+++ b/ethclient/gethclient/gethclient.go
@@ -188,6 +188,14 @@ func toBlockNumArg(number *big.Int) string {
if number.Cmp(pending) == 0 {
return "pending"
}
+ finalized := big.NewInt(int64(rpc.FinalizedBlockNumber))
+ if number.Cmp(finalized) == 0 {
+ return "finalized"
+ }
+ safe := big.NewInt(int64(rpc.SafeBlockNumber))
+ if number.Cmp(safe) == 0 {
+ return "safe"
+ }
return hexutil.EncodeBig(number)
}
diff --git a/go.mod b/go.mod
index 1f6561f4a7..b9b3cc8b18 100644
--- a/go.mod
+++ b/go.mod
@@ -4,30 +4,31 @@ go 1.19
require (
github.com/Azure/azure-storage-blob-go v0.7.0
- github.com/VictoriaMetrics/fastcache v1.6.0
+ github.com/VictoriaMetrics/fastcache v1.10.0
github.com/aws/aws-sdk-go-v2 v1.2.0
github.com/aws/aws-sdk-go-v2/config v1.1.1
github.com/aws/aws-sdk-go-v2/credentials v1.1.1
github.com/aws/aws-sdk-go-v2/service/route53 v1.1.1
- github.com/bnb-chain/ics23 v0.1.0
- github.com/cespare/cp v0.1.0
+ github.com/btcsuite/btcd/btcec/v2 v2.3.2
+ github.com/cespare/cp v1.1.1
github.com/cloudflare/cloudflare-go v0.14.0
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f
github.com/davecgh/go-spew v1.1.1
github.com/deckarep/golang-set v1.8.0
github.com/deepmap/oapi-codegen v1.8.2 // indirect
github.com/docker/docker v1.6.1
- github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf
- github.com/edsrzf/mmap-go v1.0.0
- github.com/fatih/color v1.7.0
+ github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7
+ github.com/edsrzf/mmap-go v1.1.0
+ github.com/etcd-io/bbolt v1.3.3 // indirect
+ github.com/fatih/color v1.9.0
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5
- github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff
- github.com/go-stack/stack v1.8.0
+ github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08
+ github.com/go-stack/stack v1.8.1
github.com/golang/protobuf v1.5.2
github.com/golang/snappy v0.0.4
github.com/google/gofuzz v1.2.0
- github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40
- github.com/google/uuid v1.1.5
+ github.com/google/pprof v0.0.0-20221203041831-ce31453925ec
+ github.com/google/uuid v1.3.0
github.com/gorilla/websocket v1.5.0
github.com/graph-gophers/graphql-go v1.3.0
github.com/hashicorp/go-bexpr v0.1.10
@@ -39,89 +40,234 @@ require (
github.com/influxdata/influxdb-client-go/v2 v2.4.0
github.com/jackpal/go-nat-pmp v1.0.2
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
+ github.com/jmhodges/levigo v1.0.0 // indirect
github.com/julienschmidt/httprouter v1.3.0
github.com/karalabe/usb v0.0.2
- github.com/mattn/go-colorable v0.1.8
- github.com/mattn/go-isatty v0.0.12
+ github.com/logrusorgru/aurora v2.0.3+incompatible
+ github.com/mattn/go-colorable v0.1.13
+ github.com/mattn/go-isatty v0.0.16
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
github.com/olekukonko/tablewriter v0.0.5
github.com/panjf2000/ants/v2 v2.4.5
- github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7
- github.com/pkg/errors v0.9.1 // indirect
- github.com/prometheus/tsdb v0.7.1
+ github.com/peterh/liner v1.2.0
+ github.com/pkg/errors v0.9.1
+ github.com/prometheus/tsdb v0.10.0
+ github.com/prysmaticlabs/prysm/v3 v3.2.2
github.com/rjeczalik/notify v0.9.1
github.com/rs/cors v1.7.0
github.com/shirou/gopsutil v3.21.11+incompatible
- github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4
+ github.com/status-im/keycard-go v0.2.0
github.com/stretchr/testify v1.8.1
- github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7
+ github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
github.com/tendermint/go-amino v0.14.1
github.com/tendermint/iavl v0.12.0
- github.com/tendermint/tendermint v0.31.12
- github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
+ github.com/tendermint/tendermint v0.31.15
+ github.com/tidwall/wal v1.1.7
+ github.com/tyler-smith/go-bip39 v1.1.0
+ github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3
+ github.com/willf/bitset v1.1.3
golang.org/x/crypto v0.5.0
golang.org/x/sync v0.1.0
- golang.org/x/sys v0.4.0
- golang.org/x/text v0.6.0
- golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
- golang.org/x/tools v0.1.12
+ golang.org/x/sys v0.5.0
+ golang.org/x/text v0.7.0
+ golang.org/x/time v0.0.0-20220922220347-f3bd1da661af
+ golang.org/x/tools v0.6.0
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
gopkg.in/urfave/cli.v1 v1.20.0
)
require (
- github.com/btcsuite/btcd/btcec/v2 v2.3.2
+ github.com/bnb-chain/ics23 v0.1.0
github.com/fatih/structs v1.1.0
)
require github.com/yusufpapurcu/wmi v1.2.2 // indirect
require (
+ contrib.go.opencensus.io/exporter/jaeger v0.2.1 // indirect
github.com/Azure/azure-pipeline-go v0.2.2 // indirect
github.com/Azure/go-autorest/autorest/adal v0.8.0 // indirect
+ github.com/BurntSushi/toml v1.2.1 // indirect
+ github.com/allegro/bigcache v1.2.1 // indirect
+ github.com/aristanetworks/goarista v0.0.0-20200805130819-fd197cf57d96 // indirect
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.0.2 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.0.2 // indirect
github.com/aws/aws-sdk-go-v2/service/sso v1.1.1 // indirect
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 // indirect
github.com/aws/smithy-go v1.1.0 // indirect
+ github.com/benbjohnson/clock v1.3.0 // indirect
github.com/beorn7/perks v1.0.1 // indirect
- github.com/cespare/xxhash/v2 v2.1.2 // indirect
- github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
- github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 // indirect
- github.com/etcd-io/bbolt v1.3.3 // indirect
- github.com/fortytw2/leaktest v1.3.0 // indirect
- github.com/go-kit/kit v0.9.0 // indirect
+ github.com/cespare/xxhash v1.1.0 // indirect
+ github.com/cespare/xxhash/v2 v2.2.0 // indirect
+ github.com/chzyer/readline v1.5.0 // indirect
+ github.com/containerd/cgroups v1.0.4 // indirect
+ github.com/coreos/go-systemd/v22 v22.5.0 // indirect
+ github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect
+ github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c // indirect
+ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 // indirect
+ github.com/dgraph-io/ristretto v0.0.4-0.20210318174700-74754f61e018 // indirect
+ github.com/dlclark/regexp2 v1.7.0 // indirect
+ github.com/docker/go-units v0.5.0 // indirect
+ github.com/dustin/go-humanize v1.0.0 // indirect
+ github.com/elastic/gosigar v0.14.2 // indirect
+ github.com/ferranbt/fastssz v0.0.0-20210905181407-59cf6761a7d5 // indirect
+ github.com/flynn/noise v1.0.0 // indirect
+ github.com/francoispqt/gojay v1.2.13 // indirect
+ github.com/fsnotify/fsnotify v1.6.0 // indirect
+ github.com/go-kit/kit v0.10.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
+ github.com/go-logr/logr v1.2.3 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect
+ github.com/go-playground/locales v0.14.0 // indirect
+ github.com/go-playground/universal-translator v0.18.0 // indirect
+ github.com/go-playground/validator/v10 v10.11.1 // indirect
github.com/go-sourcemap/sourcemap v2.1.3+incompatible // indirect
+ github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
+ github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
+ github.com/golang-jwt/jwt/v4 v4.3.0 // indirect
+ github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e // indirect
+ github.com/golang/mock v1.6.0 // indirect
+ github.com/google/go-cmp v0.5.9 // indirect
+ github.com/google/gopacket v1.1.19 // indirect
+ github.com/gorilla/mux v1.8.0 // indirect
+ github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 // indirect
+ github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 // indirect
+ github.com/grpc-ecosystem/grpc-gateway/v2 v2.0.1 // indirect
+ github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e // indirect
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
- github.com/jmhodges/levigo v1.0.0 // indirect
- github.com/kylelemons/godebug v1.1.0 // indirect
+ github.com/ipfs/go-cid v0.3.2 // indirect
+ github.com/ipfs/go-log v1.0.5 // indirect
+ github.com/ipfs/go-log/v2 v2.5.1 // indirect
+ github.com/jbenet/go-temp-err-catcher v0.1.0 // indirect
+ github.com/json-iterator/go v1.1.12 // indirect
+ github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a // indirect
+ github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
+ github.com/klauspost/compress v1.15.15 // indirect
+ github.com/klauspost/cpuid/v2 v2.2.1 // indirect
+ github.com/koron/go-ssdp v0.0.3 // indirect
+ github.com/kr/pretty v0.3.1 // indirect
+ github.com/kr/text v0.2.0 // indirect
+ github.com/leodido/go-urn v1.2.1 // indirect
+ github.com/libp2p/go-buffer-pool v0.1.0 // indirect
+ github.com/libp2p/go-cidranger v1.1.0 // indirect
+ github.com/libp2p/go-flow-metrics v0.1.0 // indirect
+ github.com/libp2p/go-libp2p v0.24.0 // indirect
+ github.com/libp2p/go-libp2p-asn-util v0.2.0 // indirect
+ github.com/libp2p/go-libp2p-pubsub v0.8.0 // indirect
+ github.com/libp2p/go-mplex v0.7.0 // indirect
+ github.com/libp2p/go-msgio v0.2.0 // indirect
+ github.com/libp2p/go-nat v0.1.0 // indirect
+ github.com/libp2p/go-netroute v0.2.1 // indirect
+ github.com/libp2p/go-openssl v0.1.0 // indirect
+ github.com/libp2p/go-reuseport v0.2.0 // indirect
+ github.com/libp2p/go-yamux/v4 v4.0.0 // indirect
+ github.com/lucas-clemente/quic-go v0.31.0 // indirect
+ github.com/lunixbochs/vtclean v1.0.0 // indirect
+ github.com/manifoldco/promptui v0.7.0 // indirect
+ github.com/marten-seemann/qtls-go1-18 v0.1.3 // indirect
+ github.com/marten-seemann/qtls-go1-19 v0.1.1 // indirect
+ github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd // indirect
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d // indirect
- github.com/mattn/go-runewidth v0.0.9 // indirect
- github.com/matttproud/golang_protobuf_extensions v1.0.1 // indirect
+ github.com/mattn/go-pointer v0.0.1 // indirect
+ github.com/mattn/go-runewidth v0.0.13 // indirect
+ github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect
+ github.com/miekg/dns v1.1.50 // indirect
+ github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b // indirect
+ github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc // indirect
+ github.com/minio/highwayhash v1.0.1 // indirect
+ github.com/minio/sha256-simd v1.0.0 // indirect
+ github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db // indirect
github.com/mitchellh/mapstructure v1.4.1 // indirect
github.com/mitchellh/pointerstructure v1.2.0 // indirect
+ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
+ github.com/modern-go/reflect2 v1.0.2 // indirect
+ github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
+ github.com/mr-tron/base58 v1.2.0 // indirect
+ github.com/multiformats/go-base32 v0.1.0 // indirect
+ github.com/multiformats/go-base36 v0.2.0 // indirect
+ github.com/multiformats/go-multiaddr v0.8.0 // indirect
+ github.com/multiformats/go-multiaddr-dns v0.3.1 // indirect
+ github.com/multiformats/go-multiaddr-fmt v0.1.0 // indirect
+ github.com/multiformats/go-multibase v0.1.1 // indirect
+ github.com/multiformats/go-multicodec v0.7.0 // indirect
+ github.com/multiformats/go-multihash v0.2.1 // indirect
+ github.com/multiformats/go-multistream v0.3.3 // indirect
+ github.com/multiformats/go-varint v0.0.7 // indirect
github.com/naoina/go-stringutil v0.1.0 // indirect
- github.com/opentracing/opentracing-go v1.1.0 // indirect
+ github.com/onsi/ginkgo/v2 v2.5.1 // indirect
+ github.com/opencontainers/runtime-spec v1.0.2 // indirect
+ github.com/opentracing/opentracing-go v1.2.0 // indirect
+ github.com/patrickmn/go-cache v2.1.0+incompatible // indirect
+ github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/prometheus/client_golang v1.14.0 // indirect
github.com/prometheus/client_model v0.3.0 // indirect
- github.com/prometheus/common v0.37.0 // indirect
- github.com/prometheus/procfs v0.8.0 // indirect
+ github.com/prometheus/common v0.39.0 // indirect
+ github.com/prometheus/procfs v0.9.0 // indirect
+ github.com/prometheus/prom2json v1.3.0 // indirect
+ github.com/prysmaticlabs/fastssz v0.0.0-20220628121656-93dfe28febab // indirect
+ github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 // indirect
+ github.com/prysmaticlabs/gohashtree v0.0.2-alpha // indirect
+ github.com/prysmaticlabs/prombbolt v0.0.0-20210126082820-9b7adba6db7c // indirect
+ github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc // indirect
+ github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 // indirect
- github.com/tklauser/go-sysconf v0.3.5 // indirect
- github.com/tklauser/numcpus v0.2.2 // indirect
+ github.com/rivo/uniseg v0.3.4 // indirect
+ github.com/rogpeppe/go-internal v1.9.0 // indirect
+ github.com/russross/blackfriday/v2 v2.1.0 // indirect
+ github.com/schollz/progressbar/v3 v3.3.4 // indirect
+ github.com/sirupsen/logrus v1.9.0 // indirect
+ github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 // indirect
+ github.com/spaolacci/murmur3 v1.1.0 // indirect
+ github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344 // indirect
+ github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e // indirect
+ github.com/tidwall/gjson v1.10.2 // indirect
+ github.com/tidwall/match v1.1.1 // indirect
+ github.com/tidwall/pretty v1.2.0 // indirect
+ github.com/tidwall/tinylru v1.1.0 // indirect
+ github.com/tklauser/go-sysconf v0.3.10 // indirect
+ github.com/tklauser/numcpus v0.5.0 // indirect
+ github.com/trailofbits/go-mutexasserts v0.0.0-20200708152505-19999e7d3cef // indirect
+ github.com/uber/jaeger-client-go v2.25.0+incompatible // indirect
+ github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa // indirect
+ github.com/wealdtech/go-bytesutil v1.1.1 // indirect
+ github.com/wealdtech/go-eth2-types/v2 v2.5.2 // indirect
+ github.com/wealdtech/go-eth2-util v1.6.3 // indirect
+ github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee // indirect
+ github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
go.etcd.io/bbolt v1.3.7 // indirect
- golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
- golang.org/x/net v0.5.0 // indirect
- golang.org/x/term v0.4.0 // indirect
- google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 // indirect
- google.golang.org/grpc v1.31.0 // indirect
+ go.opencensus.io v0.24.0 // indirect
+ go.uber.org/atomic v1.10.0 // indirect
+ go.uber.org/dig v1.15.0 // indirect
+ go.uber.org/fx v1.18.2 // indirect
+ go.uber.org/multierr v1.8.0 // indirect
+ go.uber.org/zap v1.24.0 // indirect
+ golang.org/x/exp v0.0.0-20230206171751-46f607a40771 // indirect
+ golang.org/x/mod v0.8.0 // indirect
+ golang.org/x/net v0.7.0 // indirect
+ golang.org/x/oauth2 v0.3.0 // indirect
+ golang.org/x/term v0.5.0 // indirect
+ google.golang.org/api v0.34.0 // indirect
+ google.golang.org/appengine v1.6.7 // indirect
+ google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84 // indirect
+ google.golang.org/grpc v1.40.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
+ gopkg.in/cenkalti/backoff.v1 v1.1.0 // indirect
+ gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
+ k8s.io/apimachinery v0.18.3 // indirect
+ k8s.io/client-go v0.18.3 // indirect
+ k8s.io/klog v1.0.0 // indirect
+ k8s.io/klog/v2 v2.80.0 // indirect
+ k8s.io/utils v0.0.0-20200520001619-278ece378a50 // indirect
+ lukechampine.com/blake3 v1.1.7 // indirect
+ sigs.k8s.io/structured-merge-diff/v3 v3.0.0 // indirect
+ sigs.k8s.io/yaml v1.2.0 // indirect
)
-replace github.com/tendermint/tendermint => github.com/bnb-chain/tendermint v0.31.15
+replace (
+ github.com/grpc-ecosystem/grpc-gateway/v2 => github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1
+ github.com/tendermint/tendermint => github.com/bnb-chain/tendermint v0.31.15
+)
diff --git a/go.sum b/go.sum
index e838e4df64..2a5734114f 100644
--- a/go.sum
+++ b/go.sum
@@ -1,5 +1,7 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.31.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
+cloud.google.com/go v0.37.0/go.mod h1:TS1dMSSfndXH133OKGwekG838Om/cQT0BUHV3HcBgoo=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.43.0/go.mod h1:BOSR3VbTLkk6FDC/TcffxP4NF/FFBGA5ku+jvKOP7pg=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
@@ -24,6 +26,7 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7
cloud.google.com/go/bigtable v1.2.0/go.mod h1:JcVAOl45lrTmQfLj7T6TxyMzIN/3FGGcFm+2xVAli2o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
+cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
@@ -34,7 +37,14 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
collectd.org v0.3.0/go.mod h1:A/8DzQBkF6abtvrT2j/AU/4tiBgJWYyh0y/oB/4MlWE=
+contrib.go.opencensus.io/exporter/jaeger v0.2.1 h1:yGBYzYMewVL0yO9qqJv3Z5+IRhPdU7e9o/2oKpX4YvI=
+contrib.go.opencensus.io/exporter/jaeger v0.2.1/go.mod h1:Y8IsLgdxqh1QxYxPC5IgXVmBaeLUeQFfBeBi9PbeZd0=
+dmitri.shuralyov.com/app/changes v0.0.0-20180602232624-0a106ad413e3/go.mod h1:Yl+fi1br7+Rr3LqpNJf1/uxUdtRUV+Tnj0o93V2B9MU=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
+dmitri.shuralyov.com/html/belt v0.0.0-20180602232347-f7d459c86be0/go.mod h1:JLBrvjyP0v+ecvNYvCpyZgu5/xkfAUhi6wJj28eUfSU=
+dmitri.shuralyov.com/service/change v0.0.0-20181023043359-a85b471d5412/go.mod h1:a1inKt/atXimZ4Mv927x+r7UpyzRUf4emIoiiSC2TN4=
+dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D6DFvNNtx+9ybjezNCa8XF0xaYcETyp6rHWU=
+git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
github.com/Azure/azure-pipeline-go v0.2.2 h1:6oiIS9yaG6XCCzhgAgKFfIWyo4LLCiDhZot6ltoThhY=
github.com/Azure/azure-pipeline-go v0.2.2/go.mod h1:4rQ/NZncSvGqNkkOsNpOU1tgoNuIlp9AfUH5G1tvCHc=
@@ -56,22 +66,51 @@ github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6L
github.com/Azure/go-autorest/tracing v0.5.0 h1:TRn4WjSnkcSy5AEG3pnbtFSwNtwzjr4VYyQflFE619k=
github.com/Azure/go-autorest/tracing v0.5.0/go.mod h1:r/s2XiOKccPW3HrqB+W0TQzfbtp2fGCgRFtBroKn4Dk=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
+github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
+github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0=
+github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
+github.com/OneOfOne/xxhash v1.2.2 h1:KMrpdQIwFcEqXDklaen+P1axHaj9BSKzvpUUfnHldSE=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
-github.com/VictoriaMetrics/fastcache v1.6.0 h1:C/3Oi3EiBCqufydp1neRZkqcwmEiuRT9c3fqvvgKm5o=
-github.com/VictoriaMetrics/fastcache v1.6.0/go.mod h1:0qHz5QP0GMX4pfmMA/zt5RgfNuXJrTP0zS7DqpHGGTw=
+github.com/PuerkitoBio/purell v1.0.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
+github.com/PuerkitoBio/urlesc v0.0.0-20160726150825-5bd2802263f2/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
+github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo=
+github.com/Shopify/sarama v1.26.1/go.mod h1:NbSGBSSndYaIhRcBtY9V0U7AyH+x71bG668AuWys/yU=
+github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI=
+github.com/VictoriaMetrics/fastcache v1.10.0 h1:5hDJnLsKLpnUEToub7ETuRu8RCkb40woBZAUiKonXzY=
+github.com/VictoriaMetrics/fastcache v1.10.0/go.mod h1:tjiYeEfYXCqacuvYw/7UoDIeJaNxq6132xHICNP77w8=
github.com/VividCortex/gohistogram v1.0.0 h1:6+hBz+qvs0JOrrNhhmR7lFxo5sINxBCGXrdtl/UvroE=
+github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
+github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c=
github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho=
-github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
+github.com/allegro/bigcache v1.2.1 h1:hg1sY1raCwic3Vnsvje6TT7/pnZba83LeFck5NrFKSc=
+github.com/allegro/bigcache v1.2.1/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
+github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
+github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
+github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ=
+github.com/aristanetworks/fsnotify v1.4.2/go.mod h1:D/rtu7LpjYM8tRJphJ0hUBYpjai8SfX+aSNsWDTq/Ks=
+github.com/aristanetworks/glog v0.0.0-20191112221043-67e8567f59f3/go.mod h1:KASm+qXFKs/xjSoWn30NrWBBvdTTQq+UjkhjEJHfSFA=
+github.com/aristanetworks/goarista v0.0.0-20200805130819-fd197cf57d96 h1:XJH0YfVFKbq782tlNThzN/Ud5qm/cx6LXOA/P6RkTxc=
+github.com/aristanetworks/goarista v0.0.0-20200805130819-fd197cf57d96/go.mod h1:QZe5Yh80Hp1b6JxQdpfSEEe8X7hTyTEZSosSrFf/oJE=
+github.com/aristanetworks/splunk-hec-go v0.3.3/go.mod h1:1VHO9r17b0K7WmOlLb9nTk/2YanvOEnLMUgsFrxBROc=
+github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
+github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
+github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
+github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A=
+github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU=
+github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo=
+github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
github.com/aws/aws-sdk-go-v2 v1.2.0 h1:BS+UYpbsElC82gB+2E2jiCBg36i8HlubTB/dO/moQ9c=
github.com/aws/aws-sdk-go-v2 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo=
github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo=
@@ -90,127 +129,257 @@ github.com/aws/aws-sdk-go-v2/service/sts v1.1.1 h1:TJoIfnIFubCX0ACVeJ0w46HEH5Mwj
github.com/aws/aws-sdk-go-v2/service/sts v1.1.1/go.mod h1:Wi0EBZwiz/K44YliU0EKxqTCJGUfYTWXrrBwkq736bM=
github.com/aws/smithy-go v1.1.0 h1:D6CSsM3gdxaGaqXnPgOBCeL6Mophqzu7KJOu7zW78sU=
github.com/aws/smithy-go v1.1.0/go.mod h1:EzMw8dbp/YJL4A5/sbhGddag+NPT7q084agLbB9LgIw=
+github.com/bazelbuild/rules_go v0.23.2 h1:Wxu7JjqnF78cKZbsBsARLSXx/jlGaSLCnUV3mTlyHvM=
+github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
+github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
+github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
+github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
+github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
+github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84=
github.com/bmizerany/pat v0.0.0-20170815010413-6226ea591a40/go.mod h1:8rLXio+WjiTceGBHIoTvn60HIbs7Hm7bcHjyrSqYB9c=
github.com/bnb-chain/ics23 v0.1.0 h1:DvjGOts2FBfbxB48384CYD1LbcrfjThFz8kowY/7KxU=
github.com/bnb-chain/ics23 v0.1.0/go.mod h1:cU6lTGolbbLFsGCgceNB2AzplH1xecLp6+KXvxM32nI=
github.com/bnb-chain/tendermint v0.31.15 h1:Xyn/Hifb/7X4E1zSuMdnZdMSoM2Fx6cZuKCNnqIxbNU=
github.com/bnb-chain/tendermint v0.31.15/go.mod h1:cmt8HHmQUSVaWQ/hoTefRxsh5X3ERaM1zCUIR0DPbFU=
github.com/boltdb/bolt v1.3.1/go.mod h1:clJnj/oiGkjum5o1McbSZDSLxVThjynRyGBgiAx27Ps=
+github.com/bradfitz/go-smtpd v0.0.0-20170404230938-deb6d6237625/go.mod h1:HYsPBTaaSFSlLx/70C2HPIMNZpVV8+vt/A+FMnYP11g=
github.com/btcsuite/btcd/btcec/v2 v2.3.2 h1:5n0X6hX0Zk+6omWcihdYvdAlGf2DfasC0GMf7DClJ3U=
github.com/btcsuite/btcd/btcec/v2 v2.3.2/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
github.com/btcsuite/btcd/btcutil v1.1.3 h1:xfbtw8lwpp0G6NwSHb+UE67ryTFHJAiNuipusjXSohQ=
github.com/btcsuite/btcd/chaincfg/chainhash v1.0.1 h1:q0rUy8C/TYNBQS1+CGKw68tLOFYSNEs0TFnxxnS9+4U=
+github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM=
+github.com/buger/jsonparser v0.0.0-20181115193947-bf1c66bbce23/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s=
github.com/c-bata/go-prompt v0.2.2/go.mod h1:VzqtzE2ksDBcdln8G7mk2RX9QyGjH+OVqOCSiVIqS34=
+github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ=
+github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
-github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk=
-github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
+github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU=
+github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
+github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
-github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
+github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
+github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
+github.com/chzyer/logex v1.2.0 h1:+eqR0HfOetur4tgnC8ftU5imRnhi4te+BadWS95c5AM=
+github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
+github.com/chzyer/readline v1.5.0 h1:lSwwFrbNviGePhkewF1az4oLmcwqCZijQ2/Wi3BGHAI=
+github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/chzyer/test v0.0.0-20210722231415-061457976a23 h1:dZ0/VyGgQdVGAss6Ju0dt5P0QltE0SFY5Woh6hbIfiQ=
+github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
+github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs=
+github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.14.0 h1:gFqGlGl/5f9UGXAaKapCGUfaTCgRKKnzu2VvzMZlOFA=
github.com/cloudflare/cloudflare-go v0.14.0/go.mod h1:EnwdgGMaFOruiPZRFSgn+TsQ3hQ7C/YWzIGLeu5c304=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
+github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
+github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
+github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
+github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI=
github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/3mZuaj6Sj+PqrmIquiOKy397AKGThQPaGzNXAQ=
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f h1:C43yEtQ6NIf4ftFXD/V55gnGFgPbMQobd//YlnLjUJ8=
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
+github.com/containerd/cgroups v0.0.0-20201119153540-4cbc285b3327/go.mod h1:ZJeTFisyysqgcCdecO57Dj79RfL0LNeGiFUqLYQRYLE=
+github.com/containerd/cgroups v1.0.4 h1:jN/mbWBEaz+T1pi5OFtnkQ+8qnmEbAr1Oo1FRm5B0dA=
+github.com/containerd/cgroups v1.0.4/go.mod h1:nLNQtsF7Sl2HxNebu77i1R0oDlhiTG+kO4JTrUzo6IA=
+github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
+github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
+github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
+github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd v0.0.0-20181012123002-c6f51f82210d/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
+github.com/coreos/go-systemd/v22 v22.1.0/go.mod h1:xO0FLkIi5MaZafQlIrOotqXZ90ih+1atmu1JpKERPPk=
+github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
+github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
+github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
+github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
+github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w=
+github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
+github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
+github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
+github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c h1:pFUpOrbxDR6AkioZ1ySsx5yxlDQZ8stG2b88gTPxgJU=
+github.com/davidlazar/go-crypto v0.0.0-20200604182044-b73af7476f6c/go.mod h1:6UhI8N9EjYm1c2odKpFpAYeR8dsBeM7PtzQhRgxRr9U=
github.com/deckarep/golang-set v1.8.0 h1:sk9/l/KqpunDwP7pSjUg0keiOOLEnOBHzykLrsPppp4=
github.com/deckarep/golang-set v1.8.0/go.mod h1:5nI87KwE7wgsBU1F4GKAw2Qod7p5kyS383rP6+o6qqo=
github.com/decred/dcrd/crypto/blake256 v1.0.0 h1:/8DMNYp9SGi5f0w7uCm6d6M4OU2rGFK09Y2A4Xv7EE0=
-github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc=
-github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0 h1:HbphB4TFFXpv7MNrT52FGrrgVXF1owhMVTHFZIlnvd4=
+github.com/decred/dcrd/dcrec/secp256k1/v4 v4.1.0/go.mod h1:DZGJHZMqrU4JJqFAWUS2UO1+lbSKsdiOoYi9Zzey7Fc=
github.com/deepmap/oapi-codegen v1.6.0/go.mod h1:ryDa9AgbELGeB+YEXE1dR53yAjHwFvE9iAUlWl9Al3M=
github.com/deepmap/oapi-codegen v1.8.2 h1:SegyeYGcdi0jLLrpbCMoJxnUUn8GBXHsvr4rbzjuhfU=
github.com/deepmap/oapi-codegen v1.8.2/go.mod h1:YLgSKSDv/bZQB7N4ws6luhozi3cEdRktEqrX88CvjIw=
+github.com/dgraph-io/ristretto v0.0.4-0.20210318174700-74754f61e018 h1:cNcG4c2n5xanQzp2hMyxDxPYVQmZ91y4WN6fJFlndLo=
+github.com/dgraph-io/ristretto v0.0.4-0.20210318174700-74754f61e018/go.mod h1:MIonLggsKgZLUSt414ExgwNtlOL5MuEoAJP514mwGe8=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/dgryski/go-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ=
+github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2 h1:tdlZCpZ/P9DhczCTSixgIKmwPv6+wP5DGjqLYw5SUiA=
+github.com/dgryski/go-farm v0.0.0-20190423205320-6a90982ecee2/go.mod h1:SqUrOPUnsFjfmXRMNPybcSiG0BgUW2AuFH8PAnS2iTw=
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
-github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91 h1:Izz0+t1Z5nI16/II7vuEo/nHjodOg0p7+OiDpjX5t1E=
github.com/dlclark/regexp2 v1.4.1-0.20201116162257-a2a8dda75c91/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc=
+github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo=
+github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8=
github.com/docker/docker v1.6.1 h1:4xYASHy5cScPkLD7PO0uTmnVc860m9NarPN1X8zeMe8=
github.com/docker/docker v1.6.1/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
-github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf h1:Yt+4K30SdjOkRoRRm3vYNQgR+/ZIy0RmeUDZo7Y8zeQ=
-github.com/dop251/goja v0.0.0-20220405120441-9037c2b61cbf/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
+github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4=
+github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
+github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
+github.com/dop251/goja v0.0.0-20211022113120-dc8c55024d06/go.mod h1:R9ET47fwRVRPZnOGvHxxhuZcbrMCuiqOz3Rlrh4KSnk=
+github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7 h1:kgvzE5wLsLa7XKfV85VZl40QXaMCaeFtHpPwJ8fhotY=
+github.com/dop251/goja v0.0.0-20230122112309-96b1610dd4f7/go.mod h1:yRkwfj0CBpOGre+TwBsqPV0IH0Pk73e4PXJOeNDboGs=
github.com/dop251/goja_nodejs v0.0.0-20210225215109-d91c329300e7/go.mod h1:hn7BA7c8pLvoGndExHudxTDKZ84Pyvv+90pbBjbTz0Y=
+github.com/dop251/goja_nodejs v0.0.0-20211022123610-8dd9abb0616d/go.mod h1:DngW8aVqWbuLRMHItjPUyqdj+HWPvnQe8V8y1nDpIbM=
+github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
+github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
+github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs=
+github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU=
+github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/eclipse/paho.mqtt.golang v1.2.0/go.mod h1:H9keYFcgq3Qr5OUJm/JZI/i6U7joQ8SYLhZwfeOo6Ts=
-github.com/edsrzf/mmap-go v1.0.0 h1:CEBF7HpRnUCSJgGUb5h1Gm7e3VkmVDrR8lvWVLtrOFw=
github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
+github.com/edsrzf/mmap-go v1.1.0 h1:6EUwBLQ/Mcr1EYLE4Tn1VdW1A4ckqCQWZBw8Hr0kjpQ=
+github.com/edsrzf/mmap-go v1.1.0/go.mod h1:19H/e8pUPLicwkyNgOykDXkJ9F0MHE+Z52B8EIth78Q=
+github.com/elastic/gosigar v0.12.0/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
+github.com/elastic/gosigar v0.14.2 h1:Dg80n8cr90OZ7x+bAax/QjoW/XqTI11RmA79ZwIm9/4=
+github.com/elastic/gosigar v0.14.2/go.mod h1:iXRIGg2tLnu7LBdpqzyQfGDEidKCfWcCMS0WKyPWoMs=
+github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc=
+github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
+github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
+github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
github.com/etcd-io/bbolt v1.3.3 h1:gSJmxrs37LgTqR/oyJBWok6k6SvXEUerFTbltIhXkBM=
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
-github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
+github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
+github.com/fatih/color v1.9.0 h1:8xPHl4/q1VyqGIPif1F+1V3Y3lSmrq01EabUW3CoW5s=
+github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo=
github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
+github.com/ferranbt/fastssz v0.0.0-20210120143747-11b9eff30ea9/go.mod h1:DyEu2iuLBnb/T51BlsiO3yLYdJC6UbGMrIkqK1KmQxM=
+github.com/ferranbt/fastssz v0.0.0-20210905181407-59cf6761a7d5 h1:6dVcS0LktRSyEEgldFY4N9J17WjUoiJStttH+RZj0Wo=
+github.com/ferranbt/fastssz v0.0.0-20210905181407-59cf6761a7d5/go.mod h1:S8yiDeAXy8f88W4Ul+0dBMPx49S05byYbmZD6Uv94K4=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c=
github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
+github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
+github.com/flynn/noise v1.0.0 h1:DlTHqmzmvcEiKj+4RYo/imoswx/4r6iBlCMfVtrMXpQ=
+github.com/flynn/noise v1.0.0/go.mod h1:xbMo+0i6+IGbYdJhF31t2eR1BIU0CYc12+BNAKwUTag=
github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
+github.com/francoispqt/gojay v1.2.13 h1:d2m3sFjloqoIUQU3TsHBgj6qg/BVGlTBeHDUmyJnXKk=
+github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
+github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4=
+github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20=
+github.com/frankban/quicktest v1.7.2/go.mod h1:jaStnuzAqU1AJdCO0l53JDCJrVDKcS03DbaAcR7Ks/o=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
-github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
-github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
-github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
+github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
+github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
+github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
+github.com/garyburd/redigo v1.6.0/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
+github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08 h1:f6D9Hr8xV8uYKlyuj8XIruxlh9WjVjdh1gIicAS7ays=
+github.com/gballet/go-libpcsclite v0.0.0-20191108122812-4678299bea08/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
github.com/getkin/kin-openapi v0.53.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
github.com/getkin/kin-openapi v0.61.0/go.mod h1:7Yn5whZr5kJi6t+kShccXS8ae1APpYTW6yheSwk8Yi4=
+github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/gliderlabs/ssh v0.1.1/go.mod h1:U7qILu1NlMHj9FlMhZLlkCdDnU1DBEAqr0aevW3Awn0=
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
github.com/glycerine/goconvey v0.0.0-20190410193231-58a59202ab31/go.mod h1:Ogl1Tioa0aV7gstGFO7KhffUsb9M4ydbEbbxpcEDc24=
github.com/go-chi/chi/v5 v5.0.0/go.mod h1:BBug9lr0cqtdAhsu6R4AAdvufI0/XBzAQSsUqJpoZOs=
+github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
-github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY=
-github.com/go-kit/log v0.2.0/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
+github.com/go-kit/kit v0.10.0 h1:dXFJfIHVvUcpSgDOV+Ne6t7jXri8Tfv2uOLHUZ2XNuo=
+github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A=
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs=
+github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
+github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
+github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
+github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
+github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
+github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
+github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nAiCcj+friV/PDoE1/3eeccG9LYBs0tYvLOWc=
+github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
+github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
+github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
+github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
+github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
+github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
+github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
+github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
+github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible h1:W1iEw64niKVGogNgBN3ePyLFfuisuzeidWPMPWmECqU=
github.com/go-sourcemap/sourcemap v2.1.3+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
+github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
-github.com/go-stack/stack v1.8.0 h1:5SgMzNM5HxrEjV0ww2lTmX6E2Izsfxas4+YHWRs3Lsk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/go-stack/stack v1.8.1 h1:ntEHSVwIt7PNXNpgPmVfMrNhLtgjlmnZha2kOpuRiDw=
+github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 h1:p104kn46Q8WdvHunIJ9dAyjPVtrBPhSr3KT2yUst43I=
+github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
+github.com/go-yaml/yaml v2.1.0+incompatible h1:RYi2hDdss1u4YE7GwixGzWwVo47T8UQwnTLB6vQiq+o=
+github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
+github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
+github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU=
github.com/gofrs/uuid v3.3.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
+github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
+github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
+github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
+github.com/golang-jwt/jwt/v4 v4.3.0 h1:kHL1vqdqWNfATmA0FNMdmZNMyZI1U6O31X4rlIPoBog=
+github.com/golang-jwt/jwt/v4 v4.3.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg=
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
+github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
+github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
+github.com/golang/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:tluoj9z5200jBnyusfRPU2LqT6J+DAorxEvtC7LHB+E=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
@@ -218,6 +387,9 @@ github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
+github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc=
+github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
+github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
@@ -236,6 +408,7 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
+github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
@@ -250,12 +423,21 @@ github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
+github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
-github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
+github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
+github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
+github.com/google/go-github v17.0.0+incompatible/go.mod h1:zLgOLi98H3fifZn+44m+umXrS52loVEgC2AApnigrVQ=
+github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0=
github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
+github.com/google/gopacket v1.1.17/go.mod h1:UdDNZ1OO62aGYVnPhxT1U6aI7ukYtA/kB8vaU0diBUM=
+github.com/google/gopacket v1.1.19 h1:ves8RnFZPGiFnTS0uPQStjwru6uO6h+nlr9j6fL7kF8=
+github.com/google/gopacket v1.1.19/go.mod h1:iJ8V8n6KS+z2U1A8pUwu8bW5SyEMkXJB8Yo/Vo+TKTo=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
@@ -265,40 +447,98 @@ github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hf
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
-github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40 h1:ykKxL12NZd3JmWZnyqarJGsF73M9Xhtrik/FEtEeFRE=
-github.com/google/pprof v0.0.0-20220829040838-70bd9ae97f40/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
+github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
+github.com/google/pprof v0.0.0-20221203041831-ce31453925ec h1:fR20TYVVwhK4O7r7y+McjRYyaTH6/vjwJOajE+XhlzM=
+github.com/google/pprof v0.0.0-20221203041831-ce31453925ec/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
-github.com/google/uuid v1.1.5 h1:kxhtnfFVi+rYdOALN0B3k9UT86zVJKfBimRaciULW4I=
-github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
+github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/googleapis/gax-go v2.0.0+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY=
+github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE08qbEPm1M08qg=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
+github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/googleapis/gnostic v0.1.0/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
+github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
+github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
+github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
+github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
+github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
+github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
+github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/graph-gophers/graphql-go v1.3.0 h1:Eb9x/q6MFpCLz7jBCiP/WTxjSDrYLR1QY41SORZyNJ0=
github.com/graph-gophers/graphql-go v1.3.0/go.mod h1:9CQHMSxwO4MprSdzoIEobiHpoLtHm77vfxsvsIN5Vuc=
+github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
+github.com/grpc-ecosystem/go-grpc-middleware v1.2.2 h1:FlFbCRLd5Jr4iYXZufAvgWN6Ao0JrI5chLINnUXDDr0=
+github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
+github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
+github.com/grpc-ecosystem/grpc-gateway v1.5.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
+github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY=
+github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
+github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
+github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE=
+github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
+github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
+github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-bexpr v0.1.10 h1:9kuI5PFotCboP3dkDYFr/wi0gg0QVbSNz5oFRpxn4uE=
github.com/hashicorp/go-bexpr v0.1.10/go.mod h1:oxlubA2vC/gFVfX1A6JGp7ls7uCDlfJn732ehYYg+g0=
+github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
+github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
+github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
+github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
+github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
+github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
+github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
+github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
+github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
+github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d h1:dg1dEPuWpEqDnvIw251EVy4zlP8gWbsGj4BsUKCRpYs=
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
+github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
+github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
+github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
+github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
+github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
+github.com/herumi/bls-eth-go-binary v0.0.0-20210130185500-57372fb27371/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
+github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e h1:wCMygKUQhmcQAjlk2Gquzq6dLmyMv2kF+llRspoRgrk=
+github.com/herumi/bls-eth-go-binary v0.0.0-20210917013441-d37c07cfda4e/go.mod h1:luAnRm3OsMQeokhGzpYmc0ZKwawY7o87PUEP11Z7r7U=
github.com/holiman/bloomfilter/v2 v2.0.3 h1:73e0e/V0tCydx14a0SCYS/EWCxgwLZ18CZcZKVu0fao=
github.com/holiman/bloomfilter/v2 v2.0.3/go.mod h1:zpoh+gs7qcpqrHr3dB55AMiJwo0iURXE7ZOP9L9hSkA=
github.com/holiman/uint256 v1.2.0 h1:gpSYcPLWGv4sG43I2mVLiDZCNDh/EpGjSk8tmtxitHM=
github.com/holiman/uint256 v1.2.0/go.mod h1:y4ga/t+u+Xwd7CpDgZESaRcWy0I7XMlTMA25ApIH5Jw=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
+github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg=
+github.com/huin/goupnp v1.0.0/go.mod h1:n9v9KO1tAxYH82qOn+UTIFQDmx5n1Zxd/ClZDMX7Bnc=
github.com/huin/goupnp v1.0.3 h1:N8No57ls+MnjlB+JPiCVSOyy/ot7MJTqlo7rn+NYSqQ=
github.com/huin/goupnp v1.0.3/go.mod h1:ZxNlw5WqJj6wSsRK5+YfflQGXYfccj5VgQsMNixHM7Y=
github.com/huin/goutil v0.0.0-20170803182201-1ca381bf3150/go.mod h1:PpLOETDnJ0o3iZrZfqZzyLl6l7F3c6L1oWn7OICBi6o=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
+github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY=
github.com/influxdata/influxdb v1.8.3 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vAiBg8=
github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI=
github.com/influxdata/influxdb-client-go/v2 v2.4.0 h1:HGBfZYStlx3Kqvsv1h2pJixbCl/jhnFtxpKFAv9Tu5k=
github.com/influxdata/influxdb-client-go/v2 v2.4.0/go.mod h1:vLNHdxTJkIf2mSLvGrpj8TCcISApPoXkaxP8g9uRlW8=
+github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo=
github.com/influxdata/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk=
github.com/influxdata/line-protocol v0.0.0-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE=
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
@@ -308,44 +548,88 @@ github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19y
github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE=
github.com/influxdata/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
github.com/influxdata/usage-client v0.0.0-20160829180054-6d3895376368/go.mod h1:Wbbw6tYNvwa5dlB6304Sd+82Z3f7PmVZHVKU637d4po=
+github.com/ipfs/go-cid v0.3.2 h1:OGgOd+JCFM+y1DjWPmVH+2/4POtpDzwcr7VgnB7mZXc=
+github.com/ipfs/go-cid v0.3.2/go.mod h1:gQ8pKqT/sUxGY+tIwy1RPpAojYu7jAyCp5Tz1svoupw=
+github.com/ipfs/go-detect-race v0.0.1 h1:qX/xay2W3E4Q1U7d9lNs1sU9nvguX0a7319XbyQ6cOk=
+github.com/ipfs/go-detect-race v0.0.1/go.mod h1:8BNT7shDZPo99Q74BpGMK+4D8Mn4j46UU0LZ723meps=
+github.com/ipfs/go-log v1.0.5 h1:2dOuUCB1Z7uoczMWgAyDck5JLb72zHzrMnGnCNNbvY8=
+github.com/ipfs/go-log v1.0.5/go.mod h1:j0b8ZoR+7+R99LD9jZ6+AJsrzkPbSXbZfGakb5JPtIo=
+github.com/ipfs/go-log/v2 v2.1.3/go.mod h1:/8d0SH3Su5Ooc31QlL1WysJhvyOTDCjcCZ9Axpmri6g=
+github.com/ipfs/go-log/v2 v2.5.1 h1:1XdUzF7048prq4aBjDQQ4SL5RxftpRGdXhNRwKSAlcY=
+github.com/ipfs/go-log/v2 v2.5.1/go.mod h1:prSpmC1Gpllc9UYWxDiZDreBYw7zp4Iqp1kOLU9U5UI=
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
+github.com/jbenet/go-temp-err-catcher v0.1.0 h1:zpb3ZH6wIE8Shj2sKS+khgRvf7T7RABoLk/+KKHggpk=
+github.com/jbenet/go-temp-err-catcher v0.1.0/go.mod h1:0kJRvmDZXNMIiJirNPEYfhpPwbGVtZVWC34vc5WLsDk=
+github.com/jcmturner/gofork v1.0.0/go.mod h1:MK8+TM0La+2rjBD4jE12Kj1pCCxK7d2LK/UM3ncEo0o=
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U=
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
+github.com/jellevandenhooff/dkim v0.0.0-20150330215556-f50fe3d243e1/go.mod h1:E0B/fFc00Y+Rasa88328GlI/XbtyysCtTHZS8h7IrBU=
+github.com/jhump/protoreflect v1.8.1/go.mod h1:7GcYQDdMU/O/BBrl/cX6PNHpXh6cenjd8pneu5yW7Tg=
+github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/jmhodges/levigo v1.0.0 h1:q5EC36kV79HWeTBWsod3mG11EgStG3qArTKcvlksN1U=
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
+github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
+github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
-github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
+github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jsternberg/zap-logfmt v1.0.0/go.mod h1:uvPs/4X51zdkcm5jXl5SYoN+4RK21K8mysFmDaM/h+o=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
+github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
+github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
github.com/julienschmidt/httprouter v1.3.0/go.mod h1:JR6WtHb+2LUe8TCKY3cZOxFyyO8IZAc4RVcycCCAKdM=
github.com/jung-kurt/gofpdf v1.0.3-0.20190309125859-24315acbbda5/go.mod h1:7Id9E/uU8ce6rXgefFLlgrJj/GYY22cpxn+r32jIOes=
github.com/jwilder/encoding v0.0.0-20170811194829-b4e1701a28ef/go.mod h1:Ct9fl0F6iIOGgxJ5npU/IUOhOhqlVrGjyIZc8/MagT0=
+github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 h1:qGQQKEcAR99REcMpsXCp3lJ03zYT1PkRd3kQGPn9GVg=
+github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213/go.mod h1:vNUNkEQ1e29fT/6vq2aBdFsgNPmy8qMdSay1npru+Sw=
github.com/karalabe/usb v0.0.2 h1:M6QQBNxF+CQ8OFvxrT90BA0qBOXymndZnk5q235mFc4=
github.com/karalabe/usb v0.0.2/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
+github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q=
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.9.8/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
+github.com/klauspost/compress v1.10.1/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
+github.com/klauspost/compress v1.15.15 h1:EF27CXIuDsYJ6mmvtBRlEuB2UVOqHG1tAXgZ7yIO+lw=
+github.com/klauspost/compress v1.15.15/go.mod h1:ZcK2JAFqKOpnBlxcLsJzYfrS9X1akm9fHZNnD9+Vo/4=
github.com/klauspost/cpuid v0.0.0-20170728055534-ae7887de9fa5/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/cpuid v1.2.3/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
+github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
+github.com/klauspost/cpuid/v2 v2.2.1 h1:U33DW0aiEj633gHYw3LoDNfkDiYnE5Q8M/TKJn2f2jI=
+github.com/klauspost/cpuid/v2 v2.2.1/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/crc32 v0.0.0-20161016154125-cb6bfca970f6/go.mod h1:+ZoRqAPRLkC4NPOvfYeR5KNOrY6TD+/sAC3HXPZgDYg=
github.com/klauspost/pgzip v1.0.2-0.20170402124221-0bf5dcad4ada/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
+github.com/klauspost/reedsolomon v1.9.3/go.mod h1:CwCi+NUr9pqSVktrkN+Ondf06rkhYZ/pcNv7fu+8Un4=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
+github.com/koron/go-ssdp v0.0.0-20191105050749-2e1c40ed0b5d/go.mod h1:5Ky9EC2xfoUKUor0Hjgi2BJhCSXJfMOFlmyYrVKGQMk=
+github.com/koron/go-ssdp v0.0.3 h1:JivLMY45N76b4p/vsWGOKewBQu6uf39y8l+AQ7sDKx8=
+github.com/koron/go-ssdp v0.0.3/go.mod h1:b2MxI6yh02pKrsyNoQUsk4+YNikaGhe4894J+Q5lDvA=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
-github.com/kr/pretty v0.2.1 h1:Fmg33tUaq4/8ym9TJN1x7sLJnHVwhP33CNkpYV/7rwI=
+github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
+github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
+github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
+github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
+github.com/kr/pty v1.1.3/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
@@ -355,133 +639,414 @@ github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4F
github.com/labstack/gommon v0.3.0/go.mod h1:MULnywXg0yavhxWKc+lOruYdAhDwPK9wf0OL7NoOu+k=
github.com/leanovate/gopter v0.2.9 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
+github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
+github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
+github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6cdF0Y8=
+github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
+github.com/libp2p/go-cidranger v1.1.0 h1:ewPN8EZ0dd1LSnrtuwd4709PXVcITVeuwbag38yPW7c=
+github.com/libp2p/go-cidranger v1.1.0/go.mod h1:KWZTfSr+r9qEo9OkI9/SIEeAtw+NNoU0dXIXt15Okic=
+github.com/libp2p/go-flow-metrics v0.1.0 h1:0iPhMI8PskQwzh57jB9WxIuIOQ0r+15PChFGkx3Q3WM=
+github.com/libp2p/go-flow-metrics v0.1.0/go.mod h1:4Xi8MX8wj5aWNDAZttg6UPmc0ZrnFNsMtpsYUClFtro=
+github.com/libp2p/go-libp2p v0.24.0 h1:DQk/5bBon+yUVIGTeRVBmOYpZzoBHx/VTC0xoLgJGG4=
+github.com/libp2p/go-libp2p v0.24.0/go.mod h1:28t24CYDlnBs23rIs1OclU89YbhgibrBq2LFbMe+cFw=
+github.com/libp2p/go-libp2p-asn-util v0.2.0 h1:rg3+Os8jbnO5DxkC7K/Utdi+DkY3q/d1/1q+8WeNAsw=
+github.com/libp2p/go-libp2p-asn-util v0.2.0/go.mod h1:WoaWxbHKBymSN41hWSq/lGKJEca7TNm58+gGJi2WsLI=
+github.com/libp2p/go-libp2p-pubsub v0.8.0 h1:KygfDpaa9AeUPGCVcpVenpXNFauDn+5kBYu3EjcL3Tg=
+github.com/libp2p/go-libp2p-pubsub v0.8.0/go.mod h1:e4kT+DYjzPUYGZeWk4I+oxCSYTXizzXii5LDRRhjKSw=
+github.com/libp2p/go-libp2p-testing v0.12.0 h1:EPvBb4kKMWO29qP4mZGyhVzUyR25dvfUIK5WDu6iPUA=
+github.com/libp2p/go-mplex v0.7.0 h1:BDhFZdlk5tbr0oyFq/xv/NPGfjbnrsDam1EvutpBDbY=
+github.com/libp2p/go-mplex v0.7.0/go.mod h1:rW8ThnRcYWft/Jb2jeORBmPd6xuG3dGxWN/W168L9EU=
+github.com/libp2p/go-msgio v0.2.0 h1:W6shmB+FeynDrUVl2dgFQvzfBZcXiyqY4VmpQLu9FqU=
+github.com/libp2p/go-msgio v0.2.0/go.mod h1:dBVM1gW3Jk9XqHkU4eKdGvVHdLa51hoGfll6jMJMSlY=
+github.com/libp2p/go-nat v0.1.0 h1:MfVsH6DLcpa04Xr+p8hmVRG4juse0s3J8HyNWYHffXg=
+github.com/libp2p/go-nat v0.1.0/go.mod h1:X7teVkwRHNInVNWQiO/tAiAVRwSr5zoRz4YSTC3uRBM=
+github.com/libp2p/go-netroute v0.1.2/go.mod h1:jZLDV+1PE8y5XxBySEBgbuVAXbhtuHSdmLPL2n9MKbk=
+github.com/libp2p/go-netroute v0.2.1 h1:V8kVrpD8GK0Riv15/7VN6RbUQ3URNZVosw7H2v9tksU=
+github.com/libp2p/go-netroute v0.2.1/go.mod h1:hraioZr0fhBjG0ZRXJJ6Zj2IVEVNx6tDTFQfSmcq7mQ=
+github.com/libp2p/go-openssl v0.1.0 h1:LBkKEcUv6vtZIQLVTegAil8jbNpJErQ9AnT+bWV+Ooo=
+github.com/libp2p/go-openssl v0.1.0/go.mod h1:OiOxwPpL3n4xlenjx2h7AwSGaFSC/KZvf6gNdOBQMtc=
+github.com/libp2p/go-reuseport v0.2.0 h1:18PRvIMlpY6ZK85nIAicSBuXXvrYoSw3dsBAR7zc560=
+github.com/libp2p/go-reuseport v0.2.0/go.mod h1:bvVho6eLMm6Bz5hmU0LYN3ixd3nPPvtIlaURZZgOY4k=
+github.com/libp2p/go-sockaddr v0.0.2/go.mod h1:syPvOmNs24S3dFVGJA1/mrqdeijPxLV2Le3BRLKd68k=
+github.com/libp2p/go-yamux/v4 v4.0.0 h1:+Y80dV2Yx/kv7Y7JKu0LECyVdMXm1VUoko+VQ9rBfZQ=
+github.com/libp2p/go-yamux/v4 v4.0.0/go.mod h1:NWjl8ZTLOGlozrXSOZ/HlfG++39iKNnM5wwmtQP1YB4=
+github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM=
+github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4=
+github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczGlG91VSDkswnjF5A8=
+github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
+github.com/lucas-clemente/quic-go v0.31.0 h1:MfNp3fk0wjWRajw6quMFA3ap1AVtlU+2mtwmbVogB2M=
+github.com/lucas-clemente/quic-go v0.31.0/go.mod h1:0wFbizLgYzqHqtlyxyCaJKlE7bYgE6JQ+54TLd/Dq2g=
+github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
+github.com/lunixbochs/vtclean v1.0.0 h1:xu2sLAri4lGiovBDQKxl5mrXyESr3gUr5m5SM5+LVb8=
+github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
+github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ=
+github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
+github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
+github.com/manifoldco/promptui v0.7.0 h1:3l11YT8tm9MnwGFQ4kETwkzpAwY2Jt9lCrumCUW4+z4=
+github.com/manifoldco/promptui v0.7.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
+github.com/marten-seemann/qpack v0.3.0 h1:UiWstOgT8+znlkDPOg2+3rIuYXJ2CnGDkGUXN6ki6hE=
+github.com/marten-seemann/qtls-go1-18 v0.1.3 h1:R4H2Ks8P6pAtUagjFty2p7BVHn3XiwDAl7TTQf5h7TI=
+github.com/marten-seemann/qtls-go1-18 v0.1.3/go.mod h1:mJttiymBAByA49mhlNZZGrH5u1uXYZJ+RW28Py7f4m4=
+github.com/marten-seemann/qtls-go1-19 v0.1.1 h1:mnbxeq3oEyQxQXwI4ReCgW9DPoPR94sNlqWoDZnjRIE=
+github.com/marten-seemann/qtls-go1-19 v0.1.1/go.mod h1:5HTDWtVudo/WFsHKRNuOhWlbdjrfs5JHrYb0wIJqGpI=
+github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd h1:br0buuQ854V8u83wA0rVZ8ttrq5CpaPZdvrK0LP2lOk=
+github.com/marten-seemann/tcp v0.0.0-20210406111302-dfbc87cc63fd/go.mod h1:QuCEs1Nt24+FYQEqAAncTDPJIuGs+LxK1MCiFL25pMU=
+github.com/marten-seemann/webtransport-go v0.4.1 h1:8Ir7OoAvtp79yxQpa3foTKIPuoH+0eKpisHObJyu9Sk=
github.com/matryer/moq v0.0.0-20190312154309-6cfb0558e1bd/go.mod h1:9ELz6aaclSIGnZBoaSLZ3NAl1VTufbOrXBPvtcy6WiQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
+github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
github.com/mattn/go-colorable v0.1.7/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
-github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8=
github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
+github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
+github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d h1:oNAwILwmgWKFpuU+dXvI6dl9jG2mAWAZLX3r9s0PPiw=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
+github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ=
-github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY=
+github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
+github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
+github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
+github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
+github.com/mattn/go-pointer v0.0.1 h1:n+XhsuGeVO6MEAp7xyEukFINEa+Quek5psIR/ylA6o0=
+github.com/mattn/go-pointer v0.0.1/go.mod h1:2zXcozF6qYGgmsG+SeTZz3oAbFLdD3OWqnUbNvJZAlc=
+github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
-github.com/mattn/go-runewidth v0.0.9 h1:Lm995f3rfxdpd6TSmuVCHVb/QhupuXlYr8sCI/QdE+0=
github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
+github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
+github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
github.com/mattn/go-tty v0.0.0-20180907095812-13ff1204f104/go.mod h1:XPvLUNfbS4fJH25nqRHfWLMa1ONC8Amw+mIA639KxkE=
-github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
+github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
+github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
+github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
+github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
+github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
+github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA=
+github.com/miekg/dns v1.1.50/go.mod h1:e3IlAVfNqAllflbibAZEWOXOQ+Ynzk/dDozDxY7XnME=
+github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c h1:bzE/A84HN25pxAuk9Eej1Kz9OUelF97nAc82bDquQI8=
+github.com/mikioh/tcp v0.0.0-20190314235350-803a9b46060c/go.mod h1:0SQS9kMwD2VsyFEB++InYyBJroV/FRmBgcydeSUcJms=
+github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b h1:z78hV3sbSMAUoyUMM0I83AUIT6Hu17AWfgjzIbtrYFc=
+github.com/mikioh/tcpinfo v0.0.0-20190314235526-30a79bb1804b/go.mod h1:lxPUiZwKoFL8DUUmalo2yJJUCxbPKtm8OKfqr2/FTNU=
+github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc h1:PTfri+PuQmWDqERdnNMiD9ZejrlswWrCpBEZgWOiTrc=
+github.com/mikioh/tcpopt v0.0.0-20190314235656-172688c1accc/go.mod h1:cGKTAVKx4SxOuR/czcZ/E2RSJ3sfHs8FpHhQ5CWMf9s=
+github.com/minio/blake2b-simd v0.0.0-20160723061019-3f5f724cb5b1/go.mod h1:pD8RvIylQ358TN4wwqatJ8rNavkEINozVn9DtGI3dfQ=
+github.com/minio/highwayhash v1.0.1 h1:dZ6IIu8Z14VlC0VpfKofAhCy74wu/Qb5gcn52yWoz/0=
+github.com/minio/highwayhash v1.0.1/go.mod h1:BQskDq+xkJ12lmlUUi7U0M5Swg3EWR+dLTk+kldvVxY=
+github.com/minio/sha256-simd v0.1.1-0.20190913151208-6de447530771/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
+github.com/minio/sha256-simd v0.1.1/go.mod h1:B5e1o+1/KgNmWrSQK08Y6Z1Vb5pwIktudl0J58iy0KM=
+github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
+github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
+github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
+github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db h1:62I3jR2EmQ4l5rM/4FEfDWcRD+abF5XlKShorW5LRoQ=
+github.com/mitchellh/colorstring v0.0.0-20190213212951-d06e56a500db/go.mod h1:l0dey0ia/Uv7NcFFVbCLtqEBQbrT4OCwCSKTEv6enCw=
+github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
+github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
+github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
+github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
+github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
+github.com/mitchellh/mapstructure v1.3.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.1 h1:CpVNEelQCZBooIPDn+AR3NpivK/TIKU8bDxdASFVQag=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/pointerstructure v1.2.0 h1:O+i9nHnXS3l/9Wu7r4NrEdwA2VFTicjUEN1uBnDo34A=
github.com/mitchellh/pointerstructure v1.2.0/go.mod h1:BRAsLI5zgXmw97Lf6s25bs8ohIXc3tViBH44KcwB2g4=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
+github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
+github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
+github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
+github.com/mr-tron/base58 v1.1.2/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
+github.com/mr-tron/base58 v1.2.0 h1:T/HDJBh4ZCPbU39/+c3rRvE0uKBQlU27+QI8LJ4t64o=
+github.com/mr-tron/base58 v1.2.0/go.mod h1:BinMc/sQntlIE1frQmRFPUoPA1Zkr8VRgBdjWI2mNwc=
github.com/mschoch/smat v0.0.0-20160514031455-90eadee771ae/go.mod h1:qAyveg+e4CE+eKJXWVjKXM4ck2QobLqTDytGJbLLhJg=
+github.com/multiformats/go-base32 v0.1.0 h1:pVx9xoSPqEIQG8o+UbAe7DNi51oej1NtK+aGkbLYxPE=
+github.com/multiformats/go-base32 v0.1.0/go.mod h1:Kj3tFY6zNr+ABYMqeUNeGvkIC/UYgtWibDcT0rExnbI=
+github.com/multiformats/go-base36 v0.2.0 h1:lFsAbNOGeKtuKozrtBsAkSVhv1p9D0/qedU9rQyccr0=
+github.com/multiformats/go-base36 v0.2.0/go.mod h1:qvnKE++v+2MWCfePClUEjE78Z7P2a1UV0xHgWc0hkp4=
+github.com/multiformats/go-multiaddr v0.1.1/go.mod h1:aMKBKNEYmzmDmxfX88/vz+J5IU55txyt0p4aiWVohjo=
+github.com/multiformats/go-multiaddr v0.2.0/go.mod h1:0nO36NvPpyV4QzvTLi/lafl2y95ncPj0vFwVF6k6wJ4=
+github.com/multiformats/go-multiaddr v0.8.0 h1:aqjksEcqK+iD/Foe1RRFsGZh8+XFiGo7FgUCZlpv3LU=
+github.com/multiformats/go-multiaddr v0.8.0/go.mod h1:Fs50eBDWvZu+l3/9S6xAE7ZYj6yhxlvaVZjakWN7xRs=
+github.com/multiformats/go-multiaddr-dns v0.3.1 h1:QgQgR+LQVt3NPTjbrLLpsaT2ufAA2y0Mkk+QRVJbW3A=
+github.com/multiformats/go-multiaddr-dns v0.3.1/go.mod h1:G/245BRQ6FJGmryJCrOuTdB37AMA5AMOVuO6NY3JwTk=
+github.com/multiformats/go-multiaddr-fmt v0.1.0 h1:WLEFClPycPkp4fnIzoFoV9FVd49/eQsuaL3/CWe167E=
+github.com/multiformats/go-multiaddr-fmt v0.1.0/go.mod h1:hGtDIW4PU4BqJ50gW2quDuPVjyWNZxToGUh/HwTZYJo=
+github.com/multiformats/go-multibase v0.1.1 h1:3ASCDsuLX8+j4kx58qnJ4YFq/JWTJpCyDW27ztsVTOI=
+github.com/multiformats/go-multibase v0.1.1/go.mod h1:ZEjHE+IsUrgp5mhlEAYjMtZwK1k4haNkcaPg9aoe1a8=
+github.com/multiformats/go-multicodec v0.7.0 h1:rTUjGOwjlhGHbEMbPoSUJowG1spZTVsITRANCjKTUAQ=
+github.com/multiformats/go-multicodec v0.7.0/go.mod h1:GUC8upxSBE4oG+q3kWZRw/+6yC1BqO550bjhWsJbZlw=
+github.com/multiformats/go-multihash v0.0.8/go.mod h1:YSLudS+Pi8NHE7o6tb3D8vrpKa63epEDmG8nTduyAew=
+github.com/multiformats/go-multihash v0.2.1 h1:aem8ZT0VA2nCHHk7bPJ1BjUbHNciqZC/d16Vve9l108=
+github.com/multiformats/go-multihash v0.2.1/go.mod h1:WxoMcYG85AZVQUyRyo9s4wULvW5qrI9vb2Lt6evduFc=
+github.com/multiformats/go-multistream v0.3.3 h1:d5PZpjwRgVlbwfdTDjife7XszfZd8KYWfROYFlGcR8o=
+github.com/multiformats/go-multistream v0.3.3/go.mod h1:ODRoqamLUsETKS9BNcII4gcRsJBU5VAwRIv7O39cEXg=
+github.com/multiformats/go-varint v0.0.1/go.mod h1:3Ls8CIEsrijN6+B7PbrXRPxHRPuXSrVKRY101jdMZYE=
+github.com/multiformats/go-varint v0.0.7 h1:sWSGR+f/eu5ABZA2ZpYKBILXTTs9JWpdEM/nEGOHFS8=
+github.com/multiformats/go-varint v0.0.7/go.mod h1:r8PUYw/fD/SjBCiKOoDlGF6QawOELpZAu9eioSos/OU=
+github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/naoina/go-stringutil v0.1.0 h1:rCUeRUHjBjGTSHl0VC00jUPLz8/F9dDzYI70Hzifhks=
github.com/naoina/go-stringutil v0.1.0/go.mod h1:XJ2SJL9jCtBh+P9q5btrd/Ylo8XwT/h1USek5+NqSA0=
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416 h1:shk/vn9oCoOTmwcouEdwIeOtOGA/ELRUw/GwvxwfT+0=
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416/go.mod h1:NBIhNtsFMo3G2szEBne+bO4gS192HuIYRqfvOWb4i1E=
-github.com/nxadm/tail v1.4.4 h1:DQuhQpB1tVlglWS2hLQ5OV6B5r8aGxSrPc5Qo6uTN78=
+github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg=
+github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU=
+github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k=
+github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w=
+github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w=
+github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c=
+github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
+github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
+github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
+github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
+github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
+github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs=
+github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA=
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
+github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec=
github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY=
+github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
+github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
-github.com/onsi/ginkgo v1.14.0 h1:2mOpI4JVVPBN+WQRa0WKH2eXR+Ey+uK4n7Zj0aYpIQA=
-github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY=
+github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
+github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
+github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
+github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
+github.com/onsi/ginkgo/v2 v2.5.1 h1:auzK7OI497k6x4OvWq+TKAcpcSAlod0doAH72oIN0Jw=
+github.com/onsi/ginkgo/v2 v2.5.1/go.mod h1:63DOGlLAH8+REH8jUGdL3YpCpu7JODesutUjdENfUAc=
+github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
+github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
+github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
-github.com/onsi/gomega v1.10.1 h1:o0+MgICZLuZ7xjH7Vx6zS/zcu93/BEp1VwkIW1mEXCE=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
+github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
+github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
+github.com/onsi/gomega v1.24.0 h1:+0glovB9Jd6z3VR+ScSwQqXVTIfJcGA9UBM8yzQxhqg=
+github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
+github.com/openconfig/gnmi v0.0.0-20190823184014-89b2bf29312c/go.mod h1:t+O9It+LKzfOAhKTT5O0ehDix+MTqbtT0T9t+7zzOvc=
+github.com/openconfig/reference v0.0.0-20190727015836-8dfd928c9696/go.mod h1:ym2A+zigScwkSEb/cVQB0/ZMpU3rqiH6X7WRRsxgOGw=
+github.com/opencontainers/runtime-spec v1.0.2 h1:UfAcuLBJB9Coz72x1hgl8O5RVzTdNiaglX6v2DM6FI0=
+github.com/opencontainers/runtime-spec v1.0.2/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
+github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis=
+github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74=
github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/opentracing/opentracing-go v1.0.3-0.20180606204148-bd9c31933947/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
-github.com/opentracing/opentracing-go v1.1.0 h1:pWlfV3Bxv7k65HYwkikxat0+s3pV4bsqf19k25Ur8rU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
+github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs=
+github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc=
+github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA=
+github.com/openzipkin/zipkin-go v0.1.1/go.mod h1:NtoC/o8u3JlF1lSlyPNswIbeQH9bJTmOf0Erfk+hxe8=
+github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw=
+github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
+github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4=
+github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM=
github.com/panjf2000/ants/v2 v2.4.5 h1:kcGvjXB7ea0MrzzszpnlVFthhYKoFxLi75nRbsq01HY=
github.com/panjf2000/ants/v2 v2.4.5/go.mod h1:f6F0NZVFsGCp5A7QW/Zj/m92atWwOkY0OIhFxRNFr4A=
+github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
+github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
+github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/paulbellamy/ratecounter v0.2.0/go.mod h1:Hfx1hDpSGoqxkVVpBi/IlYD7kChlfo5C6hzIHwPqfFE=
+github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0=
+github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y=
+github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
+github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
+github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac=
+github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/peterh/liner v1.0.1-0.20180619022028-8c1271fcf47f/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
-github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7 h1:oYW+YCJ1pachXTQmzR3rNLYGGz4g/UgFcjb28p/viDM=
-github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
+github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg=
+github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0=
github.com/philhofer/fwd v1.0.0/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
+github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc=
github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pierrec/lz4 v2.4.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY=
+github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
+github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA=
+github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18=
github.com/pkg/term v0.0.0-20180730021639-bffc007b7fd5/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
+github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
+github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
+github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs=
+github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo=
+github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og=
+github.com/prometheus/client_golang v1.4.1/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU=
github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M=
-github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0=
-github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY=
+github.com/prometheus/client_golang v1.9.0/go.mod h1:FqZLKOZnGdFAhOK4nqGHa7D66IdsO+O441Eve7ptJDU=
github.com/prometheus/client_golang v1.14.0 h1:nJdhIvne2eSX/XRAFV9PcvFFRbrjbcTUj0VP62TMhnw=
github.com/prometheus/client_golang v1.14.0/go.mod h1:8vpkKitgIVNcqrRBWh1C4TIUQgYNtG/XQE4E/Zae36Y=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
+github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
+github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.3.0 h1:UBgGFHqYdG/TPFD1B1ogZywDqEkwp3fBMvqdiQ7Xew4=
github.com/prometheus/client_model v0.3.0/go.mod h1:LDGWKZIo7rky3hgvBe+caln+Dr3dPggB5dvjtD7w9+w=
+github.com/prometheus/common v0.0.0-20180801064454-c7de2306084e/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
+github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
+github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.6.0/go.mod h1:eBmuwkDJBwy6iBfxCBob6t6dR6ENT/y+J+Zk0j9GMYc=
+github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA=
+github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo=
-github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc=
-github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls=
-github.com/prometheus/common v0.37.0 h1:ccBbHCgIiT9uSoFY0vX8H3zsNR5eLt17/RQLUvn8pXE=
-github.com/prometheus/common v0.37.0/go.mod h1:phzohg0JFMnBEFGxTDbfu3QyL5GI8gTQJFhYO5B3mfA=
+github.com/prometheus/common v0.15.0/go.mod h1:U+gB1OBLb1lF3O42bTCL+FK18tX9Oar16Clt/msog/s=
+github.com/prometheus/common v0.39.0 h1:oOyhkDq05hPZKItWVBkJ6g6AtGxi+fy7F4JvUV8uhsI=
+github.com/prometheus/common v0.39.0/go.mod h1:6XBZ7lYdLCbkAVhwRsWTZn+IN5AB9F/NXd5w0BbEX0Y=
+github.com/prometheus/procfs v0.0.0-20180725123919-05ee40e3a273/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
+github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
+github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
+github.com/prometheus/procfs v0.0.10/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
-github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA=
-github.com/prometheus/procfs v0.8.0 h1:ODq8ZFEaYeCaZOJlZZdJA2AbQR98dSHSM1KW/You5mo=
-github.com/prometheus/procfs v0.8.0/go.mod h1:z7EfXMXOkbkqb9IINtpCn86r/to3BnA0uaxHdg830/4=
-github.com/prometheus/tsdb v0.7.1 h1:YZcsG11NqnK4czYLrWd9mpEuAJIHVQLwdrleYfszMAA=
+github.com/prometheus/procfs v0.2.0/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU=
+github.com/prometheus/procfs v0.9.0 h1:wzCHvIvM5SxWqYvwgVL7yJY8Lz3PKn49KQtpgMYJfhI=
+github.com/prometheus/procfs v0.9.0/go.mod h1:+pB4zwohETzFnmlpe6yd2lSc+0/46IYZRB/chUwxUZY=
+github.com/prometheus/prom2json v1.3.0 h1:BlqrtbT9lLH3ZsOVhXPsHzFrApCTKRifB7gjJuypu6Y=
+github.com/prometheus/prom2json v1.3.0/go.mod h1:rMN7m0ApCowcoDlypBHlkNbp5eJQf/+1isKykIP5ZnM=
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
+github.com/prometheus/tsdb v0.10.0 h1:If5rVCMTp6W2SiRAQFlbpJNgVlgMEd+U2GZckwK38ic=
+github.com/prometheus/tsdb v0.10.0/go.mod h1:oi49uRhEe9dPUTlS3JRZOwJuVi6tmh10QSgwXEyGCt4=
+github.com/prysmaticlabs/fastssz v0.0.0-20220628121656-93dfe28febab h1:Y3PcvUrnneMWLuypZpwPz8P70/DQsz6KgV9JveKpyZs=
+github.com/prysmaticlabs/fastssz v0.0.0-20220628121656-93dfe28febab/go.mod h1:MA5zShstUwCQaE9faGHgCGvEWUbG87p4SAXINhmCkvg=
+github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7 h1:0tVE4tdWQK9ZpYygoV7+vS6QkDvQVySboMVEIxBJmXw=
+github.com/prysmaticlabs/go-bitfield v0.0.0-20210809151128-385d8c5e3fb7/go.mod h1:wmuf/mdK4VMD+jA9ThwcUKjg3a2XWM9cVfFYjDyY4j4=
+github.com/prysmaticlabs/gohashtree v0.0.2-alpha h1:hk5ZsDQuSkyUMhTd55qB396P1+dtyIKiSwMmYE/hyEU=
+github.com/prysmaticlabs/gohashtree v0.0.2-alpha/go.mod h1:4pWaT30XoEx1j8KNJf3TV+E3mQkaufn7mf+jRNb/Fuk=
+github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1 h1:xcu59yYL6AWWTl6jtejBfE0y8uF35fArCBeZjRlvJss=
+github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1/go.mod h1:IOyTYjcIO0rkmnGBfJTL0NJ11exy/Tc2QEuv7hCXp24=
+github.com/prysmaticlabs/prombbolt v0.0.0-20210126082820-9b7adba6db7c h1:9PHRCuO/VN0s9k+RmLykho7AjDxblNYI5bYKed16NPU=
+github.com/prysmaticlabs/prombbolt v0.0.0-20210126082820-9b7adba6db7c/go.mod h1:ZRws458tYHS/Zs936OQ6oCrL+Ict5O4Xpwve1UQ6C9M=
+github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294 h1:q9wE0ZZRdTUAAeyFP/w0SwBEnCqlVy2+on6X2/e+eAU=
+github.com/prysmaticlabs/prysm/v3 v3.2.2 h1:8lC6vX4F/gVPVOrOZ49SkHjxZIpl0XLziIvlFKdyLwA=
+github.com/prysmaticlabs/prysm/v3 v3.2.2/go.mod h1:tk/LvCJpiq/EpMPkSJwE0OYBLnXOiMktEN+Xt1IIKkE=
+github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc h1:zAsgcP8MhzAbhMnB1QQ2O7ZhWYVGYSR2iVcjzQuPV+o=
+github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc/go.mod h1:S8xSOnV3CgpNrWd0GQ/OoQfMtlg2uPRSuTzcSGrzwK8=
+github.com/raulk/go-watchdog v1.3.0 h1:oUmdlHxdkXRJlwfG0O9omj8ukerm8MEQavSiDTEtBsk=
+github.com/raulk/go-watchdog v1.3.0/go.mod h1:fIvOnLbF0b0ZwkB9YU4mOW9Did//4vPZtDqv66NfsMU=
+github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563 h1:dY6ETXrvDG7Sa4vE8ZQG4yqWg6UnOcbqTAahkV813vQ=
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
+github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
+github.com/rivo/uniseg v0.3.4 h1:3Z3Eu6FGHZWSfNKJTOUiPatWwfc7DzJRU04jFUqJODw=
+github.com/rivo/uniseg v0.3.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
+github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg=
+github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
+github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
+github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
+github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
+github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
+github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
+github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
+github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
+github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E=
+github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
+github.com/schollz/progressbar/v3 v3.3.4 h1:nMinx+JaEm/zJz4cEyClQeAw5rsYSB5th3xv+5lV6Vg=
+github.com/schollz/progressbar/v3 v3.3.4/go.mod h1:Rp5lZwpgtYmlvmGo1FyDwXMqagyRBQYSDwzlP9QDu84=
+github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/segmentio/kafka-go v0.1.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/segmentio/kafka-go v0.2.0/go.mod h1:X6itGqS9L4jDletMsxZ7Dz+JFWxM6JHfPOCvTvk+EJo=
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
+github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
+github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
+github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
+github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
+github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
+github.com/shurcooL/gofontwoff v0.0.0-20180329035133-29b52fc0a18d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
+github.com/shurcooL/gopherjslib v0.0.0-20160914041154-feb6d3990c2c/go.mod h1:8d3azKNyqcHP1GaQE/c6dDgjkgSx2BZ4IoEi4F1reUI=
+github.com/shurcooL/highlight_diff v0.0.0-20170515013008-09bb4053de1b/go.mod h1:ZpfEhSmds4ytuByIcDnOLkTHGUI6KNqRNPDLHDk+mUU=
+github.com/shurcooL/highlight_go v0.0.0-20181028180052-98c3abbbae20/go.mod h1:UDKB5a1T23gOMUJrI+uSuH0VRDStOiUVSjBTRDVBVag=
+github.com/shurcooL/home v0.0.0-20181020052607-80b7ffcb30f9/go.mod h1:+rgNQw2P9ARFAs37qieuu7ohDNQ3gds9msbT2yn85sg=
+github.com/shurcooL/htmlg v0.0.0-20170918183704-d01228ac9e50/go.mod h1:zPn1wHpTIePGnXSHpsVPWEktKXHr6+SS6x/IKRb7cpw=
+github.com/shurcooL/httperror v0.0.0-20170206035902-86b7830d14cc/go.mod h1:aYMfkZ6DWSJPJ6c4Wwz3QtW22G7mf/PEgaB9k/ik5+Y=
+github.com/shurcooL/httpfs v0.0.0-20171119174359-809beceb2371/go.mod h1:ZY1cvUeJuFPAdZ/B6v7RHavJWZn2YPVFQ1OSXhCGOkg=
+github.com/shurcooL/httpgzip v0.0.0-20180522190206-b1c53ac65af9/go.mod h1:919LwcH0M7/W4fcZ0/jy0qGght1GIhqyS/EgWGH2j5Q=
+github.com/shurcooL/issues v0.0.0-20181008053335-6292fdc1e191/go.mod h1:e2qWDig5bLteJ4fwvDAc2NHzqFEthkqn7aOZAOpj+PQ=
+github.com/shurcooL/issuesapp v0.0.0-20180602232740-048589ce2241/go.mod h1:NPpHK2TI7iSaM0buivtFUc9offApnI0Alt/K8hcHy0I=
+github.com/shurcooL/notifications v0.0.0-20181007000457-627ab5aea122/go.mod h1:b5uSkrEVM1jQUspwbixRBhaIjIzL2xazXp6kntxYle0=
+github.com/shurcooL/octicon v0.0.0-20181028054416-fa4f57f9efb2/go.mod h1:eWdoE5JD4R5UVWDucdOPg1g2fqQRq78IQa9zlOV1vpQ=
+github.com/shurcooL/reactions v0.0.0-20181006231557-f2e0b4ca5b82/go.mod h1:TCR1lToEk4d2s07G3XGfz2QrgHXg4RJBvjrOozvoWfk=
+github.com/shurcooL/sanitized_anchor_name v0.0.0-20170918181015-86672fcb3f95/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
+github.com/shurcooL/users v0.0.0-20180125191416-49c67e49c537/go.mod h1:QJTqeLYEDaXHZDBsXlPCDqdhQuJkuw4NOtaxYe3xii4=
+github.com/shurcooL/webdavfs v0.0.0-20170829043945-18c3829fa133/go.mod h1:hKmq5kWdCj2z2KEozexVbfEZIWiTjhE0+UjmZgPqehw=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
+github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
+github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
+github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
+github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
+github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY=
+github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:UdhH50NIW0fCiwBSr0co2m7BnFLdv4fQTgdqdJTHFeE=
+github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
+github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572 h1:RC6RW7j+1+HkWaX/Yh71Ee5ZHaHYt7ZP4sQgUrm6cDU=
+github.com/spacemonkeygo/spacelog v0.0.0-20180420211403-2296661a0572/go.mod h1:w0SWMsp6j9O/dk4/ZpIhL+3CkG8ofA2vuv7k+ltqUMc=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
+github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
+github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
+github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
+github.com/spf13/cobra v1.0.1-0.20201006035406-b97b5ead31f7/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ=
+github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
+github.com/spf13/pflag v0.0.0-20170130214245-9ff6c6923cff/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
+github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
-github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4 h1:Gb2Tyox57NRNuZ2d3rmvB3pcmbu7O1RS3m8WRx7ilrg=
-github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4/go.mod h1:RZLeN1LMWmRsyYjvAu+I6Dm9QmlDaIIt+Y+4Kd7Tp+Q=
+github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
+github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
+github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
+github.com/status-im/keycard-go v0.2.0 h1:QDLFswOQu1r5jsycloeQh3bVU8n/NatHHaZobtDnDzA=
+github.com/status-im/keycard-go v0.2.0/go.mod h1:wlp8ZLbsmrF6g6WjugPAx+IzoLrkdf9+mHxBEeo3Hbg=
+github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
+github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw=
+github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
@@ -491,57 +1056,162 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
+github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
+github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
-github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY=
-github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc=
+github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
+github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344 h1:m+8fKfQwCAy1QjzINvKe/pYtLjo2dl59x2w9YSEJxuY=
+github.com/supranational/blst v0.3.8-0.20220526154634-513d2456b344/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
+github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
+github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d/go.mod h1:RRCYJbIwD5jmqPI9XoAFR0OcDxqUctll6zUj/+B4S48=
+github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=
+github.com/templexxx/cpufeat v0.0.0-20180724012125-cef66df7f161/go.mod h1:wM7WEvslTq+iOEAMDLSzhVuOt5BRZ05WirO+b09GHQU=
+github.com/templexxx/xor v0.0.0-20191217153810-f85b25db303b/go.mod h1:5XA7W9S6mni3h5uvOC75dA3m9CCCaS83lltmc0ukdi4=
github.com/tendermint/go-amino v0.14.1 h1:o2WudxNfdLNBwMyl2dqOJxiro5rfrEaU0Ugs6offJMk=
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
github.com/tendermint/iavl v0.12.0 h1:xcaFAr+ycqCj7WN1RzL2EfcBioRDOHcU1oWcg83K028=
github.com/tendermint/iavl v0.12.0/go.mod h1:EoKMMv++tDOL5qKKVnoIqtVPshRrEPeJ0WsgDOLAauM=
+github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e h1:cR8/SYRgyQCt5cNCMniB/ZScMkhI9nk8U5C7SbISXjo=
+github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e/go.mod h1:Tu4lItkATkonrYuvtVjG0/rhy15qrNGNTjPdaphtZ/8=
+github.com/tidwall/gjson v1.10.2 h1:APbLGOM0rrEkd8WBw9C24nllro4ajFuJu0Sc9hRz8Bo=
+github.com/tidwall/gjson v1.10.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
+github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
+github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
+github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
+github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
+github.com/tidwall/tinylru v1.1.0 h1:XY6IUfzVTU9rpwdhKUF6nQdChgCdGjkMfLzbWyiau6I=
+github.com/tidwall/tinylru v1.1.0/go.mod h1:3+bX+TJ2baOLMWTnlyNWHh4QMnFyARg2TLTQ6OFbzw8=
+github.com/tidwall/wal v1.1.7 h1:emc1TRjIVsdKKSnpwGBAcsAGg0767SvUk8+ygx7Bb+4=
+github.com/tidwall/wal v1.1.7/go.mod h1:r6lR1j27W9EPalgHiB7zLJDYu3mzW5BQP5KrzBpYY/E=
github.com/tinylib/msgp v1.0.2/go.mod h1:+d+yLhGm8mzTaHzB+wgMYrodPfmZrzkirds8fDWklFE=
-github.com/tklauser/go-sysconf v0.3.5 h1:uu3Xl4nkLzQfXNsWn15rPc/HQCJKObbt1dKJeWp3vU4=
-github.com/tklauser/go-sysconf v0.3.5/go.mod h1:MkWzOF4RMCshBAMXuhXJs64Rte09mITnppBXY/rYEFI=
-github.com/tklauser/numcpus v0.2.2 h1:oyhllyrScuYI6g+h/zUvNXNp1wy7x8qQy3t/piefldA=
-github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZFu0T9wgjM=
-github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
-github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
+github.com/tjfoc/gmsm v1.3.0/go.mod h1:HaUcFuY0auTiaHB9MHFGCPx5IaLhTUd2atbCFBQXn9w=
+github.com/tklauser/go-sysconf v0.3.10 h1:IJ1AZGZRWbY8T5Vfk04D9WOA5WSejdflXxP03OUqALw=
+github.com/tklauser/go-sysconf v0.3.10/go.mod h1:C8XykCvCb+Gn0oNCWPIlcb0RuglQTYaQ2hGm7jmxEFk=
+github.com/tklauser/numcpus v0.4.0/go.mod h1:1+UI3pD8NW14VMwdgJNJ1ESk2UnwhAnz5hMwiKKqXCQ=
+github.com/tklauser/numcpus v0.5.0 h1:ooe7gN0fg6myJ0EKoTAf5hebTZrH52px3New/D9iJ+A=
+github.com/tklauser/numcpus v0.5.0/go.mod h1:OGzpTxpcIMNGYQdit2BYL1pvk/dSOaJWjKoflh+RQjo=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
+github.com/trailofbits/go-mutexasserts v0.0.0-20200708152505-19999e7d3cef h1:8LRP+2JK8piIUU16ZDgWDXwjJcuJNTtCzadjTZj8Jf0=
+github.com/trailofbits/go-mutexasserts v0.0.0-20200708152505-19999e7d3cef/go.mod h1:+SV/613m53DNAmlXPTWGZhIyt4E/qDvn9g/lOPRiy0A=
+github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A=
+github.com/tyler-smith/go-bip39 v1.1.0 h1:5eUemwrMargf3BSLRRCalXT93Ns6pQJIjYQN2nyfOP8=
+github.com/tyler-smith/go-bip39 v1.1.0/go.mod h1:gUYDtqQw1JS3ZJ8UWVcGTGqqr6YIN3CWg+kkNaLt55U=
+github.com/uber/jaeger-client-go v2.25.0+incompatible h1:IxcNZ7WRY1Y3G4poYlx24szfsn/3LvK9QHCq9oQw8+U=
+github.com/uber/jaeger-client-go v2.25.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk=
+github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
+github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
+github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
+github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa h1:5SqCsI/2Qya2bCzK15ozrqo2sZxkh0FHynJZOTVoV6Q=
+github.com/urfave/cli/v2 v2.17.2-0.20221006022127-8f469abc00aa/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
+github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
+github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
+github.com/wealdtech/go-bytesutil v1.1.1 h1:ocEg3Ke2GkZ4vQw5lp46rmO+pfqCCTgq35gqOy8JKVc=
+github.com/wealdtech/go-bytesutil v1.1.1/go.mod h1:jENeMqeTEU8FNZyDFRVc7KqBdRKSnJ9CCh26TcuNb9s=
+github.com/wealdtech/go-eth2-types/v2 v2.5.2 h1:tiA6T88M6XQIbrV5Zz53l1G5HtRERcxQfmET225V4Ls=
+github.com/wealdtech/go-eth2-types/v2 v2.5.2/go.mod h1:8lkNUbgklSQ4LZ2oMSuxSdR7WwJW3L9ge1dcoCVyzws=
+github.com/wealdtech/go-eth2-util v1.6.3 h1:2INPeOR35x5LdFFpSzyw954WzTD+DFyHe3yKlJnG5As=
+github.com/wealdtech/go-eth2-util v1.6.3/go.mod h1:0hFMj/qtio288oZFHmAbCnPQ9OB3c4WFzs5NVPKTY4k=
+github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3 h1:SxrDVSr+oXuT1x8kZt4uWqNCvv5xXEGV9zd7cuSrZS8=
+github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3/go.mod h1:qiIimacW5NhVRy8o+YxWo9YrecXqDAKKbL0+sOa0SJ4=
+github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.2 h1:264/meVYWt1wFw6Mtn+xwkZkXjID42gNra4rycoiDXI=
+github.com/wealdtech/go-eth2-wallet-types/v2 v2.8.2/go.mod h1:k6kmiKWSWBTd4OxFifTEkPaBLhZspnO2KFD5XJY9nqg=
+github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee h1:lYbXeSvJi5zk5GLKVuid9TVjS9a0OmLIDKTfoZBL6Ow=
+github.com/whyrusleeping/timecache v0.0.0-20160911033111-cfcb2f1abfee/go.mod h1:m2aV4LZI4Aez7dP5PMyVKEHhUyEJ/RjmPEDOpDvudHg=
+github.com/willf/bitset v1.1.3 h1:ekJIKh6+YbUIVt9DfNbkR5d6aFcFTLDRyJNAACURBg8=
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
+github.com/xdg/scram v0.0.0-20180814205039-7eeb5667e42c/go.mod h1:lB8K/P019DLNhemzwFU4jHLhdvlE6uDZjXFejJXr49I=
+github.com/xdg/stringprep v1.0.0/go.mod h1:Jhud4/sHMO4oL310DaZAKk9ZaJ08SJfe+sJh0HrGL1Y=
+github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
+github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
+github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
+github.com/xtaci/kcp-go v5.4.20+incompatible/go.mod h1:bN6vIwHQbfHaHtFpEssmWsN45a+AZwO7eyRCmEIbtvE=
+github.com/xtaci/lossyconn v0.0.0-20190602105132-8df528c0c9ae/go.mod h1:gXtu8J62kEgmN++bm9BVICuT/e8yiLI2KFobd/TRFsE=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
+go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
+go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
go.etcd.io/bbolt v1.3.7 h1:j+zJOnnEjF/kyHlDDgGnVL/AIqIJPq8UoB2GSNfkUfQ=
go.etcd.io/bbolt v1.3.7/go.mod h1:N9Mkw9X8x5fupy0IKsmuqVtoGDyxsaDlbk4Rd05IAQw=
+go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
+go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
+go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
+go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
+go.opencensus.io v0.22.6/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
+go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
+go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
+go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
+go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ=
+go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
+go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
+go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
+go.uber.org/dig v1.15.0 h1:vq3YWr8zRj1eFGC7Gvf907hE0eRjPTZ1d3xHadD6liE=
+go.uber.org/dig v1.15.0/go.mod h1:pKHs0wMynzL6brANhB2hLMro+zalv1osARTviTcqHLM=
+go.uber.org/fx v1.18.2 h1:bUNI6oShr+OVFQeU8cDNbnN7VFsu+SsjHzUF51V/GAU=
+go.uber.org/fx v1.18.2/go.mod h1:g0V1KMQ66zIRk8bLu3Ea5Jt2w/cHlOIp4wdRsgh0JaY=
+go.uber.org/goleak v1.1.11-0.20210813005559-691160354723/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
+go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
+go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4=
+go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU=
+go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
+go.uber.org/multierr v1.8.0 h1:dg6GjLku4EH+249NNmoIciG9N/jURbDG+pFlTkhzIC8=
+go.uber.org/multierr v1.8.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak=
+go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA=
go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
+go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
+go.uber.org/zap v1.16.0/go.mod h1:MA8QOfq0BHJwdXa996Y4dYkAqRKB8/1K1QMMZVaNZjQ=
+go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI=
+go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
+go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
+go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
+golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20181030102418-4d3f4d9ffa16/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
+golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
+golang.org/x/crypto v0.0.0-20190313024323-a1f597ede03a/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191219195013-becbf705a915/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
+golang.org/x/crypto v0.0.0-20200602180216-279210d13fed/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@@ -557,9 +1227,13 @@ golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u0
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
+golang.org/x/exp v0.0.0-20200331195152-e8c3332aa8e5/go.mod h1:4M0jN8W1tt0AVLNr8HDosyJCDCDuyL9N9+3m7wDWgKw=
+golang.org/x/exp v0.0.0-20230206171751-46f607a40771 h1:xP7rWLUr1e1n2xkK5YB4LI0hPEy3LJC6Wk+D4pGlOJg=
+golang.org/x/exp v0.0.0-20230206171751-46f607a40771/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
+golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@@ -570,6 +1244,8 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
+golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
@@ -579,15 +1255,24 @@ golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzB
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
-golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
+golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
+golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
+golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
+golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
+golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -596,6 +1281,9 @@ golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/net v0.0.0-20191116160921-f9c825593386/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -603,6 +1291,7 @@ golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
+golang.org/x/net v0.0.0-20200421231249-e086a090c8fd/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
@@ -610,24 +1299,33 @@ golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
-golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210220033124-5f55cee0dc0d/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
-golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
+golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
+golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
+golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
-golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
-golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
+golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
+golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
+golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
+golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
-golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
-golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc=
+golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
+golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8=
+golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
+golang.org/x/perf v0.0.0-20180704124530-6e6d33e29852/go.mod h1:JLpeXjPJfIyPr5TlbXLkXWLhP8nz10XfvxElABhCtcw=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
@@ -637,18 +1335,28 @@ golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180810173357-98c5dad5d1a0/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190130150945-aca44879d564/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
+golang.org/x/sys v0.0.0-20190228124157-a34e9553db1e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190405154228-4b34438f7a67/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -657,54 +1365,76 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191022100944-742c48ecaeb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200219091948-cb0a6d8edb6c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200420163511-1957bb5e6d1f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200826173525-f9321e4c35a6/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201214210602-f9fddec55a1e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
-golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
-golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220128215802-99c3d69c2c27/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220405052023-b1e9470b6e64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220503163025-988cb79eb6c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
+golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
-golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
-golang.org/x/term v0.4.0/go.mod h1:9P2UbLfCdcvo3p/nzKvsmas4TnlujnuoV9hGgYzW1lQ=
+golang.org/x/term v0.5.0 h1:n2a8QNdAb0sZNpU9R1ALUXBbY+w51fCQDN+7EdxNBsY=
+golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
+golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -714,16 +1444,22 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
-golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
-golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
+golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
+golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
-golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba h1:O8mE0/t419eoIwhTFpKVkHiTs/Igowgfkj25AcZrtiE=
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/time v0.0.0-20220922220347-f3bd1da661af h1:Yx9k8YCG3dvF87UAn2tu2HQLf2dt/eR1bXxpLMWeH+Y=
+golang.org/x/time v0.0.0-20220922220347-f3bd1da661af/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
+golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181011042414-1f849cf54d09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
+golang.org/x/tools v0.0.0-20181030000716-a0a13e073c7b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190206041539-40960b6deb8e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
@@ -741,6 +1477,9 @@ golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgw
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -748,6 +1487,7 @@ golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200108203644-89082a384178/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
@@ -755,6 +1495,7 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
+golang.org/x/tools v0.0.0-20200221224223-e1da425f72fd/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
@@ -763,26 +1504,38 @@ golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWc
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
+golang.org/x/tools v0.0.0-20200717024301-6ddee64345a6/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
+golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
+golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
-golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
-golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
+golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
+golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
-golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.0.0-20181121035319-3f7ecaa7e8ca/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
gonum.org/v1/gonum v0.6.0/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
gonum.org/v1/netlib v0.0.0-20181029234149-ec6d1f5cefe6/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc=
+google.golang.org/api v0.0.0-20180910000450-7ca32eb868bf/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.0.0-20181030000543-1d582fd0359e/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0=
+google.golang.org/api v0.1.0/go.mod h1:UGEZY7KEX120AnNLIHFMKIo4obdJhkp2tPbaPlQx13Y=
+google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
@@ -799,17 +1552,28 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
+google.golang.org/api v0.34.0 h1:k40adF3uR+6x/+hO5Dh4ZFUqFp67vxvbpafFiJxl10A=
+google.golang.org/api v0.34.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
+google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
+google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
+google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6c=
+google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20181029155118-b69ba1387ce2/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
+google.golang.org/genproto v0.0.0-20181202183823-bd91e49a0898/go.mod h1:7Ep/1NZk928CDR8SjdVbjWNpdIf6nzjE3BTgJDr2Atg=
+google.golang.org/genproto v0.0.0-20190306203927-b5d61aea6440/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
+google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
google.golang.org/genproto v0.0.0-20190716160619-c506a9f90610/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
@@ -823,24 +1587,38 @@ google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvx
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200218151345-dad8c97a84f5/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200423170343-7949de9c1215/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
+google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
-google.golang.org/genproto v0.0.0-20200825200019-8632dd797987 h1:PDIOdWxZ8eRizhKa1AAvY53xsvLB1cWorMjslvY3VA8=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210207032614-bba0dbe2a9ea/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
+google.golang.org/genproto v0.0.0-20210426193834-eac7f76ac494/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
+google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84 h1:R1r5J0u6Cx+RNl/6mezTw6oA14cmKC96FeUwL6A9bd4=
+google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
+google.golang.org/grpc v1.14.0/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw=
+google.golang.org/grpc v1.16.0/go.mod h1:0JHn/cJsOMiMfNA9+DeHDlAU7KAAB5GDlYFpa9MZMio=
+google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
+google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
+google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
+google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
+google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
@@ -848,8 +1626,18 @@ google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
-google.golang.org/grpc v1.31.0 h1:T7P4R73V3SSDPhH7WW7ATbfViLtmamH0DKrP3f9AuDI=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
+google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
+google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
+google.golang.org/grpc v1.35.0-dev.0.20201218190559-666aea1fb34c/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
+google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
+google.golang.org/grpc v1.40.0 h1:AGJ0Ih4mHjSeibYkFGh1dD9KJ/eOtZ93I6hoHhukQ5Q=
+google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
+google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
@@ -860,24 +1648,44 @@ google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.25.1-0.20200805231151-a709e31e5d12/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
+google.golang.org/protobuf v1.25.1-0.20201208041424-160c7477e0e8/go.mod h1:hFxJC2f0epmp1elRCiEGJTKAWbwxZ2nvqZdHl3FQXCY=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
+gopkg.in/bsm/ratelimit.v1 v1.0.0-20160220154919-db14e161995a/go.mod h1:KF9sEfUPAXdG8Oev9e99iLGnl2uJMjc5B+4y3O7x610=
+gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y=
+gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
+gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
+gopkg.in/d4l3k/messagediff.v1 v1.2.1 h1:70AthpjunwzUiarMHyED52mj9UwtAnE89l1Gmrt3EU0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
+gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o=
+gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
+gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
+gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
+gopkg.in/jcmturner/aescts.v1 v1.0.1/go.mod h1:nsR8qBOg+OucoIW+WMhB3GspUQXq9XorLnQb9XtvcOo=
+gopkg.in/jcmturner/dnsutils.v1 v1.0.1/go.mod h1:m3v+5svpVOhtFAP/wSz+yzh4Mc0Fg7eRhxkJMWSIz9Q=
+gopkg.in/jcmturner/goidentity.v3 v3.0.0/go.mod h1:oG2kH0IvSYNIu80dVAyu/yoefjq1mNfM5bm88whjWx4=
+gopkg.in/jcmturner/gokrb5.v7 v7.5.0/go.mod h1:l8VISx+WGYp+Fp7KRbsiUuXTTOnxIc3Tuvyavf11/WM=
+gopkg.in/jcmturner/rpc.v1 v1.1.0/go.mod h1:YIdkC4XfD6GXbzje11McwsDuOlZQSb9W4vfLvuNnlv8=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
+gopkg.in/redis.v4 v4.2.4/go.mod h1:8KREHdypkCEojGKQcjMqAODMICIVwZAONWq8RowTITA=
+gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
+gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI=
+gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -889,8 +1697,11 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
+grpc.go4.org v0.0.0-20170609214715-11d0a25b4919/go.mod h1:77eQGdRu53HpSqPFJFmuJdjuHRquDANNeA4x7B8WQ9o=
+honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
@@ -899,7 +1710,36 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.1.3/go.mod h1:NgwopIslSNH47DimFoV78dnkksY2EFtX0ajyb3K/las=
+k8s.io/api v0.18.3 h1:2AJaUQdgUZLoDZHrun21PW2Nx9+ll6cUzvn3IKhSIn0=
+k8s.io/api v0.18.3/go.mod h1:UOaMwERbqJMfeeeHc8XJKawj4P9TgDRnViIqqBeH2QA=
+k8s.io/apimachinery v0.18.3 h1:pOGcbVAhxADgUYnjS08EFXs9QMl8qaH5U4fr5LGUrSk=
+k8s.io/apimachinery v0.18.3/go.mod h1:OaXp26zu/5J7p0f92ASynJa1pZo06YlV9fG7BoWbCko=
+k8s.io/client-go v0.18.3 h1:QaJzz92tsN67oorwzmoB0a9r9ZVHuD5ryjbCKP0U22k=
+k8s.io/client-go v0.18.3/go.mod h1:4a/dpQEvzAhT1BbuWW09qvIaGw6Gbu1gZYiQZIi1DMw=
+k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
+k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
+k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
+k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
+k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
+k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
+k8s.io/klog/v2 v2.80.0 h1:lyJt0TWMPaGoODa8B8bUuxgHS3W/m/bNr2cca3brA/g=
+k8s.io/klog/v2 v2.80.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
+k8s.io/kube-openapi v0.0.0-20200410145947-61e04a5be9a6/go.mod h1:GRQhZsXIAJ1xR0C9bd8UpWHZ5plfAS9fzPjJuQ6JL3E=
+k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
+k8s.io/utils v0.0.0-20200520001619-278ece378a50 h1:ZtTUW5+ZWaoqjR3zOpRa7oFJ5d4aA22l4me/xArfOIc=
+k8s.io/utils v0.0.0-20200520001619-278ece378a50/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
+lukechampine.com/blake3 v1.1.7 h1:GgRMhmdsuK8+ii6UZFDL8Nb+VyMwadAgcJyfYHxG6n0=
+lukechampine.com/blake3 v1.1.7/go.mod h1:tkKEOtDkNtklkXtLNEOGNq5tcV90tJiA1vAA12R78LA=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=
+sigs.k8s.io/structured-merge-diff/v3 v3.0.0-20200116222232-67a7b8c61874/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
+sigs.k8s.io/structured-merge-diff/v3 v3.0.0 h1:dOmIZBMfhcHS09XZkMyUgkq5trg3/jRyJYFZUiaOp8E=
+sigs.k8s.io/structured-merge-diff/v3 v3.0.0/go.mod h1:PlARxl6Hbt/+BC80dRLi1qAmnMqwqDg62YvvVkZjemw=
+sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
+sigs.k8s.io/yaml v1.2.0 h1:kr/MCeFWJWTwyaHoR9c8EjH9OumOmoF9YGiZd7lFm/Q=
+sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
+sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
+sourcegraph.com/sourcegraph/go-diff v0.5.0/go.mod h1:kuch7UrkMzY0X+p9CRK03kfuPQ2zzQcaEFbx8wA8rck=
+sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
diff --git a/internal/ethapi/backend.go b/internal/ethapi/backend.go
index 889370440e..244279624b 100644
--- a/internal/ethapi/backend.go
+++ b/internal/ethapi/backend.go
@@ -93,6 +93,8 @@ type Backend interface {
SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscription
SubscribePendingLogsEvent(ch chan<- []*types.Log) event.Subscription
SubscribeRemovedLogsEvent(ch chan<- core.RemovedLogsEvent) event.Subscription
+ SubscribeNewVoteEvent(chan<- core.NewVoteEvent) event.Subscription
+ SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription
ChainConfig() *params.ChainConfig
Engine() consensus.Engine
diff --git a/les/api_backend.go b/les/api_backend.go
index 0e02a03050..e354b19fe6 100644
--- a/les/api_backend.go
+++ b/les/api_backend.go
@@ -36,6 +36,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/light"
+ "github.com/ethereum/go-ethereum/log"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/rpc"
)
@@ -231,6 +232,11 @@ func (b *LesApiBackend) SubscribeNewTxsEvent(ch chan<- core.NewTxsEvent) event.S
return b.eth.txPool.SubscribeNewTxsEvent(ch)
}
+func (b *LesApiBackend) SubscribeNewVoteEvent(ch chan<- core.NewVoteEvent) event.Subscription {
+ log.Error("light ethereum does not support SubscribeNewVoteEvent")
+ return nil
+}
+
func (b *LesApiBackend) SubscribeChainEvent(ch chan<- core.ChainEvent) event.Subscription {
return b.eth.blockchain.SubscribeChainEvent(ch)
}
@@ -239,6 +245,10 @@ func (b *LesApiBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) e
return b.eth.blockchain.SubscribeChainHeadEvent(ch)
}
+func (b *LesApiBackend) SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription {
+ return b.eth.blockchain.SubscribeFinalizedHeaderEvent(ch)
+}
+
func (b *LesApiBackend) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
return b.eth.blockchain.SubscribeChainSideEvent(ch)
}
diff --git a/light/lightchain.go b/light/lightchain.go
index 7ce0b2698d..086b673d30 100644
--- a/light/lightchain.go
+++ b/light/lightchain.go
@@ -50,17 +50,18 @@ var (
// headers, downloading block bodies and receipts on demand through an ODR
// interface. It only does header validation during chain insertion.
type LightChain struct {
- hc *core.HeaderChain
- indexerConfig *IndexerConfig
- chainDb ethdb.Database
- engine consensus.Engine
- odr OdrBackend
- chainFeed event.Feed
- chainSideFeed event.Feed
- chainHeadFeed event.Feed
- scope event.SubscriptionScope
- genesisBlock *types.Block
- forker *core.ForkChoice
+ hc *core.HeaderChain
+ indexerConfig *IndexerConfig
+ chainDb ethdb.Database
+ engine consensus.Engine
+ odr OdrBackend
+ chainFeed event.Feed
+ chainSideFeed event.Feed
+ chainHeadFeed event.Feed
+ finalizedHeaderFeed event.Feed
+ scope event.SubscriptionScope
+ genesisBlock *types.Block
+ forker *core.ForkChoice
bodyCache *lru.Cache // Cache for the most recent block bodies
bodyRLPCache *lru.Cache // Cache for the most recent block bodies in RLP encoded format
@@ -370,6 +371,8 @@ func (lc *LightChain) postChainEvents(events []interface{}) {
lc.chainHeadFeed.Send(core.ChainHeadEvent{Block: ev.Block})
}
lc.chainFeed.Send(ev)
+ case core.FinalizedHeaderEvent:
+ lc.finalizedHeaderFeed.Send(ev)
case core.ChainSideEvent:
lc.chainSideFeed.Send(ev)
}
@@ -456,6 +459,9 @@ func (lc *LightChain) InsertHeaderChain(chain []*types.Header, checkFreq int) (i
case core.CanonStatTy:
lc.chainFeed.Send(core.ChainEvent{Block: block, Hash: block.Hash()})
lc.chainHeadFeed.Send(core.ChainHeadEvent{Block: block})
+ if posa, ok := lc.Engine().(consensus.PoSA); ok {
+ lc.finalizedHeaderFeed.Send(core.FinalizedHeaderEvent{Header: posa.GetFinalizedHeader(lc, block.Header())})
+ }
case core.SideStatTy:
lc.chainSideFeed.Send(core.ChainSideEvent{Block: block})
}
@@ -468,6 +474,19 @@ func (lc *LightChain) CurrentHeader() *types.Header {
return lc.hc.CurrentHeader()
}
+// GetJustifiedNumber returns the highest justified blockNumber on the branch including and before `header`
+func (lc *LightChain) GetJustifiedNumber(header *types.Header) uint64 {
+ if p, ok := lc.engine.(consensus.PoSA); ok {
+ justifiedBlockNumber, _, err := p.GetJustifiedNumberAndHash(lc.hc, header)
+ if err == nil {
+ return justifiedBlockNumber
+ }
+ }
+ // return 0 when err!=nil
+ // so the input `header` will at a disadvantage during reorg
+ return 0
+}
+
// GetTd retrieves a block's total difficulty in the canonical chain from the
// database by hash and number, caching it if found.
func (lc *LightChain) GetTd(hash common.Hash, number uint64) *big.Int {
@@ -588,6 +607,11 @@ func (lc *LightChain) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) eve
return lc.scope.Track(lc.chainHeadFeed.Subscribe(ch))
}
+// SubscribeFinalizedHeaderEvent registers a subscription of FinalizedHeaderEvent.
+func (lc *LightChain) SubscribeFinalizedHeaderEvent(ch chan<- core.FinalizedHeaderEvent) event.Subscription {
+ return lc.scope.Track(lc.finalizedHeaderFeed.Subscribe(ch))
+}
+
// SubscribeChainSideEvent registers a subscription of ChainSideEvent.
func (lc *LightChain) SubscribeChainSideEvent(ch chan<- core.ChainSideEvent) event.Subscription {
return lc.scope.Track(lc.chainSideFeed.Subscribe(ch))
diff --git a/mobile/ethclient.go b/mobile/ethclient.go
index 662125c4ad..59e39e53ec 100644
--- a/mobile/ethclient.go
+++ b/mobile/ethclient.go
@@ -148,6 +148,74 @@ func (ec *EthereumClient) SubscribeNewHead(ctx *Context, handler NewHeadHandler,
return &Subscription{rawSub}, nil
}
+// NewFinalizedHeaderHandler is a client-side subscription callback to invoke on events and
+// subscription failure.
+type NewFinalizedHeaderHandler interface {
+ OnNewFinalizedHeader(header *Header)
+ OnError(failure string)
+}
+
+// SubscribeNewFinalizedHeader subscribes to notifications about the current blockchain finalized header
+// on the given channel.
+func (ec *EthereumClient) SubscribeNewFinalizedHeader(ctx *Context, handler NewFinalizedHeaderHandler, buffer int) (sub *Subscription, _ error) {
+ // Subscribe to the event internally
+ ch := make(chan *types.Header, buffer)
+ rawSub, err := ec.client.SubscribeNewFinalizedHeader(ctx.context, ch)
+ if err != nil {
+ return nil, err
+ }
+ // Start up a dispatcher to feed into the callback
+ go func() {
+ for {
+ select {
+ case header := <-ch:
+ handler.OnNewFinalizedHeader(&Header{header})
+
+ case err := <-rawSub.Err():
+ if err != nil {
+ handler.OnError(err.Error())
+ }
+ return
+ }
+ }
+ }()
+ return &Subscription{rawSub}, nil
+}
+
+// NewVoteHandler is a client-side subscription callback to invoke on events and
+// subscription failure.
+type NewVoteHandler interface {
+ OnNewVote(vote *types.VoteEnvelope)
+ OnError(failure string)
+}
+
+// SubscribeNewVotes subscribes to notifications about the new votes into the vote pool
+// on the given channel.
+func (ec *EthereumClient) SubscribeNewVotes(ctx *Context, handler NewVoteHandler, buffer int) (sub *Subscription, _ error) {
+ // Subscribe to the event internally
+ ch := make(chan *types.VoteEnvelope, buffer)
+ rawSub, err := ec.client.SubscribeNewVotes(ctx.context, ch)
+ if err != nil {
+ return nil, err
+ }
+ // Start up a dispatcher to feed into the callback
+ go func() {
+ for {
+ select {
+ case vote := <-ch:
+ handler.OnNewVote(vote)
+
+ case err := <-rawSub.Err():
+ if err != nil {
+ handler.OnError(err.Error())
+ }
+ return
+ }
+ }
+ }()
+ return &Subscription{rawSub}, nil
+}
+
// State Access
// GetBalanceAt returns the wei balance of the given account.
diff --git a/node/config.go b/node/config.go
index b4f1378c8f..cd87e26362 100644
--- a/node/config.go
+++ b/node/config.go
@@ -204,6 +204,17 @@ type Config struct {
// EnableDoubleSignMonitor is a flag that whether to enable the double signature checker
EnableDoubleSignMonitor bool `toml:",omitempty"`
+
+ // BLSPasswordFile is the file that contains BLS wallet password.
+ BLSPasswordFile string `toml:",omitempty"`
+
+ // BLSWalletDir is the file system folder of BLS wallet. The directory can
+ // be specified as a relative path, in which case it is resolved relative to the
+ // current directory.
+ BLSWalletDir string `toml:",omitempty"`
+
+ // VoteJournalDir is the directory to store votes in the fast finality feature.
+ VoteJournalDir string `toml:",omitempty"`
}
// IPCEndpoint resolves an IPC endpoint based on a configured value, taking into
diff --git a/p2p/discover/v5_udp.go b/p2p/discover/v5_udp.go
index 1e9909559f..f98b8eadd9 100644
--- a/p2p/discover/v5_udp.go
+++ b/p2p/discover/v5_udp.go
@@ -54,7 +54,7 @@ type codecV5 interface {
// Encode encodes a packet.
Encode(enode.ID, string, v5wire.Packet, *v5wire.Whoareyou) ([]byte, v5wire.Nonce, error)
- // decode decodes a packet. It returns a *v5wire.Unknown packet if decryption fails.
+ // Decode decodes a packet. It returns a *v5wire.Unknown packet if decryption fails.
// The *enode.Node return value is non-nil when the input contains a handshake response.
Decode([]byte, string) (enode.ID, *enode.Node, v5wire.Packet, error)
}
diff --git a/p2p/transport.go b/p2p/transport.go
index de9e685ed4..f71fce070c 100644
--- a/p2p/transport.go
+++ b/p2p/transport.go
@@ -136,7 +136,7 @@ func (t *rlpxTransport) doProtoHandshake(our *protoHandshake) (their *protoHands
// Writing our handshake happens concurrently, we prefer
// returning the handshake read error. If the remote side
// disconnects us early with a valid reason, we should return it
- // as the error so it can be tracked elsewhere.
+ // as the error, so it can be tracked elsewhere.
werr := make(chan error, 1)
gopool.Submit(func() { werr <- Send(t, handshakeMsg, our) })
if their, err = readProtocolHandshake(t); err != nil {
diff --git a/params/config.go b/params/config.go
index f4c485f227..afd523a52c 100644
--- a/params/config.go
+++ b/params/config.go
@@ -74,6 +74,58 @@ var (
Ethash: new(EthashConfig),
}
+ // just for prysm compile pass
+ // SepoliaChainConfig contains the chain parameters to run a node on the Sepolia test network.
+ SepoliaChainConfig = &ChainConfig{
+ ChainID: big.NewInt(11155111),
+ 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),
+ MirrorSyncBlock: big.NewInt(0),
+ BrunoBlock: big.NewInt(0),
+ EulerBlock: big.NewInt(0),
+ LondonBlock: big.NewInt(0),
+ Ethash: new(EthashConfig),
+ }
+
+ // just for prysm compile pass
+ // GoerliChainConfig contains the chain parameters to run a node on the Görli test network.
+ GoerliChainConfig = &ChainConfig{
+ ChainID: big.NewInt(5),
+ 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),
+ RamanujanBlock: big.NewInt(0),
+ NielsBlock: big.NewInt(0),
+ MirrorSyncBlock: big.NewInt(0),
+ BrunoBlock: big.NewInt(0),
+ EulerBlock: big.NewInt(0),
+ IstanbulBlock: big.NewInt(1_561_651),
+ MuirGlacierBlock: nil,
+ BerlinBlock: big.NewInt(4_460_644),
+ LondonBlock: big.NewInt(5_062_605),
+ ArrowGlacierBlock: nil,
+ Clique: &CliqueConfig{
+ Period: 15,
+ Epoch: 30000,
+ },
+ }
+
// MainnetTrustedCheckpoint contains the light client trusted checkpoint for the main network.
MainnetTrustedCheckpoint = &TrustedCheckpoint{
SectionIndex: 413,
@@ -116,6 +168,11 @@ var (
GibbsBlock: big.NewInt(23846001),
PlanckBlock: big.NewInt(27281024),
+ // TODO modify blockNumber, make sure the blockNumber is not an integer multiple of 200 (epoch number)
+ // TODO Caution !!! it should be very careful !!!
+ BonehBlock: nil,
+ LynnBlock: nil,
+
Parlia: &ParliaConfig{
Period: 3,
Epoch: 200,
@@ -142,6 +199,12 @@ var (
NanoBlock: big.NewInt(23482428),
MoranBlock: big.NewInt(23603940),
PlanckBlock: big.NewInt(28196022),
+
+ // TODO modify blockNumber, make sure the blockNumber is not an integer multiple of 200 (epoch number)
+ // TODO Caution !!! it should be very careful !!!
+ BonehBlock: nil,
+ LynnBlock: nil,
+
Parlia: &ParliaConfig{
Period: 3,
Epoch: 200,
@@ -169,6 +232,10 @@ var (
MoranBlock: nil,
PlanckBlock: nil,
+ // TODO
+ BonehBlock: nil,
+ LynnBlock: nil,
+
Parlia: &ParliaConfig{
Period: 3,
Epoch: 200,
@@ -180,16 +247,17 @@ var (
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
- AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil}
+
+ AllEthashProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil}
// AllCliqueProtocolChanges contains every protocol change (EIPs) introduced
// and accepted by the Ethereum core developers into the Clique consensus.
//
// This configuration is intentionally not using keyed fields to force anyone
// adding flags to the config to also have to set these fields.
- AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
+ AllCliqueProtocolChanges = &ChainConfig{big.NewInt(1337), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, nil, big.NewInt(0), big.NewInt(0), nil, &CliqueConfig{Period: 0, Epoch: 30000}, nil}
- TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, new(EthashConfig), nil, nil}
+ TestChainConfig = &ChainConfig{big.NewInt(1), big.NewInt(0), nil, false, big.NewInt(0), common.Hash{}, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), big.NewInt(0), nil, nil, big.NewInt(0), big.NewInt(0), new(EthashConfig), nil, nil}
TestRules = TestChainConfig.Rules(new(big.Int), false)
)
@@ -286,6 +354,8 @@ type ChainConfig struct {
NanoBlock *big.Int `json:"nanoBlock,omitempty" toml:",omitempty"` // nanoBlock switch block (nil = no fork, 0 = already activated)
MoranBlock *big.Int `json:"moranBlock,omitempty" toml:",omitempty"` // moranBlock switch block (nil = no fork, 0 = already activated)
PlanckBlock *big.Int `json:"planckBlock,omitempty" toml:",omitempty"` // planckBlock switch block (nil = no fork, 0 = already activated)
+ BonehBlock *big.Int `json:"bonehBlock,omitempty" toml:",omitempty"` // bonehBlock switch block (nil = no fork, 0 = already activated)
+ LynnBlock *big.Int `json:"lynnBlock,omitempty" toml:",omitempty"` // lynnBlock switch block (nil = no fork, 0 = already activated)
// Various consensus engines
Ethash *EthashConfig `json:"ethash,omitempty" toml:",omitempty"`
@@ -336,7 +406,8 @@ func (c *ChainConfig) String() string {
default:
engine = "unknown"
}
- return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v, Engine: %v}",
+
+ return fmt.Sprintf("{ChainID: %v Homestead: %v DAO: %v DAOSupport: %v EIP150: %v EIP155: %v EIP158: %v Byzantium: %v Constantinople: %v Petersburg: %v Istanbul: %v, Muir Glacier: %v, Ramanujan: %v, Niels: %v, MirrorSync: %v, Bruno: %v, Berlin: %v, YOLO v3: %v, CatalystBlock: %v, London: %v, ArrowGlacier: %v, MergeFork:%v, Euler: %v, Gibbs: %v, Nano: %v, Moran: %v, Planck: %v,Boneh: %v, Lynn: %v, Engine: %v}",
c.ChainID,
c.HomesteadBlock,
c.DAOForkBlock,
@@ -364,6 +435,8 @@ func (c *ChainConfig) String() string {
c.NanoBlock,
c.MoranBlock,
c.PlanckBlock,
+ c.BonehBlock,
+ c.LynnBlock,
engine,
)
}
@@ -453,6 +526,26 @@ func (c *ChainConfig) IsOnEuler(num *big.Int) bool {
return configNumEqual(c.EulerBlock, num)
}
+// IsBoneh returns whether num is either equal to the first fast finality fork block or greater.
+func (c *ChainConfig) IsBoneh(num *big.Int) bool {
+ return isForked(c.BonehBlock, num)
+}
+
+// IsOnBoneh returns whether num is equal to the first fast finality fork block.
+func (c *ChainConfig) IsOnBoneh(num *big.Int) bool {
+ return configNumEqual(c.BonehBlock, num)
+}
+
+// IsLynn returns whether num is either equal to the second fast finality fork block or greater.
+func (c *ChainConfig) IsLynn(num *big.Int) bool {
+ return isForked(c.LynnBlock, num)
+}
+
+// IsOnLynn returns whether num is equal to the second fast finality fork block.
+func (c *ChainConfig) IsOnLynn(num *big.Int) bool {
+ return configNumEqual(c.LynnBlock, num)
+}
+
// IsMuirGlacier returns whether num is either equal to the Muir Glacier (EIP-2384) fork block or greater.
func (c *ChainConfig) IsMuirGlacier(num *big.Int) bool {
return isForked(c.MuirGlacierBlock, num)
@@ -559,6 +652,8 @@ func (c *ChainConfig) CheckConfigForkOrder() error {
{name: "brunoBlock", block: c.BrunoBlock},
{name: "eulerBlock", block: c.EulerBlock},
{name: "gibbsBlock", block: c.GibbsBlock},
+ {name: "bonehBlock", block: c.BonehBlock},
+ {name: "lynnBlock", block: c.LynnBlock},
} {
if lastFork.name != "" {
// Next one must be higher number
@@ -658,6 +753,12 @@ func (c *ChainConfig) checkCompatible(newcfg *ChainConfig, head *big.Int) *Confi
if isForkIncompatible(c.PlanckBlock, newcfg.PlanckBlock, head) {
return newCompatError("planck fork block", c.PlanckBlock, newcfg.PlanckBlock)
}
+ if isForkIncompatible(c.BonehBlock, newcfg.BonehBlock, head) {
+ return newCompatError("boneh fork block", c.BonehBlock, newcfg.BonehBlock)
+ }
+ if isForkIncompatible(c.LynnBlock, newcfg.LynnBlock, head) {
+ return newCompatError("lynn fork block", c.LynnBlock, newcfg.LynnBlock)
+ }
return nil
}
@@ -730,6 +831,7 @@ type Rules struct {
IsNano bool
IsMoran bool
IsPlanck bool
+ IsBoneh bool
}
// Rules ensures c's ChainID is not nil.
@@ -754,5 +856,6 @@ func (c *ChainConfig) Rules(num *big.Int, isMerge bool) Rules {
IsNano: c.IsNano(num),
IsMoran: c.IsMoran(num),
IsPlanck: c.IsPlanck(num),
+ IsBoneh: c.IsBoneh(num),
}
}
diff --git a/params/protocol_params.go b/params/protocol_params.go
index e244c24231..653377cc41 100644
--- a/params/protocol_params.go
+++ b/params/protocol_params.go
@@ -132,13 +132,15 @@ const (
TendermintHeaderValidateGas uint64 = 3000 // Gas for validate tendermiint consensus state
IAVLMerkleProofValidateGas uint64 = 3000 // Gas for validate merkle proof
- EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price
- Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation
- Sha256PerWordGas uint64 = 12 // Per-word price for a SHA256 operation
- Ripemd160BaseGas uint64 = 600 // Base price for a RIPEMD160 operation
- Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation
- IdentityBaseGas uint64 = 15 // Base price for a data copy operation
- IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation
+ EcrecoverGas uint64 = 3000 // Elliptic curve sender recovery gas price
+ Sha256BaseGas uint64 = 60 // Base price for a SHA256 operation
+ Sha256PerWordGas uint64 = 12 // Per-word price for a SHA256 operation
+ Ripemd160BaseGas uint64 = 600 // Base price for a RIPEMD160 operation
+ Ripemd160PerWordGas uint64 = 120 // Per-word price for a RIPEMD160 operation
+ IdentityBaseGas uint64 = 15 // Base price for a data copy operation
+ IdentityPerWordGas uint64 = 3 // Per-work price for a data copy operation
+ BlsSignatureVerifyBaseGas uint64 = 1000 // base price for a BLS signature verify operation
+ BlsSignatureVerifyPerKeyGas uint64 = 3500 // Per-key price for a BLS signature verify operation
Bn256AddGasByzantium uint64 = 500 // Byzantium gas needed for an elliptic curve addition
Bn256AddGasIstanbul uint64 = 150 // Gas needed for an elliptic curve addition
diff --git a/rpc/client.go b/rpc/client.go
index a89f8ba18c..c8a1a343bc 100644
--- a/rpc/client.go
+++ b/rpc/client.go
@@ -187,6 +187,18 @@ func DialContext(ctx context.Context, rawurl string) (*Client, error) {
}
}
+// DialOptions creates a new RPC client for the given URL. You can supply any of the
+// pre-defined client options to configure the underlying transport.
+//
+// The context is used to cancel or time out the initial connection establishment. It does
+// not affect subsequent interactions with the client.
+//
+// The client reconnects automatically when the connection is lost.
+func DialOptions(ctx context.Context, rawurl string, options ...ClientOption) (*Client, error) {
+ // just for prysm compile pass
+ return nil, fmt.Errorf("not supported")
+}
+
// Client retrieves the client from the context, if any. This can be used to perform
// 'reverse calls' in a handler method.
func ClientFromContext(ctx context.Context) (*Client, bool) {
diff --git a/rpc/client_opt.go b/rpc/client_opt.go
new file mode 100644
index 0000000000..5ad7c22b3c
--- /dev/null
+++ b/rpc/client_opt.go
@@ -0,0 +1,106 @@
+// 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 .
+
+package rpc
+
+import (
+ "net/http"
+
+ "github.com/gorilla/websocket"
+)
+
+// ClientOption is a configuration option for the RPC client.
+type ClientOption interface {
+ applyOption(*clientConfig)
+}
+
+type clientConfig struct {
+ httpClient *http.Client
+ httpHeaders http.Header
+ httpAuth HTTPAuth
+
+ wsDialer *websocket.Dialer
+}
+
+func (cfg *clientConfig) initHeaders() {
+ if cfg.httpHeaders == nil {
+ cfg.httpHeaders = make(http.Header)
+ }
+}
+
+func (cfg *clientConfig) setHeader(key, value string) {
+ cfg.initHeaders()
+ cfg.httpHeaders.Set(key, value)
+}
+
+type optionFunc func(*clientConfig)
+
+func (fn optionFunc) applyOption(opt *clientConfig) {
+ fn(opt)
+}
+
+// WithWebsocketDialer configures the websocket.Dialer used by the RPC client.
+func WithWebsocketDialer(dialer websocket.Dialer) ClientOption {
+ return optionFunc(func(cfg *clientConfig) {
+ cfg.wsDialer = &dialer
+ })
+}
+
+// WithHeader configures HTTP headers set by the RPC client. Headers set using this option
+// will be used for both HTTP and WebSocket connections.
+func WithHeader(key, value string) ClientOption {
+ return optionFunc(func(cfg *clientConfig) {
+ cfg.initHeaders()
+ cfg.httpHeaders.Set(key, value)
+ })
+}
+
+// WithHeaders configures HTTP headers set by the RPC client. Headers set using this
+// option will be used for both HTTP and WebSocket connections.
+func WithHeaders(headers http.Header) ClientOption {
+ return optionFunc(func(cfg *clientConfig) {
+ cfg.initHeaders()
+ for k, vs := range headers {
+ cfg.httpHeaders[k] = vs
+ }
+ })
+}
+
+// WithHTTPClient configures the http.Client used by the RPC client.
+func WithHTTPClient(c *http.Client) ClientOption {
+ return optionFunc(func(cfg *clientConfig) {
+ cfg.httpClient = c
+ })
+}
+
+// WithHTTPAuth configures HTTP request authentication. The given provider will be called
+// whenever a request is made. Note that only one authentication provider can be active at
+// any time.
+func WithHTTPAuth(a HTTPAuth) ClientOption {
+ if a == nil {
+ panic("nil auth")
+ }
+ return optionFunc(func(cfg *clientConfig) {
+ cfg.httpAuth = a
+ })
+}
+
+// A HTTPAuth function is called by the client whenever a HTTP request is sent.
+// The function must be safe for concurrent use.
+//
+// Usually, HTTPAuth functions will call h.Set("authorization", "...") to add
+// auth information to the request.
+type HTTPAuth func(h http.Header) error
diff --git a/rpc/subscription.go b/rpc/subscription.go
index 942e764e5d..d7ba784fc5 100644
--- a/rpc/subscription.go
+++ b/rpc/subscription.go
@@ -34,7 +34,7 @@ import (
var (
// ErrNotificationsUnsupported is returned when the connection doesn't support notifications
ErrNotificationsUnsupported = errors.New("notifications not supported")
- // ErrNotificationNotFound is returned when the notification for the given id is not found
+ // ErrSubscriptionNotFound is returned when the notification for the given id is not found
ErrSubscriptionNotFound = errors.New("subscription not found")
)
diff --git a/rpc/types.go b/rpc/types.go
index 959e383723..151e5ee27e 100644
--- a/rpc/types.go
+++ b/rpc/types.go
@@ -60,13 +60,15 @@ type jsonWriter interface {
type BlockNumber int64
const (
- PendingBlockNumber = BlockNumber(-2)
- LatestBlockNumber = BlockNumber(-1)
- EarliestBlockNumber = BlockNumber(0)
+ SafeBlockNumber = BlockNumber(-4)
+ FinalizedBlockNumber = BlockNumber(-3)
+ PendingBlockNumber = BlockNumber(-2)
+ LatestBlockNumber = BlockNumber(-1)
+ EarliestBlockNumber = BlockNumber(0)
)
// UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports:
-// - "latest", "earliest" or "pending" as string arguments
+// - "safe", "finalized", "latest", "earliest" or "pending" as string arguments
// - the block number
// Returned errors:
// - an invalid block number error when the given argument isn't a known strings
@@ -87,6 +89,12 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
case "pending":
*bn = PendingBlockNumber
return nil
+ case "finalized":
+ *bn = FinalizedBlockNumber
+ return nil
+ case "safe":
+ *bn = SafeBlockNumber
+ return nil
}
blckNum, err := hexutil.DecodeUint64(input)
@@ -101,7 +109,7 @@ func (bn *BlockNumber) UnmarshalJSON(data []byte) error {
}
// MarshalText implements encoding.TextMarshaler. It marshals:
-// - "latest", "earliest" or "pending" as strings
+// - "safe", "finalized", "latest", "earliest" or "pending" as strings
// - other numbers as hex
func (bn BlockNumber) MarshalText() ([]byte, error) {
switch bn {
@@ -111,6 +119,10 @@ func (bn BlockNumber) MarshalText() ([]byte, error) {
return []byte("latest"), nil
case PendingBlockNumber:
return []byte("pending"), nil
+ case FinalizedBlockNumber:
+ return []byte("finalized"), nil
+ case SafeBlockNumber:
+ return []byte("safe"), nil
default:
return hexutil.Uint64(bn).MarshalText()
}
@@ -157,6 +169,14 @@ func (bnh *BlockNumberOrHash) UnmarshalJSON(data []byte) error {
bn := PendingBlockNumber
bnh.BlockNumber = &bn
return nil
+ case "finalized":
+ bn := FinalizedBlockNumber
+ bnh.BlockNumber = &bn
+ return nil
+ case "safe":
+ bn := SafeBlockNumber
+ bnh.BlockNumber = &bn
+ return nil
default:
if len(input) == 66 {
hash := common.Hash{}
diff --git a/tests/truffle/.env b/tests/truffle/.env
index d933e4cfef..e2b3e27f5c 100644
--- a/tests/truffle/.env
+++ b/tests/truffle/.env
@@ -1,4 +1,4 @@
-BSC_CHAIN_ID="99"
+BSC_CHAIN_ID=99
CLUSTER_CIDR=99.1.0.0/16
BOOTSTRAP_PUB_KEY=177ae5db445a2f70db781b019aedd928f5b1528a7a43448840b022408f9a21509adcce0b37c87d59da68d47a16879cc1e95a62bbac9723f7b22f4365b2afabbe
BOOTSTRAP_TCP_PORT=30311
diff --git a/tests/truffle/scripts/bootstrap.sh b/tests/truffle/scripts/bootstrap.sh
index 0e5e00df99..653059115d 100755
--- a/tests/truffle/scripts/bootstrap.sh
+++ b/tests/truffle/scripts/bootstrap.sh
@@ -42,19 +42,38 @@ function init_genesis_data() {
fi
}
+function prepareBLSWallet(){
+ node_id=$1
+ echo "123456" > ${workspace}/storage/${node_id}/blspassword.txt
+ expect ${workspace}/scripts/create_bls_key.sh ${workspace}/storage/${node_id}
+
+ sed -i -e 's/DataDir/BLSPasswordFile = \"{{BLSPasswordFile}}\"\nBLSWalletDir = \"{{BLSWalletDir}}\"\nDataDir/g' ${workspace}/storage/${node_id}/config.toml
+ PassWordPath="/root/.ethereum/blspassword.txt"
+ sed -i -e "s:{{BLSPasswordFile}}:${PassWordPath}:g" ${workspace}/storage/${node_id}/config.toml
+ WalletPath="/root/.ethereum/bls/wallet"
+ sed -i -e "s:{{BLSWalletDir}}:${WalletPath}:g" ${workspace}/storage/${node_id}/config.toml
+}
+
prepare
-# First, generate config for each validator
+# Step 1, generate config for each validator
for((i=1;i<=${NUMS_OF_VALIDATOR};i++)); do
init_validator "bsc-validator${i}"
done
-# Then, use validator configs to generate genesis file
+# Step 2, use validator configs to generate genesis file
generate_genesis
-# Finally, use genesis file to init cluster data
+# Step 3, use genesis file to init cluster data
init_genesis_data bsc-rpc bsc-rpc
for((i=1;i<=${NUMS_OF_VALIDATOR};i++)); do
init_genesis_data validator "bsc-validator${i}"
done
+
+#Step 4, prepare bls wallet, used by fast finality vote
+prepareBLSWallet bsc-rpc
+
+for((i=1;i<=${NUMS_OF_VALIDATOR};i++)); do
+ prepareBLSWallet "bsc-validator${i}"
+done
\ No newline at end of file
diff --git a/tests/truffle/scripts/create_bls_key.sh b/tests/truffle/scripts/create_bls_key.sh
new file mode 100644
index 0000000000..a1a4d97bd6
--- /dev/null
+++ b/tests/truffle/scripts/create_bls_key.sh
@@ -0,0 +1,17 @@
+#!/usr/bin/expect
+# 6 num wanted
+set wallet_password 123456
+# 10 characters at least wanted
+set account_password 1234567890
+
+set timeout 5
+spawn geth bls account new --datadir [lindex $argv 0]
+expect "*assword:*"
+send "$wallet_password\r"
+expect "*assword:*"
+send "$wallet_password\r"
+expect "*assword:*"
+send "$account_password\r"
+expect "*assword:*"
+send "$account_password\r"
+expect EOF
\ No newline at end of file