forked from cerc-io/plugeth
Merge tag 'v1.10.8' into develop
This commit is contained in:
commit
9497293e26
@ -795,7 +795,7 @@ type callMsg struct {
|
|||||||
|
|
||||||
func (m callMsg) From() common.Address { return m.CallMsg.From }
|
func (m callMsg) From() common.Address { return m.CallMsg.From }
|
||||||
func (m callMsg) Nonce() uint64 { return 0 }
|
func (m callMsg) Nonce() uint64 { return 0 }
|
||||||
func (m callMsg) CheckNonce() bool { return false }
|
func (m callMsg) IsFake() bool { return true }
|
||||||
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
func (m callMsg) To() *common.Address { return m.CallMsg.To }
|
||||||
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
func (m callMsg) GasPrice() *big.Int { return m.CallMsg.GasPrice }
|
||||||
func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap }
|
func (m callMsg) GasFeeCap() *big.Int { return m.CallMsg.GasFeeCap }
|
||||||
|
10
accounts/external/backend.go
vendored
10
accounts/external/backend.go
vendored
@ -196,6 +196,10 @@ type signTransactionResult struct {
|
|||||||
Tx *types.Transaction `json:"tx"`
|
Tx *types.Transaction `json:"tx"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SignTx sends the transaction to the external signer.
|
||||||
|
// If chainID is nil, or tx.ChainID is zero, the chain ID will be assigned
|
||||||
|
// by the external signer. For non-legacy transactions, the chain ID of the
|
||||||
|
// transaction overrides the chainID parameter.
|
||||||
func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
|
func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
|
||||||
data := hexutil.Bytes(tx.Data())
|
data := hexutil.Bytes(tx.Data())
|
||||||
var to *common.MixedcaseAddress
|
var to *common.MixedcaseAddress
|
||||||
@ -218,17 +222,17 @@ func (api *ExternalSigner) SignTx(account accounts.Account, tx *types.Transactio
|
|||||||
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
|
args.MaxFeePerGas = (*hexutil.Big)(tx.GasFeeCap())
|
||||||
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
|
args.MaxPriorityFeePerGas = (*hexutil.Big)(tx.GasTipCap())
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("Unsupported tx type %d", tx.Type())
|
return nil, fmt.Errorf("unsupported tx type %d", tx.Type())
|
||||||
}
|
}
|
||||||
// We should request the default chain id that we're operating with
|
// We should request the default chain id that we're operating with
|
||||||
// (the chain we're executing on)
|
// (the chain we're executing on)
|
||||||
if chainID != nil {
|
if chainID != nil && chainID.Sign() != 0 {
|
||||||
args.ChainID = (*hexutil.Big)(chainID)
|
args.ChainID = (*hexutil.Big)(chainID)
|
||||||
}
|
}
|
||||||
if tx.Type() != types.LegacyTxType {
|
if tx.Type() != types.LegacyTxType {
|
||||||
// However, if the user asked for a particular chain id, then we should
|
// However, if the user asked for a particular chain id, then we should
|
||||||
// use that instead.
|
// use that instead.
|
||||||
if tx.ChainId() != nil {
|
if tx.ChainId().Sign() != 0 {
|
||||||
args.ChainID = (*hexutil.Big)(tx.ChainId())
|
args.ChainID = (*hexutil.Big)(tx.ChainId())
|
||||||
}
|
}
|
||||||
accessList := tx.AccessList()
|
accessList := tx.AccessList()
|
||||||
|
@ -68,7 +68,6 @@ It expects the genesis file as argument.`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
},
|
},
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
Category: "BLOCKCHAIN COMMANDS",
|
||||||
Description: `
|
Description: `
|
||||||
@ -92,11 +91,15 @@ The dumpgenesis command dumps the genesis block configuration in JSON format to
|
|||||||
utils.MetricsHTTPFlag,
|
utils.MetricsHTTPFlag,
|
||||||
utils.MetricsPortFlag,
|
utils.MetricsPortFlag,
|
||||||
utils.MetricsEnableInfluxDBFlag,
|
utils.MetricsEnableInfluxDBFlag,
|
||||||
|
utils.MetricsEnableInfluxDBV2Flag,
|
||||||
utils.MetricsInfluxDBEndpointFlag,
|
utils.MetricsInfluxDBEndpointFlag,
|
||||||
utils.MetricsInfluxDBDatabaseFlag,
|
utils.MetricsInfluxDBDatabaseFlag,
|
||||||
utils.MetricsInfluxDBUsernameFlag,
|
utils.MetricsInfluxDBUsernameFlag,
|
||||||
utils.MetricsInfluxDBPasswordFlag,
|
utils.MetricsInfluxDBPasswordFlag,
|
||||||
utils.MetricsInfluxDBTagsFlag,
|
utils.MetricsInfluxDBTagsFlag,
|
||||||
|
utils.MetricsInfluxDBTokenFlag,
|
||||||
|
utils.MetricsInfluxDBBucketFlag,
|
||||||
|
utils.MetricsInfluxDBOrganizationFlag,
|
||||||
utils.TxLookupLimitFlag,
|
utils.TxLookupLimitFlag,
|
||||||
},
|
},
|
||||||
Category: "BLOCKCHAIN COMMANDS",
|
Category: "BLOCKCHAIN COMMANDS",
|
||||||
|
@ -233,6 +233,18 @@ func applyMetricConfig(ctx *cli.Context, cfg *gethConfig) {
|
|||||||
if ctx.GlobalIsSet(utils.MetricsInfluxDBTagsFlag.Name) {
|
if ctx.GlobalIsSet(utils.MetricsInfluxDBTagsFlag.Name) {
|
||||||
cfg.Metrics.InfluxDBTags = ctx.GlobalString(utils.MetricsInfluxDBTagsFlag.Name)
|
cfg.Metrics.InfluxDBTags = ctx.GlobalString(utils.MetricsInfluxDBTagsFlag.Name)
|
||||||
}
|
}
|
||||||
|
if ctx.GlobalIsSet(utils.MetricsEnableInfluxDBV2Flag.Name) {
|
||||||
|
cfg.Metrics.EnableInfluxDBV2 = ctx.GlobalBool(utils.MetricsEnableInfluxDBV2Flag.Name)
|
||||||
|
}
|
||||||
|
if ctx.GlobalIsSet(utils.MetricsInfluxDBTokenFlag.Name) {
|
||||||
|
cfg.Metrics.InfluxDBToken = ctx.GlobalString(utils.MetricsInfluxDBTokenFlag.Name)
|
||||||
|
}
|
||||||
|
if ctx.GlobalIsSet(utils.MetricsInfluxDBBucketFlag.Name) {
|
||||||
|
cfg.Metrics.InfluxDBBucket = ctx.GlobalString(utils.MetricsInfluxDBBucketFlag.Name)
|
||||||
|
}
|
||||||
|
if ctx.GlobalIsSet(utils.MetricsInfluxDBOrganizationFlag.Name) {
|
||||||
|
cfg.Metrics.InfluxDBOrganization = ctx.GlobalString(utils.MetricsInfluxDBOrganizationFlag.Name)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func deprecated(field string) bool {
|
func deprecated(field string) bool {
|
||||||
|
@ -134,8 +134,6 @@ func remoteConsole(ctx *cli.Context) error {
|
|||||||
path = filepath.Join(path, "rinkeby")
|
path = filepath.Join(path, "rinkeby")
|
||||||
} else if ctx.GlobalBool(utils.GoerliFlag.Name) {
|
} else if ctx.GlobalBool(utils.GoerliFlag.Name) {
|
||||||
path = filepath.Join(path, "goerli")
|
path = filepath.Join(path, "goerli")
|
||||||
} else if ctx.GlobalBool(utils.CalaverasFlag.Name) {
|
|
||||||
path = filepath.Join(path, "calaveras")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
endpoint = fmt.Sprintf("%s/geth.ipc", path)
|
endpoint = fmt.Sprintf("%s/geth.ipc", path)
|
||||||
|
@ -75,7 +75,6 @@ Remove blockchain and state databases`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
},
|
},
|
||||||
Usage: "Inspect the storage size for each type of data in the database",
|
Usage: "Inspect the storage size for each type of data in the database",
|
||||||
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
Description: `This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data.`,
|
||||||
@ -91,7 +90,6 @@ Remove blockchain and state databases`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
dbCompactCmd = cli.Command{
|
dbCompactCmd = cli.Command{
|
||||||
@ -105,7 +103,6 @@ Remove blockchain and state databases`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
utils.CacheFlag,
|
utils.CacheFlag,
|
||||||
utils.CacheDatabaseFlag,
|
utils.CacheDatabaseFlag,
|
||||||
},
|
},
|
||||||
@ -125,7 +122,6 @@ corruption if it is aborted during execution'!`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
},
|
},
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
}
|
}
|
||||||
@ -141,7 +137,6 @@ corruption if it is aborted during execution'!`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
},
|
},
|
||||||
Description: `This command deletes the specified database key from the database.
|
Description: `This command deletes the specified database key from the database.
|
||||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
@ -158,7 +153,6 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
},
|
},
|
||||||
Description: `This command sets a given database key to the given value.
|
Description: `This command sets a given database key to the given value.
|
||||||
WARNING: This is a low-level operation which may cause database corruption!`,
|
WARNING: This is a low-level operation which may cause database corruption!`,
|
||||||
@ -175,7 +169,6 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
},
|
},
|
||||||
Description: "This command looks up the specified database key from the database.",
|
Description: "This command looks up the specified database key from the database.",
|
||||||
}
|
}
|
||||||
@ -191,7 +184,6 @@ WARNING: This is a low-level operation which may cause database corruption!`,
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
},
|
},
|
||||||
Description: "This command displays information about the freezer index.",
|
Description: "This command displays information about the freezer index.",
|
||||||
}
|
}
|
||||||
|
@ -141,7 +141,6 @@ var (
|
|||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
utils.VMEnableDebugFlag,
|
utils.VMEnableDebugFlag,
|
||||||
utils.NetworkIdFlag,
|
utils.NetworkIdFlag,
|
||||||
utils.EthStatsURLFlag,
|
utils.EthStatsURLFlag,
|
||||||
@ -198,6 +197,10 @@ var (
|
|||||||
utils.MetricsInfluxDBUsernameFlag,
|
utils.MetricsInfluxDBUsernameFlag,
|
||||||
utils.MetricsInfluxDBPasswordFlag,
|
utils.MetricsInfluxDBPasswordFlag,
|
||||||
utils.MetricsInfluxDBTagsFlag,
|
utils.MetricsInfluxDBTagsFlag,
|
||||||
|
utils.MetricsEnableInfluxDBV2Flag,
|
||||||
|
utils.MetricsInfluxDBTokenFlag,
|
||||||
|
utils.MetricsInfluxDBBucketFlag,
|
||||||
|
utils.MetricsInfluxDBOrganizationFlag,
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -277,9 +280,6 @@ func prepare(ctx *cli.Context) {
|
|||||||
case ctx.GlobalIsSet(utils.GoerliFlag.Name):
|
case ctx.GlobalIsSet(utils.GoerliFlag.Name):
|
||||||
log.Info("Starting Geth on Görli testnet...")
|
log.Info("Starting Geth on Görli testnet...")
|
||||||
|
|
||||||
case ctx.GlobalIsSet(utils.CalaverasFlag.Name):
|
|
||||||
log.Info("Starting Geth on Calaveras testnet...")
|
|
||||||
|
|
||||||
case ctx.GlobalIsSet(utils.DeveloperFlag.Name):
|
case ctx.GlobalIsSet(utils.DeveloperFlag.Name):
|
||||||
log.Info("Starting Geth in ephemeral dev mode...")
|
log.Info("Starting Geth in ephemeral dev mode...")
|
||||||
|
|
||||||
|
@ -44,7 +44,6 @@ var AppHelpFlagGroups = []flags.FlagGroup{
|
|||||||
utils.MainnetFlag,
|
utils.MainnetFlag,
|
||||||
utils.GoerliFlag,
|
utils.GoerliFlag,
|
||||||
utils.RinkebyFlag,
|
utils.RinkebyFlag,
|
||||||
utils.CalaverasFlag,
|
|
||||||
utils.RopstenFlag,
|
utils.RopstenFlag,
|
||||||
utils.SyncModeFlag,
|
utils.SyncModeFlag,
|
||||||
utils.ExitWhenSyncedFlag,
|
utils.ExitWhenSyncedFlag,
|
||||||
|
@ -125,10 +125,6 @@ var (
|
|||||||
Name: "keystore",
|
Name: "keystore",
|
||||||
Usage: "Directory for the keystore (default = inside the datadir)",
|
Usage: "Directory for the keystore (default = inside the datadir)",
|
||||||
}
|
}
|
||||||
NoUSBFlag = cli.BoolFlag{
|
|
||||||
Name: "nousb",
|
|
||||||
Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)",
|
|
||||||
}
|
|
||||||
USBFlag = cli.BoolFlag{
|
USBFlag = cli.BoolFlag{
|
||||||
Name: "usb",
|
Name: "usb",
|
||||||
Usage: "Enable monitoring and management of USB hardware wallets",
|
Usage: "Enable monitoring and management of USB hardware wallets",
|
||||||
@ -151,10 +147,6 @@ var (
|
|||||||
Name: "goerli",
|
Name: "goerli",
|
||||||
Usage: "Görli network: pre-configured proof-of-authority test network",
|
Usage: "Görli network: pre-configured proof-of-authority test network",
|
||||||
}
|
}
|
||||||
CalaverasFlag = cli.BoolFlag{
|
|
||||||
Name: "calaveras",
|
|
||||||
Usage: "Calaveras network: pre-configured proof-of-authority shortlived test network.",
|
|
||||||
}
|
|
||||||
RinkebyFlag = cli.BoolFlag{
|
RinkebyFlag = cli.BoolFlag{
|
||||||
Name: "rinkeby",
|
Name: "rinkeby",
|
||||||
Usage: "Rinkeby network: pre-configured proof-of-authority test network",
|
Usage: "Rinkeby network: pre-configured proof-of-authority test network",
|
||||||
@ -756,6 +748,29 @@ var (
|
|||||||
Value: metrics.DefaultConfig.InfluxDBTags,
|
Value: metrics.DefaultConfig.InfluxDBTags,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MetricsEnableInfluxDBV2Flag = cli.BoolFlag{
|
||||||
|
Name: "metrics.influxdbv2",
|
||||||
|
Usage: "Enable metrics export/push to an external InfluxDB v2 database",
|
||||||
|
}
|
||||||
|
|
||||||
|
MetricsInfluxDBTokenFlag = cli.StringFlag{
|
||||||
|
Name: "metrics.influxdb.token",
|
||||||
|
Usage: "Token to authorize access to the database (v2 only)",
|
||||||
|
Value: metrics.DefaultConfig.InfluxDBToken,
|
||||||
|
}
|
||||||
|
|
||||||
|
MetricsInfluxDBBucketFlag = cli.StringFlag{
|
||||||
|
Name: "metrics.influxdb.bucket",
|
||||||
|
Usage: "InfluxDB bucket name to push reported metrics to (v2 only)",
|
||||||
|
Value: metrics.DefaultConfig.InfluxDBBucket,
|
||||||
|
}
|
||||||
|
|
||||||
|
MetricsInfluxDBOrganizationFlag = cli.StringFlag{
|
||||||
|
Name: "metrics.influxdb.organization",
|
||||||
|
Usage: "InfluxDB organization name (v2 only)",
|
||||||
|
Value: metrics.DefaultConfig.InfluxDBOrganization,
|
||||||
|
}
|
||||||
|
|
||||||
CatalystFlag = cli.BoolFlag{
|
CatalystFlag = cli.BoolFlag{
|
||||||
Name: "catalyst",
|
Name: "catalyst",
|
||||||
Usage: "Catalyst mode (eth2 integration testing)",
|
Usage: "Catalyst mode (eth2 integration testing)",
|
||||||
@ -778,9 +793,6 @@ func MakeDataDir(ctx *cli.Context) string {
|
|||||||
if ctx.GlobalBool(GoerliFlag.Name) {
|
if ctx.GlobalBool(GoerliFlag.Name) {
|
||||||
return filepath.Join(path, "goerli")
|
return filepath.Join(path, "goerli")
|
||||||
}
|
}
|
||||||
if ctx.GlobalBool(CalaverasFlag.Name) {
|
|
||||||
return filepath.Join(path, "calaveras")
|
|
||||||
}
|
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
Fatalf("Cannot determine default data directory, please set manually (--datadir)")
|
Fatalf("Cannot determine default data directory, please set manually (--datadir)")
|
||||||
@ -833,8 +845,6 @@ func setBootstrapNodes(ctx *cli.Context, cfg *p2p.Config) {
|
|||||||
urls = params.RinkebyBootnodes
|
urls = params.RinkebyBootnodes
|
||||||
case ctx.GlobalBool(GoerliFlag.Name):
|
case ctx.GlobalBool(GoerliFlag.Name):
|
||||||
urls = params.GoerliBootnodes
|
urls = params.GoerliBootnodes
|
||||||
case ctx.GlobalBool(CalaverasFlag.Name):
|
|
||||||
urls = params.CalaverasBootnodes
|
|
||||||
case cfg.BootstrapNodes != nil:
|
case cfg.BootstrapNodes != nil:
|
||||||
return // already set, don't apply defaults.
|
return // already set, don't apply defaults.
|
||||||
}
|
}
|
||||||
@ -1278,8 +1288,6 @@ func setDataDir(ctx *cli.Context, cfg *node.Config) {
|
|||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "rinkeby")
|
||||||
case ctx.GlobalBool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
case ctx.GlobalBool(GoerliFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
|
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "goerli")
|
||||||
case ctx.GlobalBool(CalaverasFlag.Name) && cfg.DataDir == node.DefaultDataDir():
|
|
||||||
cfg.DataDir = filepath.Join(node.DefaultDataDir(), "calaveras")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1465,7 +1473,7 @@ func CheckExclusive(ctx *cli.Context, args ...interface{}) {
|
|||||||
// SetEthConfig applies eth-related command line flags to the config.
|
// SetEthConfig applies eth-related command line flags to the config.
|
||||||
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
||||||
// Avoid conflicting network flags
|
// Avoid conflicting network flags
|
||||||
CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RopstenFlag, RinkebyFlag, GoerliFlag, CalaverasFlag)
|
CheckExclusive(ctx, MainnetFlag, DeveloperFlag, RopstenFlag, RinkebyFlag, GoerliFlag)
|
||||||
CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
|
CheckExclusive(ctx, LightServeFlag, SyncModeFlag, "light")
|
||||||
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
CheckExclusive(ctx, DeveloperFlag, ExternalSignerFlag) // Can't use both ephemeral unlocked and external signer
|
||||||
if ctx.GlobalString(GCModeFlag.Name) == "archive" && ctx.GlobalUint64(TxLookupLimitFlag.Name) != 0 {
|
if ctx.GlobalString(GCModeFlag.Name) == "archive" && ctx.GlobalUint64(TxLookupLimitFlag.Name) != 0 {
|
||||||
@ -1618,11 +1626,6 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
|
|||||||
}
|
}
|
||||||
cfg.Genesis = core.DefaultGoerliGenesisBlock()
|
cfg.Genesis = core.DefaultGoerliGenesisBlock()
|
||||||
SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash)
|
SetDNSDiscoveryDefaults(cfg, params.GoerliGenesisHash)
|
||||||
case ctx.GlobalBool(CalaverasFlag.Name):
|
|
||||||
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
|
|
||||||
cfg.NetworkId = 123 // https://gist.github.com/holiman/c5697b041b3dc18c50a5cdd382cbdd16
|
|
||||||
}
|
|
||||||
cfg.Genesis = core.DefaultCalaverasGenesisBlock()
|
|
||||||
case ctx.GlobalBool(DeveloperFlag.Name):
|
case ctx.GlobalBool(DeveloperFlag.Name):
|
||||||
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
|
if !ctx.GlobalIsSet(NetworkIdFlag.Name) {
|
||||||
cfg.NetworkId = 1337
|
cfg.NetworkId = 1337
|
||||||
@ -1739,11 +1742,36 @@ func SetupMetrics(ctx *cli.Context) {
|
|||||||
log.Info("Enabling metrics collection")
|
log.Info("Enabling metrics collection")
|
||||||
|
|
||||||
var (
|
var (
|
||||||
enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
|
enableExport = ctx.GlobalBool(MetricsEnableInfluxDBFlag.Name)
|
||||||
endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
|
enableExportV2 = ctx.GlobalBool(MetricsEnableInfluxDBV2Flag.Name)
|
||||||
database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
|
)
|
||||||
username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
|
|
||||||
password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
|
if enableExport || enableExportV2 {
|
||||||
|
CheckExclusive(ctx, MetricsEnableInfluxDBFlag, MetricsEnableInfluxDBV2Flag)
|
||||||
|
|
||||||
|
v1FlagIsSet := ctx.GlobalIsSet(MetricsInfluxDBUsernameFlag.Name) ||
|
||||||
|
ctx.GlobalIsSet(MetricsInfluxDBPasswordFlag.Name)
|
||||||
|
|
||||||
|
v2FlagIsSet := ctx.GlobalIsSet(MetricsInfluxDBTokenFlag.Name) ||
|
||||||
|
ctx.GlobalIsSet(MetricsInfluxDBOrganizationFlag.Name) ||
|
||||||
|
ctx.GlobalIsSet(MetricsInfluxDBBucketFlag.Name)
|
||||||
|
|
||||||
|
if enableExport && v2FlagIsSet {
|
||||||
|
Fatalf("Flags --influxdb.metrics.organization, --influxdb.metrics.token, --influxdb.metrics.bucket are only available for influxdb-v2")
|
||||||
|
} else if enableExportV2 && v1FlagIsSet {
|
||||||
|
Fatalf("Flags --influxdb.metrics.username, --influxdb.metrics.password are only available for influxdb-v1")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
endpoint = ctx.GlobalString(MetricsInfluxDBEndpointFlag.Name)
|
||||||
|
database = ctx.GlobalString(MetricsInfluxDBDatabaseFlag.Name)
|
||||||
|
username = ctx.GlobalString(MetricsInfluxDBUsernameFlag.Name)
|
||||||
|
password = ctx.GlobalString(MetricsInfluxDBPasswordFlag.Name)
|
||||||
|
|
||||||
|
token = ctx.GlobalString(MetricsInfluxDBTokenFlag.Name)
|
||||||
|
bucket = ctx.GlobalString(MetricsInfluxDBBucketFlag.Name)
|
||||||
|
organization = ctx.GlobalString(MetricsInfluxDBOrganizationFlag.Name)
|
||||||
)
|
)
|
||||||
|
|
||||||
if enableExport {
|
if enableExport {
|
||||||
@ -1752,6 +1780,12 @@ func SetupMetrics(ctx *cli.Context) {
|
|||||||
log.Info("Enabling metrics export to InfluxDB")
|
log.Info("Enabling metrics export to InfluxDB")
|
||||||
|
|
||||||
go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
|
go influxdb.InfluxDBWithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, database, username, password, "geth.", tagsMap)
|
||||||
|
} else if enableExportV2 {
|
||||||
|
tagsMap := SplitTagsFlag(ctx.GlobalString(MetricsInfluxDBTagsFlag.Name))
|
||||||
|
|
||||||
|
log.Info("Enabling metrics export to InfluxDB (v2)")
|
||||||
|
|
||||||
|
go influxdb.InfluxDBV2WithTags(metrics.DefaultRegistry, 10*time.Second, endpoint, token, bucket, organization, "geth.", tagsMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.GlobalIsSet(MetricsHTTPFlag.Name) {
|
if ctx.GlobalIsSet(MetricsHTTPFlag.Name) {
|
||||||
@ -1812,8 +1846,6 @@ func MakeGenesis(ctx *cli.Context) *core.Genesis {
|
|||||||
genesis = core.DefaultRinkebyGenesisBlock()
|
genesis = core.DefaultRinkebyGenesisBlock()
|
||||||
case ctx.GlobalBool(GoerliFlag.Name):
|
case ctx.GlobalBool(GoerliFlag.Name):
|
||||||
genesis = core.DefaultGoerliGenesisBlock()
|
genesis = core.DefaultGoerliGenesisBlock()
|
||||||
case ctx.GlobalBool(CalaverasFlag.Name):
|
|
||||||
genesis = core.DefaultCalaverasGenesisBlock()
|
|
||||||
case ctx.GlobalBool(DeveloperFlag.Name):
|
case ctx.GlobalBool(DeveloperFlag.Name):
|
||||||
Fatalf("Developer chains are ephemeral")
|
Fatalf("Developer chains are ephemeral")
|
||||||
}
|
}
|
||||||
|
@ -36,10 +36,15 @@ var ShowDeprecated = cli.Command{
|
|||||||
|
|
||||||
var DeprecatedFlags = []cli.Flag{
|
var DeprecatedFlags = []cli.Flag{
|
||||||
LegacyMinerGasTargetFlag,
|
LegacyMinerGasTargetFlag,
|
||||||
|
NoUSBFlag,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// (Deprecated May 2020, shown in aliased flags section)
|
// (Deprecated May 2020, shown in aliased flags section)
|
||||||
|
NoUSBFlag = cli.BoolFlag{
|
||||||
|
Name: "nousb",
|
||||||
|
Usage: "Disables monitoring for and managing USB hardware wallets (deprecated)",
|
||||||
|
}
|
||||||
LegacyRPCEnabledFlag = cli.BoolFlag{
|
LegacyRPCEnabledFlag = cli.BoolFlag{
|
||||||
Name: "rpc",
|
Name: "rpc",
|
||||||
Usage: "Enable the HTTP-RPC server (deprecated and will be removed June 2021, use --http)",
|
Usage: "Enable the HTTP-RPC server (deprecated and will be removed June 2021, use --http)",
|
||||||
|
@ -248,8 +248,6 @@ func (g *Genesis) configOrDefault(ghash common.Hash) *params.ChainConfig {
|
|||||||
return params.RinkebyChainConfig
|
return params.RinkebyChainConfig
|
||||||
case ghash == params.GoerliGenesisHash:
|
case ghash == params.GoerliGenesisHash:
|
||||||
return params.GoerliChainConfig
|
return params.GoerliChainConfig
|
||||||
case ghash == params.CalaverasGenesisHash:
|
|
||||||
return params.CalaverasChainConfig
|
|
||||||
default:
|
default:
|
||||||
return params.AllEthashProtocolChanges
|
return params.AllEthashProtocolChanges
|
||||||
}
|
}
|
||||||
@ -399,18 +397,6 @@ func DefaultGoerliGenesisBlock() *Genesis {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func DefaultCalaverasGenesisBlock() *Genesis {
|
|
||||||
// Full genesis: https://gist.github.com/holiman/c6ed9269dce28304ad176314caa75e97
|
|
||||||
return &Genesis{
|
|
||||||
Config: params.CalaverasChainConfig,
|
|
||||||
Timestamp: 0x60b3877f,
|
|
||||||
ExtraData: hexutil.MustDecode("0x00000000000000000000000000000000000000000000000000000000000000005211cea3870c7ba7c6c44b185e62eecdb864cd8c560228ce57d31efbf64c200b2c200aacec78cf17a7148e784fe95a7a750335f8b9572ee28d72e7650000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"),
|
|
||||||
GasLimit: 0x47b760,
|
|
||||||
Difficulty: big.NewInt(1),
|
|
||||||
Alloc: decodePrealloc(calaverasAllocData),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
// DeveloperGenesisBlock returns the 'geth --dev' genesis block.
|
||||||
func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
|
func DeveloperGenesisBlock(period uint64, faucet common.Address) *Genesis {
|
||||||
// Override the default period to the user requested one
|
// Override the default period to the user requested one
|
||||||
|
@ -185,10 +185,6 @@ func TestGenesisHashes(t *testing.T) {
|
|||||||
genesis: DefaultRinkebyGenesisBlock(),
|
genesis: DefaultRinkebyGenesisBlock(),
|
||||||
hash: params.RinkebyGenesisHash,
|
hash: params.RinkebyGenesisHash,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
genesis: DefaultCalaverasGenesisBlock(),
|
|
||||||
hash: params.CalaverasGenesisHash,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
for i, c := range cases {
|
for i, c := range cases {
|
||||||
b := c.genesis.MustCommit(rawdb.NewMemoryDatabase())
|
b := c.genesis.MustCommit(rawdb.NewMemoryDatabase())
|
||||||
|
@ -89,6 +89,11 @@ func (db *nofreezedb) Ancient(kind string, number uint64) ([]byte, error) {
|
|||||||
return nil, errNotSupported
|
return nil, errNotSupported
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadAncients returns an error as we don't have a backing chain freezer.
|
||||||
|
func (db *nofreezedb) ReadAncients(kind string, start, max, maxByteSize uint64) ([][]byte, error) {
|
||||||
|
return nil, errNotSupported
|
||||||
|
}
|
||||||
|
|
||||||
// Ancients returns an error as we don't have a backing chain freezer.
|
// Ancients returns an error as we don't have a backing chain freezer.
|
||||||
func (db *nofreezedb) Ancients() (uint64, error) {
|
func (db *nofreezedb) Ancients() (uint64, error) {
|
||||||
return 0, errNotSupported
|
return 0, errNotSupported
|
||||||
|
@ -180,6 +180,18 @@ func (f *freezer) Ancient(kind string, number uint64) ([]byte, error) {
|
|||||||
return nil, errUnknownTable
|
return nil, errUnknownTable
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadAncients retrieves multiple items in sequence, starting from the index 'start'.
|
||||||
|
// It will return
|
||||||
|
// - at most 'max' items,
|
||||||
|
// - at least 1 item (even if exceeding the maxByteSize), but will otherwise
|
||||||
|
// return as many items as fit into maxByteSize.
|
||||||
|
func (f *freezer) ReadAncients(kind string, start, count, maxBytes uint64) ([][]byte, error) {
|
||||||
|
if table := f.tables[kind]; table != nil {
|
||||||
|
return table.RetrieveItems(start, count, maxBytes)
|
||||||
|
}
|
||||||
|
return nil, errUnknownTable
|
||||||
|
}
|
||||||
|
|
||||||
// Ancients returns the length of the frozen items.
|
// Ancients returns the length of the frozen items.
|
||||||
func (f *freezer) Ancients() (uint64, error) {
|
func (f *freezer) Ancients() (uint64, error) {
|
||||||
return atomic.LoadUint64(&f.frozen), nil
|
return atomic.LoadUint64(&f.frozen), nil
|
||||||
@ -403,7 +415,7 @@ func (f *freezer) freeze(db ethdb.KeyValueStore) {
|
|||||||
}
|
}
|
||||||
batch.Reset()
|
batch.Reset()
|
||||||
|
|
||||||
// Wipe out side chains also and track dangling side chians
|
// Wipe out side chains also and track dangling side chains
|
||||||
var dangling []common.Hash
|
var dangling []common.Hash
|
||||||
for number := first; number < f.frozen; number++ {
|
for number := first; number < f.frozen; number++ {
|
||||||
// Always keep the genesis block in active database
|
// Always keep the genesis block in active database
|
||||||
|
@ -70,6 +70,19 @@ func (i *indexEntry) marshallBinary() []byte {
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bounds returns the start- and end- offsets, and the file number of where to
|
||||||
|
// read there data item marked by the two index entries. The two entries are
|
||||||
|
// assumed to be sequential.
|
||||||
|
func (start *indexEntry) bounds(end *indexEntry) (startOffset, endOffset, fileId uint32) {
|
||||||
|
if start.filenum != end.filenum {
|
||||||
|
// If a piece of data 'crosses' a data-file,
|
||||||
|
// it's actually in one piece on the second data-file.
|
||||||
|
// We return a zero-indexEntry for the second file as start
|
||||||
|
return 0, end.offset, end.filenum
|
||||||
|
}
|
||||||
|
return start.offset, end.offset, end.filenum
|
||||||
|
}
|
||||||
|
|
||||||
// freezerTable represents a single chained data table within the freezer (e.g. blocks).
|
// freezerTable represents a single chained data table within the freezer (e.g. blocks).
|
||||||
// It consists of a data file (snappy encoded arbitrary data blobs) and an indexEntry
|
// It consists of a data file (snappy encoded arbitrary data blobs) and an indexEntry
|
||||||
// file (uncompressed 64 bit indices into the data file).
|
// file (uncompressed 64 bit indices into the data file).
|
||||||
@ -546,84 +559,183 @@ func (t *freezerTable) append(item uint64, encodedBlob []byte, wlock bool) (bool
|
|||||||
return false, nil
|
return false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getBounds returns the indexes for the item
|
// getIndices returns the index entries for the given from-item, covering 'count' items.
|
||||||
// returns start, end, filenumber and error
|
// N.B: The actual number of returned indices for N items will always be N+1 (unless an
|
||||||
func (t *freezerTable) getBounds(item uint64) (uint32, uint32, uint32, error) {
|
// error is returned).
|
||||||
buffer := make([]byte, indexEntrySize)
|
// OBS: This method assumes that the caller has already verified (and/or trimmed) the range
|
||||||
var startIdx, endIdx indexEntry
|
// so that the items are within bounds. If this method is used to read out of bounds,
|
||||||
// Read second index
|
// it will return error.
|
||||||
if _, err := t.index.ReadAt(buffer, int64((item+1)*indexEntrySize)); err != nil {
|
func (t *freezerTable) getIndices(from, count uint64) ([]*indexEntry, error) {
|
||||||
return 0, 0, 0, err
|
// Apply the table-offset
|
||||||
|
from = from - uint64(t.itemOffset)
|
||||||
|
// For reading N items, we need N+1 indices.
|
||||||
|
buffer := make([]byte, (count+1)*indexEntrySize)
|
||||||
|
if _, err := t.index.ReadAt(buffer, int64(from*indexEntrySize)); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
endIdx.unmarshalBinary(buffer)
|
var (
|
||||||
// Read first index (unless it's the very first item)
|
indices []*indexEntry
|
||||||
if item != 0 {
|
offset int
|
||||||
if _, err := t.index.ReadAt(buffer, int64(item*indexEntrySize)); err != nil {
|
)
|
||||||
return 0, 0, 0, err
|
for i := from; i <= from+count; i++ {
|
||||||
}
|
index := new(indexEntry)
|
||||||
startIdx.unmarshalBinary(buffer)
|
index.unmarshalBinary(buffer[offset:])
|
||||||
} else {
|
offset += indexEntrySize
|
||||||
|
indices = append(indices, index)
|
||||||
|
}
|
||||||
|
if from == 0 {
|
||||||
// Special case if we're reading the first item in the freezer. We assume that
|
// Special case if we're reading the first item in the freezer. We assume that
|
||||||
// the first item always start from zero(regarding the deletion, we
|
// the first item always start from zero(regarding the deletion, we
|
||||||
// only support deletion by files, so that the assumption is held).
|
// only support deletion by files, so that the assumption is held).
|
||||||
// This means we can use the first item metadata to carry information about
|
// This means we can use the first item metadata to carry information about
|
||||||
// the 'global' offset, for the deletion-case
|
// the 'global' offset, for the deletion-case
|
||||||
return 0, endIdx.offset, endIdx.filenum, nil
|
indices[0].offset = 0
|
||||||
|
indices[0].filenum = indices[1].filenum
|
||||||
}
|
}
|
||||||
if startIdx.filenum != endIdx.filenum {
|
return indices, nil
|
||||||
// If a piece of data 'crosses' a data-file,
|
|
||||||
// it's actually in one piece on the second data-file.
|
|
||||||
// We return a zero-indexEntry for the second file as start
|
|
||||||
return 0, endIdx.offset, endIdx.filenum, nil
|
|
||||||
}
|
|
||||||
return startIdx.offset, endIdx.offset, endIdx.filenum, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retrieve looks up the data offset of an item with the given number and retrieves
|
// Retrieve looks up the data offset of an item with the given number and retrieves
|
||||||
// the raw binary blob from the data file.
|
// the raw binary blob from the data file.
|
||||||
func (t *freezerTable) Retrieve(item uint64) ([]byte, error) {
|
func (t *freezerTable) Retrieve(item uint64) ([]byte, error) {
|
||||||
blob, err := t.retrieve(item)
|
items, err := t.RetrieveItems(item, 1, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if t.noCompression {
|
return items[0], nil
|
||||||
return blob, nil
|
|
||||||
}
|
|
||||||
return snappy.Decode(nil, blob)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// retrieve looks up the data offset of an item with the given number and retrieves
|
// RetrieveItems returns multiple items in sequence, starting from the index 'start'.
|
||||||
// the raw binary blob from the data file. OBS! This method does not decode
|
// It will return at most 'max' items, but will abort earlier to respect the
|
||||||
// compressed data.
|
// 'maxBytes' argument. However, if the 'maxBytes' is smaller than the size of one
|
||||||
func (t *freezerTable) retrieve(item uint64) ([]byte, error) {
|
// item, it _will_ return one element and possibly overflow the maxBytes.
|
||||||
|
func (t *freezerTable) RetrieveItems(start, count, maxBytes uint64) ([][]byte, error) {
|
||||||
|
// First we read the 'raw' data, which might be compressed.
|
||||||
|
diskData, sizes, err := t.retrieveItems(start, count, maxBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var (
|
||||||
|
output = make([][]byte, 0, count)
|
||||||
|
offset int // offset for reading
|
||||||
|
outputSize int // size of uncompressed data
|
||||||
|
)
|
||||||
|
// Now slice up the data and decompress.
|
||||||
|
for i, diskSize := range sizes {
|
||||||
|
item := diskData[offset : offset+diskSize]
|
||||||
|
offset += diskSize
|
||||||
|
decompressedSize := diskSize
|
||||||
|
if !t.noCompression {
|
||||||
|
decompressedSize, _ = snappy.DecodedLen(item)
|
||||||
|
}
|
||||||
|
if i > 0 && uint64(outputSize+decompressedSize) > maxBytes {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if !t.noCompression {
|
||||||
|
data, err := snappy.Decode(nil, item)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
output = append(output, data)
|
||||||
|
} else {
|
||||||
|
output = append(output, item)
|
||||||
|
}
|
||||||
|
outputSize += decompressedSize
|
||||||
|
}
|
||||||
|
return output, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// retrieveItems reads up to 'count' items from the table. It reads at least
|
||||||
|
// one item, but otherwise avoids reading more than maxBytes bytes.
|
||||||
|
// It returns the (potentially compressed) data, and the sizes.
|
||||||
|
func (t *freezerTable) retrieveItems(start, count, maxBytes uint64) ([]byte, []int, error) {
|
||||||
t.lock.RLock()
|
t.lock.RLock()
|
||||||
defer t.lock.RUnlock()
|
defer t.lock.RUnlock()
|
||||||
// Ensure the table and the item is accessible
|
// Ensure the table and the item is accessible
|
||||||
if t.index == nil || t.head == nil {
|
if t.index == nil || t.head == nil {
|
||||||
return nil, errClosed
|
return nil, nil, errClosed
|
||||||
}
|
}
|
||||||
if atomic.LoadUint64(&t.items) <= item {
|
itemCount := atomic.LoadUint64(&t.items) // max number
|
||||||
return nil, errOutOfBounds
|
// Ensure the start is written, not deleted from the tail, and that the
|
||||||
|
// caller actually wants something
|
||||||
|
if itemCount <= start || uint64(t.itemOffset) > start || count == 0 {
|
||||||
|
return nil, nil, errOutOfBounds
|
||||||
}
|
}
|
||||||
// Ensure the item was not deleted from the tail either
|
if start+count > itemCount {
|
||||||
if uint64(t.itemOffset) > item {
|
count = itemCount - start
|
||||||
return nil, errOutOfBounds
|
|
||||||
}
|
}
|
||||||
startOffset, endOffset, filenum, err := t.getBounds(item - uint64(t.itemOffset))
|
var (
|
||||||
|
output = make([]byte, maxBytes) // Buffer to read data into
|
||||||
|
outputSize int // Used size of that buffer
|
||||||
|
)
|
||||||
|
// readData is a helper method to read a single data item from disk.
|
||||||
|
readData := func(fileId, start uint32, length int) error {
|
||||||
|
// In case a small limit is used, and the elements are large, may need to
|
||||||
|
// realloc the read-buffer when reading the first (and only) item.
|
||||||
|
if len(output) < length {
|
||||||
|
output = make([]byte, length)
|
||||||
|
}
|
||||||
|
dataFile, exist := t.files[fileId]
|
||||||
|
if !exist {
|
||||||
|
return fmt.Errorf("missing data file %d", fileId)
|
||||||
|
}
|
||||||
|
if _, err := dataFile.ReadAt(output[outputSize:outputSize+length], int64(start)); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
outputSize += length
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// Read all the indexes in one go
|
||||||
|
indices, err := t.getIndices(start, count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
dataFile, exist := t.files[filenum]
|
var (
|
||||||
if !exist {
|
sizes []int // The sizes for each element
|
||||||
return nil, fmt.Errorf("missing data file %d", filenum)
|
totalSize = 0 // The total size of all data read so far
|
||||||
|
readStart = indices[0].offset // Where, in the file, to start reading
|
||||||
|
unreadSize = 0 // The size of the as-yet-unread data
|
||||||
|
)
|
||||||
|
|
||||||
|
for i, firstIndex := range indices[:len(indices)-1] {
|
||||||
|
secondIndex := indices[i+1]
|
||||||
|
// Determine the size of the item.
|
||||||
|
offset1, offset2, _ := firstIndex.bounds(secondIndex)
|
||||||
|
size := int(offset2 - offset1)
|
||||||
|
// Crossing a file boundary?
|
||||||
|
if secondIndex.filenum != firstIndex.filenum {
|
||||||
|
// If we have unread data in the first file, we need to do that read now.
|
||||||
|
if unreadSize > 0 {
|
||||||
|
if err := readData(firstIndex.filenum, readStart, unreadSize); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
unreadSize = 0
|
||||||
|
}
|
||||||
|
readStart = 0
|
||||||
|
}
|
||||||
|
if i > 0 && uint64(totalSize+size) > maxBytes {
|
||||||
|
// About to break out due to byte limit being exceeded. We don't
|
||||||
|
// read this last item, but we need to do the deferred reads now.
|
||||||
|
if unreadSize > 0 {
|
||||||
|
if err := readData(secondIndex.filenum, readStart, unreadSize); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
// Defer the read for later
|
||||||
|
unreadSize += size
|
||||||
|
totalSize += size
|
||||||
|
sizes = append(sizes, size)
|
||||||
|
if i == len(indices)-2 || uint64(totalSize) > maxBytes {
|
||||||
|
// Last item, need to do the read now
|
||||||
|
if err := readData(secondIndex.filenum, readStart, unreadSize); err != nil {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// Retrieve the data itself, decompress and return
|
return output[:outputSize], sizes, nil
|
||||||
blob := make([]byte, endOffset-startOffset)
|
|
||||||
if _, err := dataFile.ReadAt(blob, int64(startOffset)); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
t.readMeter.Mark(int64(len(blob) + 2*indexEntrySize))
|
|
||||||
return blob, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// has returns an indicator whether the specified number data
|
// has returns an indicator whether the specified number data
|
||||||
|
@ -74,7 +74,7 @@ func TestFreezerBasics(t *testing.T) {
|
|||||||
exp := getChunk(15, y)
|
exp := getChunk(15, y)
|
||||||
got, err := f.Retrieve(uint64(y))
|
got, err := f.Retrieve(uint64(y))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatalf("reading item %d: %v", y, err)
|
||||||
}
|
}
|
||||||
if !bytes.Equal(got, exp) {
|
if !bytes.Equal(got, exp) {
|
||||||
t.Fatalf("test %d, got \n%x != \n%x", y, got, exp)
|
t.Fatalf("test %d, got \n%x != \n%x", y, got, exp)
|
||||||
@ -692,3 +692,118 @@ func TestAppendTruncateParallel(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestSequentialRead does some basic tests on the RetrieveItems.
|
||||||
|
func TestSequentialRead(t *testing.T) {
|
||||||
|
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
|
||||||
|
fname := fmt.Sprintf("batchread-%d", rand.Uint64())
|
||||||
|
{ // Fill table
|
||||||
|
f, err := newCustomTable(os.TempDir(), fname, rm, wm, sg, 50, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// Write 15 bytes 30 times
|
||||||
|
for x := 0; x < 30; x++ {
|
||||||
|
data := getChunk(15, x)
|
||||||
|
f.Append(uint64(x), data)
|
||||||
|
}
|
||||||
|
f.DumpIndex(0, 30)
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
{ // Open it, iterate, verify iteration
|
||||||
|
f, err := newCustomTable(os.TempDir(), fname, rm, wm, sg, 50, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
items, err := f.RetrieveItems(0, 10000, 100000)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if have, want := len(items), 30; have != want {
|
||||||
|
t.Fatalf("want %d items, have %d ", want, have)
|
||||||
|
}
|
||||||
|
for i, have := range items {
|
||||||
|
want := getChunk(15, i)
|
||||||
|
if !bytes.Equal(want, have) {
|
||||||
|
t.Fatalf("data corruption: have\n%x\n, want \n%x\n", have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
{ // Open it, iterate, verify byte limit. The byte limit is less than item
|
||||||
|
// size, so each lookup should only return one item
|
||||||
|
f, err := newCustomTable(os.TempDir(), fname, rm, wm, sg, 40, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
items, err := f.RetrieveItems(0, 10000, 10)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if have, want := len(items), 1; have != want {
|
||||||
|
t.Fatalf("want %d items, have %d ", want, have)
|
||||||
|
}
|
||||||
|
for i, have := range items {
|
||||||
|
want := getChunk(15, i)
|
||||||
|
if !bytes.Equal(want, have) {
|
||||||
|
t.Fatalf("data corruption: have\n%x\n, want \n%x\n", have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestSequentialReadByteLimit does some more advanced tests on batch reads.
|
||||||
|
// These tests check that when the byte limit hits, we correctly abort in time,
|
||||||
|
// but also properly do all the deferred reads for the previous data, regardless
|
||||||
|
// of whether the data crosses a file boundary or not.
|
||||||
|
func TestSequentialReadByteLimit(t *testing.T) {
|
||||||
|
rm, wm, sg := metrics.NewMeter(), metrics.NewMeter(), metrics.NewGauge()
|
||||||
|
fname := fmt.Sprintf("batchread-2-%d", rand.Uint64())
|
||||||
|
{ // Fill table
|
||||||
|
f, err := newCustomTable(os.TempDir(), fname, rm, wm, sg, 100, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
// Write 10 bytes 30 times,
|
||||||
|
// Splitting it at every 100 bytes (10 items)
|
||||||
|
for x := 0; x < 30; x++ {
|
||||||
|
data := getChunk(10, x)
|
||||||
|
f.Append(uint64(x), data)
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
for i, tc := range []struct {
|
||||||
|
items uint64
|
||||||
|
limit uint64
|
||||||
|
want int
|
||||||
|
}{
|
||||||
|
{9, 89, 8},
|
||||||
|
{10, 99, 9},
|
||||||
|
{11, 109, 10},
|
||||||
|
{100, 89, 8},
|
||||||
|
{100, 99, 9},
|
||||||
|
{100, 109, 10},
|
||||||
|
} {
|
||||||
|
{
|
||||||
|
f, err := newCustomTable(os.TempDir(), fname, rm, wm, sg, 100, true)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
items, err := f.RetrieveItems(0, tc.items, tc.limit)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if have, want := len(items), tc.want; have != want {
|
||||||
|
t.Fatalf("test %d: want %d items, have %d ", i, want, have)
|
||||||
|
}
|
||||||
|
for ii, have := range items {
|
||||||
|
want := getChunk(10, ii)
|
||||||
|
if !bytes.Equal(want, have) {
|
||||||
|
t.Fatalf("test %d: data corruption item %d: have\n%x\n, want \n%x\n", i, ii, have, want)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -62,6 +62,12 @@ func (t *table) Ancient(kind string, number uint64) ([]byte, error) {
|
|||||||
return t.db.Ancient(kind, number)
|
return t.db.Ancient(kind, number)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReadAncients is a noop passthrough that just forwards the request to the underlying
|
||||||
|
// database.
|
||||||
|
func (t *table) ReadAncients(kind string, start, count, maxBytes uint64) ([][]byte, error) {
|
||||||
|
return t.db.ReadAncients(kind, start, count, maxBytes)
|
||||||
|
}
|
||||||
|
|
||||||
// Ancients is a noop passthrough that just forwards the request to the underlying
|
// Ancients is a noop passthrough that just forwards the request to the underlying
|
||||||
// database.
|
// database.
|
||||||
func (t *table) Ancients() (uint64, error) {
|
func (t *table) Ancients() (uint64, error) {
|
||||||
|
@ -74,7 +74,7 @@ type Message interface {
|
|||||||
Value() *big.Int
|
Value() *big.Int
|
||||||
|
|
||||||
Nonce() uint64
|
Nonce() uint64
|
||||||
CheckNonce() bool
|
IsFake() bool
|
||||||
Data() []byte
|
Data() []byte
|
||||||
AccessList() types.AccessList
|
AccessList() types.AccessList
|
||||||
}
|
}
|
||||||
@ -212,8 +212,9 @@ func (st *StateTransition) buyGas() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (st *StateTransition) preCheck() error {
|
func (st *StateTransition) preCheck() error {
|
||||||
// Make sure this transaction's nonce is correct.
|
// Only check transactions that are not fake
|
||||||
if st.msg.CheckNonce() {
|
if !st.msg.IsFake() {
|
||||||
|
// Make sure this transaction's nonce is correct.
|
||||||
stNonce := st.state.GetNonce(st.msg.From())
|
stNonce := st.state.GetNonce(st.msg.From())
|
||||||
if msgNonce := st.msg.Nonce(); stNonce < msgNonce {
|
if msgNonce := st.msg.Nonce(); stNonce < msgNonce {
|
||||||
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh,
|
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooHigh,
|
||||||
@ -222,11 +223,11 @@ func (st *StateTransition) preCheck() error {
|
|||||||
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow,
|
return fmt.Errorf("%w: address %v, tx: %d state: %d", ErrNonceTooLow,
|
||||||
st.msg.From().Hex(), msgNonce, stNonce)
|
st.msg.From().Hex(), msgNonce, stNonce)
|
||||||
}
|
}
|
||||||
}
|
// Make sure the sender is an EOA
|
||||||
// Make sure the sender is an EOA
|
if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyCodeHash && codeHash != (common.Hash{}) {
|
||||||
if codeHash := st.state.GetCodeHash(st.msg.From()); codeHash != emptyCodeHash && codeHash != (common.Hash{}) {
|
return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA,
|
||||||
return fmt.Errorf("%w: address %v, codehash: %s", ErrSenderNoEOA,
|
st.msg.From().Hex(), codeHash)
|
||||||
st.msg.From().Hex(), codeHash)
|
}
|
||||||
}
|
}
|
||||||
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
|
// Make sure that transaction gasFeeCap is greater than the baseFee (post london)
|
||||||
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
|
if st.evm.ChainConfig().IsLondon(st.evm.Context.BlockNumber) {
|
||||||
|
@ -579,10 +579,10 @@ type Message struct {
|
|||||||
gasTipCap *big.Int
|
gasTipCap *big.Int
|
||||||
data []byte
|
data []byte
|
||||||
accessList AccessList
|
accessList AccessList
|
||||||
checkNonce bool
|
isFake bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, data []byte, accessList AccessList, checkNonce bool) Message {
|
func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *big.Int, gasLimit uint64, gasPrice, gasFeeCap, gasTipCap *big.Int, data []byte, accessList AccessList, isFake bool) Message {
|
||||||
return Message{
|
return Message{
|
||||||
from: from,
|
from: from,
|
||||||
to: to,
|
to: to,
|
||||||
@ -594,7 +594,7 @@ func NewMessage(from common.Address, to *common.Address, nonce uint64, amount *b
|
|||||||
gasTipCap: gasTipCap,
|
gasTipCap: gasTipCap,
|
||||||
data: data,
|
data: data,
|
||||||
accessList: accessList,
|
accessList: accessList,
|
||||||
checkNonce: checkNonce,
|
isFake: isFake,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -610,7 +610,7 @@ func (tx *Transaction) AsMessage(s Signer, baseFee *big.Int) (Message, error) {
|
|||||||
amount: tx.Value(),
|
amount: tx.Value(),
|
||||||
data: tx.Data(),
|
data: tx.Data(),
|
||||||
accessList: tx.AccessList(),
|
accessList: tx.AccessList(),
|
||||||
checkNonce: true,
|
isFake: false,
|
||||||
}
|
}
|
||||||
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
// If baseFee provided, set gasPrice to effectiveGasPrice.
|
||||||
if baseFee != nil {
|
if baseFee != nil {
|
||||||
@ -631,4 +631,4 @@ func (m Message) Gas() uint64 { return m.gasLimit }
|
|||||||
func (m Message) Nonce() uint64 { return m.nonce }
|
func (m Message) Nonce() uint64 { return m.nonce }
|
||||||
func (m Message) Data() []byte { return m.data }
|
func (m Message) Data() []byte { return m.data }
|
||||||
func (m Message) AccessList() AccessList { return m.accessList }
|
func (m Message) AccessList() AccessList { return m.accessList }
|
||||||
func (m Message) CheckNonce() bool { return m.checkNonce }
|
func (m Message) IsFake() bool { return m.isFake }
|
||||||
|
@ -16,17 +16,49 @@
|
|||||||
|
|
||||||
package vm
|
package vm
|
||||||
|
|
||||||
|
const (
|
||||||
|
set2BitsMask = uint16(0b1100_0000_0000_0000)
|
||||||
|
set3BitsMask = uint16(0b1110_0000_0000_0000)
|
||||||
|
set4BitsMask = uint16(0b1111_0000_0000_0000)
|
||||||
|
set5BitsMask = uint16(0b1111_1000_0000_0000)
|
||||||
|
set6BitsMask = uint16(0b1111_1100_0000_0000)
|
||||||
|
set7BitsMask = uint16(0b1111_1110_0000_0000)
|
||||||
|
)
|
||||||
|
|
||||||
// bitvec is a bit vector which maps bytes in a program.
|
// bitvec is a bit vector which maps bytes in a program.
|
||||||
// An unset bit means the byte is an opcode, a set bit means
|
// An unset bit means the byte is an opcode, a set bit means
|
||||||
// it's data (i.e. argument of PUSHxx).
|
// it's data (i.e. argument of PUSHxx).
|
||||||
type bitvec []byte
|
type bitvec []byte
|
||||||
|
|
||||||
func (bits *bitvec) set(pos uint64) {
|
var lookup = [8]byte{
|
||||||
(*bits)[pos/8] |= 0x80 >> (pos % 8)
|
0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, 0x1,
|
||||||
}
|
}
|
||||||
func (bits *bitvec) set8(pos uint64) {
|
|
||||||
(*bits)[pos/8] |= 0xFF >> (pos % 8)
|
func (bits bitvec) set1(pos uint64) {
|
||||||
(*bits)[pos/8+1] |= ^(0xFF >> (pos % 8))
|
bits[pos/8] |= lookup[pos%8]
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bits bitvec) setN(flag uint16, pos uint64) {
|
||||||
|
a := flag >> (pos % 8)
|
||||||
|
bits[pos/8] |= byte(a >> 8)
|
||||||
|
if b := byte(a); b != 0 {
|
||||||
|
// If the bit-setting affects the neighbouring byte, we can assign - no need to OR it,
|
||||||
|
// since it's the first write to that byte
|
||||||
|
bits[pos/8+1] = b
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bits bitvec) set8(pos uint64) {
|
||||||
|
a := byte(0xFF >> (pos % 8))
|
||||||
|
bits[pos/8] |= a
|
||||||
|
bits[pos/8+1] = ^a
|
||||||
|
}
|
||||||
|
|
||||||
|
func (bits bitvec) set16(pos uint64) {
|
||||||
|
a := byte(0xFF >> (pos % 8))
|
||||||
|
bits[pos/8] |= a
|
||||||
|
bits[pos/8+1] = 0xFF
|
||||||
|
bits[pos/8+2] = ^a
|
||||||
}
|
}
|
||||||
|
|
||||||
// codeSegment checks if the position is in a code segment.
|
// codeSegment checks if the position is in a code segment.
|
||||||
@ -40,22 +72,52 @@ func codeBitmap(code []byte) bitvec {
|
|||||||
// ends with a PUSH32, the algorithm will push zeroes onto the
|
// ends with a PUSH32, the algorithm will push zeroes onto the
|
||||||
// bitvector outside the bounds of the actual code.
|
// bitvector outside the bounds of the actual code.
|
||||||
bits := make(bitvec, len(code)/8+1+4)
|
bits := make(bitvec, len(code)/8+1+4)
|
||||||
|
return codeBitmapInternal(code, bits)
|
||||||
|
}
|
||||||
|
|
||||||
|
// codeBitmapInternal is the internal implementation of codeBitmap.
|
||||||
|
// It exists for the purpose of being able to run benchmark tests
|
||||||
|
// without dynamic allocations affecting the results.
|
||||||
|
func codeBitmapInternal(code, bits bitvec) bitvec {
|
||||||
for pc := uint64(0); pc < uint64(len(code)); {
|
for pc := uint64(0); pc < uint64(len(code)); {
|
||||||
op := OpCode(code[pc])
|
op := OpCode(code[pc])
|
||||||
|
pc++
|
||||||
if op >= PUSH1 && op <= PUSH32 {
|
if op < PUSH1 || op > PUSH32 {
|
||||||
numbits := op - PUSH1 + 1
|
continue
|
||||||
pc++
|
}
|
||||||
|
numbits := op - PUSH1 + 1
|
||||||
|
if numbits >= 8 {
|
||||||
|
for ; numbits >= 16; numbits -= 16 {
|
||||||
|
bits.set16(pc)
|
||||||
|
pc += 16
|
||||||
|
}
|
||||||
for ; numbits >= 8; numbits -= 8 {
|
for ; numbits >= 8; numbits -= 8 {
|
||||||
bits.set8(pc) // 8
|
bits.set8(pc)
|
||||||
pc += 8
|
pc += 8
|
||||||
}
|
}
|
||||||
for ; numbits > 0; numbits-- {
|
}
|
||||||
bits.set(pc)
|
switch numbits {
|
||||||
pc++
|
case 1:
|
||||||
}
|
bits.set1(pc)
|
||||||
} else {
|
pc += 1
|
||||||
pc++
|
case 2:
|
||||||
|
bits.setN(set2BitsMask, pc)
|
||||||
|
pc += 2
|
||||||
|
case 3:
|
||||||
|
bits.setN(set3BitsMask, pc)
|
||||||
|
pc += 3
|
||||||
|
case 4:
|
||||||
|
bits.setN(set4BitsMask, pc)
|
||||||
|
pc += 4
|
||||||
|
case 5:
|
||||||
|
bits.setN(set5BitsMask, pc)
|
||||||
|
pc += 5
|
||||||
|
case 6:
|
||||||
|
bits.setN(set6BitsMask, pc)
|
||||||
|
pc += 6
|
||||||
|
case 7:
|
||||||
|
bits.setN(set7BitsMask, pc)
|
||||||
|
pc += 7
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return bits
|
return bits
|
||||||
|
@ -47,10 +47,10 @@ func TestJumpDestAnalysis(t *testing.T) {
|
|||||||
{[]byte{byte(PUSH32)}, 0xFF, 1},
|
{[]byte{byte(PUSH32)}, 0xFF, 1},
|
||||||
{[]byte{byte(PUSH32)}, 0xFF, 2},
|
{[]byte{byte(PUSH32)}, 0xFF, 2},
|
||||||
}
|
}
|
||||||
for _, test := range tests {
|
for i, test := range tests {
|
||||||
ret := codeBitmap(test.code)
|
ret := codeBitmap(test.code)
|
||||||
if ret[test.which] != test.exp {
|
if ret[test.which] != test.exp {
|
||||||
t.Fatalf("expected %x, got %02x", test.exp, ret[test.which])
|
t.Fatalf("test %d: expected %x, got %02x", i, test.exp, ret[test.which])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -73,3 +73,23 @@ func BenchmarkJumpdestHashing_1200k(bench *testing.B) {
|
|||||||
}
|
}
|
||||||
bench.StopTimer()
|
bench.StopTimer()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func BenchmarkJumpdestOpAnalysis(bench *testing.B) {
|
||||||
|
var op OpCode
|
||||||
|
bencher := func(b *testing.B) {
|
||||||
|
code := make([]byte, 32*b.N)
|
||||||
|
for i := range code {
|
||||||
|
code[i] = byte(op)
|
||||||
|
}
|
||||||
|
bits := make(bitvec, len(code)/8+1+4)
|
||||||
|
b.ResetTimer()
|
||||||
|
codeBitmapInternal(code, bits)
|
||||||
|
}
|
||||||
|
for op = PUSH1; op <= PUSH32; op++ {
|
||||||
|
bench.Run(op.String(), bencher)
|
||||||
|
}
|
||||||
|
op = JUMPDEST
|
||||||
|
bench.Run(op.String(), bencher)
|
||||||
|
op = STOP
|
||||||
|
bench.Run(op.String(), bencher)
|
||||||
|
}
|
||||||
|
@ -669,6 +669,7 @@ func opCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([]byt
|
|||||||
}
|
}
|
||||||
stack.push(&temp)
|
stack.push(&temp)
|
||||||
if err == nil || err == ErrExecutionReverted {
|
if err == nil || err == ErrExecutionReverted {
|
||||||
|
ret = common.CopyBytes(ret)
|
||||||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||||
}
|
}
|
||||||
scope.Contract.Gas += returnGas
|
scope.Contract.Gas += returnGas
|
||||||
@ -703,6 +704,7 @@ func opCallCode(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext) ([
|
|||||||
}
|
}
|
||||||
stack.push(&temp)
|
stack.push(&temp)
|
||||||
if err == nil || err == ErrExecutionReverted {
|
if err == nil || err == ErrExecutionReverted {
|
||||||
|
ret = common.CopyBytes(ret)
|
||||||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||||
}
|
}
|
||||||
scope.Contract.Gas += returnGas
|
scope.Contract.Gas += returnGas
|
||||||
@ -730,6 +732,7 @@ func opDelegateCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext
|
|||||||
}
|
}
|
||||||
stack.push(&temp)
|
stack.push(&temp)
|
||||||
if err == nil || err == ErrExecutionReverted {
|
if err == nil || err == ErrExecutionReverted {
|
||||||
|
ret = common.CopyBytes(ret)
|
||||||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||||
}
|
}
|
||||||
scope.Contract.Gas += returnGas
|
scope.Contract.Gas += returnGas
|
||||||
@ -757,6 +760,7 @@ func opStaticCall(pc *uint64, interpreter *EVMInterpreter, scope *ScopeContext)
|
|||||||
}
|
}
|
||||||
stack.push(&temp)
|
stack.push(&temp)
|
||||||
if err == nil || err == ErrExecutionReverted {
|
if err == nil || err == ErrExecutionReverted {
|
||||||
|
ret = common.CopyBytes(ret)
|
||||||
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
scope.Memory.Set(retOffset.Uint64(), retSize.Uint64(), ret)
|
||||||
}
|
}
|
||||||
scope.Contract.Gas += returnGas
|
scope.Contract.Gas += returnGas
|
||||||
|
@ -262,7 +262,7 @@ func (in *EVMInterpreter) Run(contract *Contract, input []byte, readOnly bool) (
|
|||||||
// if the operation clears the return data (e.g. it has returning data)
|
// if the operation clears the return data (e.g. it has returning data)
|
||||||
// set the last return to the result of the operation.
|
// set the last return to the result of the operation.
|
||||||
if operation.returns {
|
if operation.returns {
|
||||||
in.returnData = common.CopyBytes(res)
|
in.returnData = res
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
|
@ -342,7 +342,7 @@ func (api *PrivateDebugAPI) GetBadBlocks(ctx context.Context) ([]*BadBlockArgs,
|
|||||||
} else {
|
} else {
|
||||||
blockRlp = fmt.Sprintf("0x%x", rlpBytes)
|
blockRlp = fmt.Sprintf("0x%x", rlpBytes)
|
||||||
}
|
}
|
||||||
if blockJSON, err = ethapi.RPCMarshalBlock(block, true, true); err != nil {
|
if blockJSON, err = ethapi.RPCMarshalBlock(block, true, true, api.eth.engine); err != nil {
|
||||||
blockJSON = map[string]interface{}{"error": err.Error()}
|
blockJSON = map[string]interface{}{"error": err.Error()}
|
||||||
}
|
}
|
||||||
results = append(results, &BadBlockArgs{
|
results = append(results, &BadBlockArgs{
|
||||||
|
@ -465,7 +465,7 @@ func (d *Downloader) syncWithPeer(p *peerConnection, hash common.Hash, td *big.I
|
|||||||
}
|
}
|
||||||
if mode == FastSync && pivot == nil {
|
if mode == FastSync && pivot == nil {
|
||||||
// If no pivot block was returned, the head is below the min full block
|
// If no pivot block was returned, the head is below the min full block
|
||||||
// threshold (i.e. new chian). In that case we won't really fast sync
|
// threshold (i.e. new chain). In that case we won't really fast sync
|
||||||
// anyway, but still need a valid pivot block to avoid some code hitting
|
// anyway, but still need a valid pivot block to avoid some code hitting
|
||||||
// nil panics on an access.
|
// nil panics on an access.
|
||||||
pivot = d.blockchain.CurrentBlock().Header()
|
pivot = d.blockchain.CurrentBlock().Header()
|
||||||
@ -681,7 +681,7 @@ func (d *Downloader) fetchHead(p *peerConnection) (head *types.Header, pivot *ty
|
|||||||
return head, nil, nil
|
return head, nil, nil
|
||||||
}
|
}
|
||||||
// At this point we have 2 headers in total and the first is the
|
// At this point we have 2 headers in total and the first is the
|
||||||
// validated head of the chian. Check the pivot number and return,
|
// validated head of the chain. Check the pivot number and return,
|
||||||
pivot := headers[1]
|
pivot := headers[1]
|
||||||
if pivot.Number.Uint64() != head.Number.Uint64()-uint64(fsMinFullBlocks) {
|
if pivot.Number.Uint64() != head.Number.Uint64()-uint64(fsMinFullBlocks) {
|
||||||
return nil, nil, fmt.Errorf("%w: remote pivot %d != requested %d", errInvalidChain, pivot.Number, head.Number.Uint64()-uint64(fsMinFullBlocks))
|
return nil, nil, fmt.Errorf("%w: remote pivot %d != requested %d", errInvalidChain, pivot.Number, head.Number.Uint64()-uint64(fsMinFullBlocks))
|
||||||
|
@ -43,8 +43,8 @@ import (
|
|||||||
var FullNodeGPO = gasprice.Config{
|
var FullNodeGPO = gasprice.Config{
|
||||||
Blocks: 20,
|
Blocks: 20,
|
||||||
Percentile: 60,
|
Percentile: 60,
|
||||||
MaxHeaderHistory: 0,
|
MaxHeaderHistory: 1024,
|
||||||
MaxBlockHistory: 0,
|
MaxBlockHistory: 1024,
|
||||||
MaxPrice: gasprice.DefaultMaxPrice,
|
MaxPrice: gasprice.DefaultMaxPrice,
|
||||||
IgnorePrice: gasprice.DefaultIgnorePrice,
|
IgnorePrice: gasprice.DefaultIgnorePrice,
|
||||||
}
|
}
|
||||||
|
@ -18,8 +18,10 @@ package gasprice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math"
|
||||||
"math/big"
|
"math/big"
|
||||||
"sort"
|
"sort"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
@ -37,10 +39,6 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
// maxFeeHistory is the maximum number of blocks that can be retrieved for a
|
|
||||||
// fee history request.
|
|
||||||
maxFeeHistory = 1024
|
|
||||||
|
|
||||||
// maxBlockFetchers is the max number of goroutines to spin up to pull blocks
|
// maxBlockFetchers is the max number of goroutines to spin up to pull blocks
|
||||||
// for the fee history calculation (mostly relevant for LES).
|
// for the fee history calculation (mostly relevant for LES).
|
||||||
maxBlockFetchers = 4
|
maxBlockFetchers = 4
|
||||||
@ -54,10 +52,15 @@ type blockFees struct {
|
|||||||
block *types.Block // only set if reward percentiles are requested
|
block *types.Block // only set if reward percentiles are requested
|
||||||
receipts types.Receipts
|
receipts types.Receipts
|
||||||
// filled by processBlock
|
// filled by processBlock
|
||||||
|
results processedFees
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
|
// processedFees contains the results of a processed block and is also used for caching
|
||||||
|
type processedFees struct {
|
||||||
reward []*big.Int
|
reward []*big.Int
|
||||||
baseFee, nextBaseFee *big.Int
|
baseFee, nextBaseFee *big.Int
|
||||||
gasUsedRatio float64
|
gasUsedRatio float64
|
||||||
err error
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// txGasAndReward is sorted in ascending order based on reward
|
// txGasAndReward is sorted in ascending order based on reward
|
||||||
@ -82,15 +85,15 @@ func (s sortGasAndReward) Less(i, j int) bool {
|
|||||||
// fills in the rest of the fields.
|
// fills in the rest of the fields.
|
||||||
func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
||||||
chainconfig := oracle.backend.ChainConfig()
|
chainconfig := oracle.backend.ChainConfig()
|
||||||
if bf.baseFee = bf.header.BaseFee; bf.baseFee == nil {
|
if bf.results.baseFee = bf.header.BaseFee; bf.results.baseFee == nil {
|
||||||
bf.baseFee = new(big.Int)
|
bf.results.baseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) {
|
if chainconfig.IsLondon(big.NewInt(int64(bf.blockNumber + 1))) {
|
||||||
bf.nextBaseFee = misc.CalcBaseFee(chainconfig, bf.header)
|
bf.results.nextBaseFee = misc.CalcBaseFee(chainconfig, bf.header)
|
||||||
} else {
|
} else {
|
||||||
bf.nextBaseFee = new(big.Int)
|
bf.results.nextBaseFee = new(big.Int)
|
||||||
}
|
}
|
||||||
bf.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit)
|
bf.results.gasUsedRatio = float64(bf.header.GasUsed) / float64(bf.header.GasLimit)
|
||||||
if len(percentiles) == 0 {
|
if len(percentiles) == 0 {
|
||||||
// rewards were not requested, return null
|
// rewards were not requested, return null
|
||||||
return
|
return
|
||||||
@ -100,11 +103,11 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bf.reward = make([]*big.Int, len(percentiles))
|
bf.results.reward = make([]*big.Int, len(percentiles))
|
||||||
if len(bf.block.Transactions()) == 0 {
|
if len(bf.block.Transactions()) == 0 {
|
||||||
// return an all zero row if there are no transactions to gather data from
|
// return an all zero row if there are no transactions to gather data from
|
||||||
for i := range bf.reward {
|
for i := range bf.results.reward {
|
||||||
bf.reward[i] = new(big.Int)
|
bf.results.reward[i] = new(big.Int)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -125,7 +128,7 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
|||||||
txIndex++
|
txIndex++
|
||||||
sumGasUsed += sorter[txIndex].gasUsed
|
sumGasUsed += sorter[txIndex].gasUsed
|
||||||
}
|
}
|
||||||
bf.reward[i] = sorter[txIndex].reward
|
bf.results.reward[i] = sorter[txIndex].reward
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,7 +137,7 @@ func (oracle *Oracle) processBlock(bf *blockFees, percentiles []float64) {
|
|||||||
// also returned if requested and available.
|
// also returned if requested and available.
|
||||||
// Note: an error is only returned if retrieving the head header has failed. If there are no
|
// 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.
|
// 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, maxHistory int) (*types.Block, []*types.Receipt, uint64, int, error) {
|
func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.BlockNumber, blocks int) (*types.Block, []*types.Receipt, uint64, int, error) {
|
||||||
var (
|
var (
|
||||||
headBlock rpc.BlockNumber
|
headBlock rpc.BlockNumber
|
||||||
pendingBlock *types.Block
|
pendingBlock *types.Block
|
||||||
@ -167,17 +170,6 @@ func (oracle *Oracle) resolveBlockRange(ctx context.Context, lastBlock rpc.Block
|
|||||||
} else if pendingBlock == nil && lastBlock > headBlock {
|
} else if pendingBlock == nil && lastBlock > headBlock {
|
||||||
return nil, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", errRequestBeyondHead, lastBlock, headBlock)
|
return nil, nil, 0, 0, fmt.Errorf("%w: requested %d, head %d", errRequestBeyondHead, lastBlock, headBlock)
|
||||||
}
|
}
|
||||||
if maxHistory != 0 {
|
|
||||||
// limit retrieval to the given number of latest blocks
|
|
||||||
if tooOldCount := int64(headBlock) - int64(maxHistory) - int64(lastBlock) + int64(blocks); tooOldCount > 0 {
|
|
||||||
// tooOldCount is the number of requested blocks that are too old to be served
|
|
||||||
if int64(blocks) > tooOldCount {
|
|
||||||
blocks -= int(tooOldCount)
|
|
||||||
} else {
|
|
||||||
return nil, nil, 0, 0, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// ensure not trying to retrieve before genesis
|
// ensure not trying to retrieve before genesis
|
||||||
if rpc.BlockNumber(blocks) > lastBlock+1 {
|
if rpc.BlockNumber(blocks) > lastBlock+1 {
|
||||||
blocks = int(lastBlock + 1)
|
blocks = int(lastBlock + 1)
|
||||||
@ -202,6 +194,10 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
|
|||||||
if blocks < 1 {
|
if blocks < 1 {
|
||||||
return common.Big0, nil, nil, nil, nil // returning with no data and no error means there are no retrievable blocks
|
return common.Big0, nil, nil, nil, nil // returning with no data and no error means there are no retrievable blocks
|
||||||
}
|
}
|
||||||
|
maxFeeHistory := oracle.maxHeaderHistory
|
||||||
|
if len(rewardPercentiles) != 0 {
|
||||||
|
maxFeeHistory = oracle.maxBlockHistory
|
||||||
|
}
|
||||||
if blocks > maxFeeHistory {
|
if blocks > maxFeeHistory {
|
||||||
log.Warn("Sanitizing fee history length", "requested", blocks, "truncated", maxFeeHistory)
|
log.Warn("Sanitizing fee history length", "requested", blocks, "truncated", maxFeeHistory)
|
||||||
blocks = maxFeeHistory
|
blocks = maxFeeHistory
|
||||||
@ -214,17 +210,12 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
|
|||||||
return common.Big0, nil, nil, nil, fmt.Errorf("%w: #%d:%f > #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
|
return common.Big0, nil, nil, nil, fmt.Errorf("%w: #%d:%f > #%d:%f", errInvalidPercentile, i-1, rewardPercentiles[i-1], i, p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Only process blocks if reward percentiles were requested
|
|
||||||
maxHistory := oracle.maxHeaderHistory
|
|
||||||
if len(rewardPercentiles) != 0 {
|
|
||||||
maxHistory = oracle.maxBlockHistory
|
|
||||||
}
|
|
||||||
var (
|
var (
|
||||||
pendingBlock *types.Block
|
pendingBlock *types.Block
|
||||||
pendingReceipts []*types.Receipt
|
pendingReceipts []*types.Receipt
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
pendingBlock, pendingReceipts, lastBlock, blocks, err := oracle.resolveBlockRange(ctx, unresolvedLastBlock, blocks, maxHistory)
|
pendingBlock, pendingReceipts, lastBlock, blocks, err := oracle.resolveBlockRange(ctx, unresolvedLastBlock, blocks)
|
||||||
if err != nil || blocks == 0 {
|
if err != nil || blocks == 0 {
|
||||||
return common.Big0, nil, nil, nil, err
|
return common.Big0, nil, nil, nil, err
|
||||||
}
|
}
|
||||||
@ -234,6 +225,10 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
|
|||||||
next = oldestBlock
|
next = oldestBlock
|
||||||
results = make(chan *blockFees, blocks)
|
results = make(chan *blockFees, blocks)
|
||||||
)
|
)
|
||||||
|
percentileKey := make([]byte, 8*len(rewardPercentiles))
|
||||||
|
for i, p := range rewardPercentiles {
|
||||||
|
binary.LittleEndian.PutUint64(percentileKey[i*8:(i+1)*8], math.Float64bits(p))
|
||||||
|
}
|
||||||
for i := 0; i < maxBlockFetchers && i < blocks; i++ {
|
for i := 0; i < maxBlockFetchers && i < blocks; i++ {
|
||||||
go func() {
|
go func() {
|
||||||
for {
|
for {
|
||||||
@ -246,24 +241,38 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
|
|||||||
fees := &blockFees{blockNumber: blockNumber}
|
fees := &blockFees{blockNumber: blockNumber}
|
||||||
if pendingBlock != nil && blockNumber >= pendingBlock.NumberU64() {
|
if pendingBlock != nil && blockNumber >= pendingBlock.NumberU64() {
|
||||||
fees.block, fees.receipts = pendingBlock, pendingReceipts
|
fees.block, fees.receipts = pendingBlock, pendingReceipts
|
||||||
|
fees.header = fees.block.Header()
|
||||||
|
oracle.processBlock(fees, rewardPercentiles)
|
||||||
|
results <- fees
|
||||||
} else {
|
} else {
|
||||||
if len(rewardPercentiles) != 0 {
|
cacheKey := struct {
|
||||||
fees.block, fees.err = oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNumber))
|
number uint64
|
||||||
if fees.block != nil && fees.err == nil {
|
percentiles string
|
||||||
fees.receipts, fees.err = oracle.backend.GetReceipts(ctx, fees.block.Hash())
|
}{blockNumber, string(percentileKey)}
|
||||||
}
|
|
||||||
|
if p, ok := oracle.historyCache.Get(cacheKey); ok {
|
||||||
|
fees.results = p.(processedFees)
|
||||||
|
results <- fees
|
||||||
} else {
|
} else {
|
||||||
fees.header, fees.err = oracle.backend.HeaderByNumber(ctx, rpc.BlockNumber(blockNumber))
|
if len(rewardPercentiles) != 0 {
|
||||||
|
fees.block, fees.err = oracle.backend.BlockByNumber(ctx, rpc.BlockNumber(blockNumber))
|
||||||
|
if fees.block != nil && fees.err == nil {
|
||||||
|
fees.receipts, fees.err = oracle.backend.GetReceipts(ctx, fees.block.Hash())
|
||||||
|
fees.header = fees.block.Header()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fees.header, fees.err = oracle.backend.HeaderByNumber(ctx, rpc.BlockNumber(blockNumber))
|
||||||
|
}
|
||||||
|
if fees.header != nil && fees.err == nil {
|
||||||
|
oracle.processBlock(fees, rewardPercentiles)
|
||||||
|
if fees.err == nil {
|
||||||
|
oracle.historyCache.Add(cacheKey, fees.results)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// send to results even if empty to guarantee that blocks items are sent in total
|
||||||
|
results <- fees
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if fees.block != nil {
|
|
||||||
fees.header = fees.block.Header()
|
|
||||||
}
|
|
||||||
if fees.header != nil {
|
|
||||||
oracle.processBlock(fees, rewardPercentiles)
|
|
||||||
}
|
|
||||||
// send to results even if empty to guarantee that blocks items are sent in total
|
|
||||||
results <- fees
|
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
@ -279,8 +288,8 @@ func (oracle *Oracle) FeeHistory(ctx context.Context, blocks int, unresolvedLast
|
|||||||
return common.Big0, nil, nil, nil, fees.err
|
return common.Big0, nil, nil, nil, fees.err
|
||||||
}
|
}
|
||||||
i := int(fees.blockNumber - oldestBlock)
|
i := int(fees.blockNumber - oldestBlock)
|
||||||
if fees.header != nil {
|
if fees.results.baseFee != nil {
|
||||||
reward[i], baseFee[i], baseFee[i+1], gasUsedRatio[i] = fees.reward, fees.baseFee, fees.nextBaseFee, fees.gasUsedRatio
|
reward[i], baseFee[i], baseFee[i+1], gasUsedRatio[i] = fees.results.reward, fees.results.baseFee, fees.results.nextBaseFee, fees.results.gasUsedRatio
|
||||||
} else {
|
} else {
|
||||||
// getting no block and no error means we are requesting into the future (might happen because of a reorg)
|
// getting no block and no error means we are requesting into the future (might happen because of a reorg)
|
||||||
if i < firstMissing {
|
if i < firstMissing {
|
||||||
|
@ -36,20 +36,20 @@ func TestFeeHistory(t *testing.T) {
|
|||||||
expCount int
|
expCount int
|
||||||
expErr error
|
expErr error
|
||||||
}{
|
}{
|
||||||
{false, 0, 0, 10, 30, nil, 21, 10, nil},
|
{false, 1000, 1000, 10, 30, nil, 21, 10, nil},
|
||||||
{false, 0, 0, 10, 30, []float64{0, 10}, 21, 10, nil},
|
{false, 1000, 1000, 10, 30, []float64{0, 10}, 21, 10, nil},
|
||||||
{false, 0, 0, 10, 30, []float64{20, 10}, 0, 0, errInvalidPercentile},
|
{false, 1000, 1000, 10, 30, []float64{20, 10}, 0, 0, errInvalidPercentile},
|
||||||
{false, 0, 0, 1000000000, 30, nil, 0, 31, nil},
|
{false, 1000, 1000, 1000000000, 30, nil, 0, 31, nil},
|
||||||
{false, 0, 0, 1000000000, rpc.LatestBlockNumber, nil, 0, 33, nil},
|
{false, 1000, 1000, 1000000000, rpc.LatestBlockNumber, nil, 0, 33, nil},
|
||||||
{false, 0, 0, 10, 40, nil, 0, 0, errRequestBeyondHead},
|
{false, 1000, 1000, 10, 40, nil, 0, 0, errRequestBeyondHead},
|
||||||
{true, 0, 0, 10, 40, nil, 0, 0, errRequestBeyondHead},
|
{true, 1000, 1000, 10, 40, nil, 0, 0, errRequestBeyondHead},
|
||||||
{false, 20, 2, 100, rpc.LatestBlockNumber, nil, 13, 20, nil},
|
{false, 20, 2, 100, rpc.LatestBlockNumber, nil, 13, 20, nil},
|
||||||
{false, 20, 2, 100, rpc.LatestBlockNumber, []float64{0, 10}, 31, 2, nil},
|
{false, 20, 2, 100, rpc.LatestBlockNumber, []float64{0, 10}, 31, 2, nil},
|
||||||
{false, 20, 2, 100, 32, []float64{0, 10}, 31, 2, nil},
|
{false, 20, 2, 100, 32, []float64{0, 10}, 31, 2, nil},
|
||||||
{false, 0, 0, 1, rpc.PendingBlockNumber, nil, 0, 0, nil},
|
{false, 1000, 1000, 1, rpc.PendingBlockNumber, nil, 0, 0, nil},
|
||||||
{false, 0, 0, 2, rpc.PendingBlockNumber, nil, 32, 1, nil},
|
{false, 1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 1, nil},
|
||||||
{true, 0, 0, 2, rpc.PendingBlockNumber, nil, 32, 2, nil},
|
{true, 1000, 1000, 2, rpc.PendingBlockNumber, nil, 32, 2, nil},
|
||||||
{true, 0, 0, 2, rpc.PendingBlockNumber, []float64{0, 10}, 32, 2, nil},
|
{true, 1000, 1000, 2, rpc.PendingBlockNumber, []float64{0, 10}, 32, 2, nil},
|
||||||
}
|
}
|
||||||
for i, c := range cases {
|
for i, c := range cases {
|
||||||
config := Config{
|
config := Config{
|
||||||
|
@ -23,10 +23,13 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
|
"github.com/ethereum/go-ethereum/core"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/log"
|
"github.com/ethereum/go-ethereum/log"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
lru "github.com/hashicorp/golang-lru"
|
||||||
)
|
)
|
||||||
|
|
||||||
const sampleNumber = 3 // Number of transactions sampled in a block
|
const sampleNumber = 3 // Number of transactions sampled in a block
|
||||||
@ -53,6 +56,7 @@ type OracleBackend interface {
|
|||||||
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
|
GetReceipts(ctx context.Context, hash common.Hash) (types.Receipts, error)
|
||||||
PendingBlockAndReceipts() (*types.Block, types.Receipts)
|
PendingBlockAndReceipts() (*types.Block, types.Receipts)
|
||||||
ChainConfig() *params.ChainConfig
|
ChainConfig() *params.ChainConfig
|
||||||
|
SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription
|
||||||
}
|
}
|
||||||
|
|
||||||
// Oracle recommends gas prices based on the content of recent
|
// Oracle recommends gas prices based on the content of recent
|
||||||
@ -68,6 +72,7 @@ type Oracle struct {
|
|||||||
|
|
||||||
checkBlocks, percentile int
|
checkBlocks, percentile int
|
||||||
maxHeaderHistory, maxBlockHistory int
|
maxHeaderHistory, maxBlockHistory int
|
||||||
|
historyCache *lru.Cache
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewOracle returns a new gasprice oracle which can recommend suitable
|
// NewOracle returns a new gasprice oracle which can recommend suitable
|
||||||
@ -99,6 +104,20 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
|||||||
} else if ignorePrice.Int64() > 0 {
|
} else if ignorePrice.Int64() > 0 {
|
||||||
log.Info("Gasprice oracle is ignoring threshold set", "threshold", ignorePrice)
|
log.Info("Gasprice oracle is ignoring threshold set", "threshold", ignorePrice)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cache, _ := lru.New(2048)
|
||||||
|
headEvent := make(chan core.ChainHeadEvent, 1)
|
||||||
|
backend.SubscribeChainHeadEvent(headEvent)
|
||||||
|
go func() {
|
||||||
|
var lastHead common.Hash
|
||||||
|
for ev := range headEvent {
|
||||||
|
if ev.Block.ParentHash() != lastHead {
|
||||||
|
cache.Purge()
|
||||||
|
}
|
||||||
|
lastHead = ev.Block.Hash()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
return &Oracle{
|
return &Oracle{
|
||||||
backend: backend,
|
backend: backend,
|
||||||
lastPrice: params.Default,
|
lastPrice: params.Default,
|
||||||
@ -108,6 +127,7 @@ func NewOracle(backend OracleBackend, params Config) *Oracle {
|
|||||||
percentile: percent,
|
percentile: percent,
|
||||||
maxHeaderHistory: params.MaxHeaderHistory,
|
maxHeaderHistory: params.MaxHeaderHistory,
|
||||||
maxBlockHistory: params.MaxBlockHistory,
|
maxBlockHistory: params.MaxBlockHistory,
|
||||||
|
historyCache: cache,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,6 +29,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
"github.com/ethereum/go-ethereum/core/vm"
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
"github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/ethereum/go-ethereum/event"
|
||||||
"github.com/ethereum/go-ethereum/params"
|
"github.com/ethereum/go-ethereum/params"
|
||||||
"github.com/ethereum/go-ethereum/rpc"
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
)
|
)
|
||||||
@ -90,6 +91,10 @@ func (b *testBackend) ChainConfig() *params.ChainConfig {
|
|||||||
return b.chain.Config()
|
return b.chain.Config()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *testBackend) SubscribeChainHeadEvent(ch chan<- core.ChainHeadEvent) event.Subscription {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBackend {
|
func newTestBackend(t *testing.T, londonBlock *big.Int, pending bool) *testBackend {
|
||||||
var (
|
var (
|
||||||
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
|
||||||
|
@ -76,6 +76,13 @@ type AncientReader interface {
|
|||||||
// Ancient retrieves an ancient binary blob from the append-only immutable files.
|
// Ancient retrieves an ancient binary blob from the append-only immutable files.
|
||||||
Ancient(kind string, number uint64) ([]byte, error)
|
Ancient(kind string, number uint64) ([]byte, error)
|
||||||
|
|
||||||
|
// ReadAncients retrieves multiple items in sequence, starting from the index 'start'.
|
||||||
|
// It will return
|
||||||
|
// - at most 'count' items,
|
||||||
|
// - at least 1 item (even if exceeding the maxBytes), but will otherwise
|
||||||
|
// return as many items as fit into maxBytes.
|
||||||
|
ReadAncients(kind string, start, count, maxBytes uint64) ([][]byte, error)
|
||||||
|
|
||||||
// Ancients returns the ancient item numbers in the ancient store.
|
// Ancients returns the ancient item numbers in the ancient store.
|
||||||
Ancients() (uint64, error)
|
Ancients() (uint64, error)
|
||||||
|
|
||||||
|
16
go.mod
16
go.mod
@ -8,6 +8,7 @@ require (
|
|||||||
github.com/Azure/go-autorest/autorest/adal v0.8.0 // indirect
|
github.com/Azure/go-autorest/autorest/adal v0.8.0 // indirect
|
||||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6 // indirect
|
||||||
github.com/VictoriaMetrics/fastcache v1.6.0
|
github.com/VictoriaMetrics/fastcache v1.6.0
|
||||||
|
github.com/aws/aws-sdk-go v1.41.4
|
||||||
github.com/aws/aws-sdk-go-v2 v1.2.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/config v1.1.1
|
||||||
github.com/aws/aws-sdk-go-v2/credentials v1.1.1
|
github.com/aws/aws-sdk-go-v2/credentials v1.1.1
|
||||||
@ -18,6 +19,7 @@ require (
|
|||||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f
|
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f
|
||||||
github.com/davecgh/go-spew v1.1.1
|
github.com/davecgh/go-spew v1.1.1
|
||||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
|
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea
|
||||||
|
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||||
github.com/dlclark/regexp2 v1.2.0 // indirect
|
github.com/dlclark/regexp2 v1.2.0 // indirect
|
||||||
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf
|
github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf
|
||||||
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498
|
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498
|
||||||
@ -39,13 +41,15 @@ require (
|
|||||||
github.com/holiman/uint256 v1.2.0
|
github.com/holiman/uint256 v1.2.0
|
||||||
github.com/huin/goupnp v1.0.2
|
github.com/huin/goupnp v1.0.2
|
||||||
github.com/influxdata/influxdb v1.8.3
|
github.com/influxdata/influxdb v1.8.3
|
||||||
|
github.com/influxdata/influxdb-client-go/v2 v2.4.0
|
||||||
|
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 // indirect
|
||||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458
|
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458
|
||||||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e
|
||||||
github.com/julienschmidt/httprouter v1.2.0
|
github.com/julienschmidt/httprouter v1.2.0
|
||||||
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356
|
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356
|
||||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.0
|
github.com/mattn/go-colorable v0.1.8
|
||||||
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035
|
github.com/mattn/go-isatty v0.0.12
|
||||||
github.com/naoina/go-stringutil v0.1.0 // indirect
|
github.com/naoina/go-stringutil v0.1.0 // indirect
|
||||||
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
|
github.com/naoina/toml v0.1.2-0.20170918210437-9fafd6967416
|
||||||
github.com/olekukonko/tablewriter v0.0.5
|
github.com/olekukonko/tablewriter v0.0.5
|
||||||
@ -53,6 +57,7 @@ require (
|
|||||||
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7
|
github.com/peterh/liner v1.1.1-0.20190123174540-a2c9a5303de7
|
||||||
github.com/prometheus/tsdb v0.7.1
|
github.com/prometheus/tsdb v0.7.1
|
||||||
github.com/rjeczalik/notify v0.9.1
|
github.com/rjeczalik/notify v0.9.1
|
||||||
|
github.com/robertkrimen/otto v0.0.0-20211008084715-4eacda02dd21
|
||||||
github.com/rs/cors v1.7.0
|
github.com/rs/cors v1.7.0
|
||||||
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible
|
||||||
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4
|
github.com/status-im/keycard-go v0.0.0-20190316090335-8537d3370df4
|
||||||
@ -61,13 +66,14 @@ require (
|
|||||||
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
github.com/tklauser/go-sysconf v0.3.5 // indirect
|
||||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
|
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d // indirect
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da
|
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912
|
||||||
golang.org/x/text v0.3.6
|
golang.org/x/text v0.3.6
|
||||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
|
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba
|
||||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
|
||||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
|
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6
|
||||||
gopkg.in/urfave/cli.v1 v1.20.0
|
gopkg.in/urfave/cli.v1 v1.20.0
|
||||||
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gotest.tools v2.2.0+incompatible // indirect
|
gotest.tools v2.2.0+incompatible // indirect
|
||||||
)
|
)
|
||||||
|
73
go.sum
73
go.sum
@ -33,6 +33,7 @@ github.com/Azure/go-autorest/autorest/date v0.2.0 h1:yW+Zlqf26583pE43KhfnhFcdmSW
|
|||||||
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
github.com/Azure/go-autorest/autorest/date v0.2.0/go.mod h1:vcORJHLJEh643/Ioh9+vPmf1Ij9AEBM5FuBIXLmIy0g=
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
github.com/Azure/go-autorest/autorest/mocks v0.1.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
github.com/Azure/go-autorest/autorest/mocks v0.2.0/go.mod h1:OTyCOPRA2IgIlWxVYxBee2F5Gr4kF2zd2J5cFRaIDN0=
|
||||||
|
github.com/Azure/go-autorest/autorest/mocks v0.3.0 h1:qJumjCaCudz+OcqE9/XtEPfvtOjOmKaui4EOpFI6zZc=
|
||||||
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
github.com/Azure/go-autorest/autorest/mocks v0.3.0/go.mod h1:a8FDP3DYzQ4RYfVAxAN3SVSiiO77gL2j2ronKKP0syM=
|
||||||
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
|
github.com/Azure/go-autorest/logger v0.1.0 h1:ruG4BSDXONFRrZZJ2GUXDiUyVpayPmb1GnWeHDdaNKY=
|
||||||
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
github.com/Azure/go-autorest/logger v0.1.0/go.mod h1:oExouG+K6PryycPJfVSxi/koC6LSNgds39diKLz7Vrc=
|
||||||
@ -54,6 +55,8 @@ github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah
|
|||||||
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
|
||||||
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8=
|
||||||
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
|
github.com/apache/arrow/go/arrow v0.0.0-20191024131854-af6fa24be0db/go.mod h1:VTxUBvSJ3s3eHAg65PNgrsn5BtqCRPdmyXh6rAfdxN0=
|
||||||
|
github.com/aws/aws-sdk-go v1.41.4 h1:5xRzZp8LfBFfowMPxmoNsxLBZOY/NTH4EeI7q2F5eWE=
|
||||||
|
github.com/aws/aws-sdk-go v1.41.4/go.mod h1:585smgzpB/KqRA+K3y/NL/oYRqQvpNJYvLm+LY1U59Q=
|
||||||
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 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 v1.2.0/go.mod h1:zEQs02YRBw1DjK0PoJv3ygDYOFTre1ejlJWl8FwAuQo=
|
||||||
github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo=
|
github.com/aws/aws-sdk-go-v2/config v1.1.1 h1:ZAoq32boMzcaTW9bcUacBswAmHTbvlvDJICgHFZuECo=
|
||||||
@ -103,6 +106,7 @@ github.com/consensys/bavard v0.1.8-0.20210406032232-f3452dc9b572/go.mod h1:Bpd0/
|
|||||||
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 h1:C43yEtQ6NIf4ftFXD/V55gnGFgPbMQobd//YlnLjUJ8=
|
||||||
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
|
github.com/consensys/gnark-crypto v0.4.1-0.20210426202927-39ac3d4b3f1f/go.mod h1:815PAHg3wvysy0SyIqanF8gZ0Y1wjk/hrDHD/iT88+Q=
|
||||||
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-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
|
||||||
|
github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4=
|
||||||
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
github.com/dave/jennifer v1.2.0/go.mod h1:fIb+770HOpJ2fmN9EPPKOqm1vMGhB+TwXKMZhrIygKg=
|
||||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@ -110,6 +114,9 @@ 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/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
|
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea h1:j4317fAZh7X6GqbFowYdYdI0L9bwxL07jyPZIdepyZ0=
|
||||||
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
github.com/deckarep/golang-set v0.0.0-20180603214616-504e848d77ea/go.mod h1:93vsz/8Wt4joVM7c2AVqh+YRMiUSc14yDtF28KmMOgQ=
|
||||||
|
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/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
|
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/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-bitstream v0.0.0-20180413035011-3522498ce2c8/go.mod h1:VMaSuZ+SZcx/wljOQKvp5srsbCiKDEb6K2wC4+PiBmQ=
|
||||||
@ -135,8 +142,12 @@ github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWo
|
|||||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
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 h1:tY80oXqGNY4FhTFhk+o9oFHGINQ/+vhlm8HFzi6znCI=
|
||||||
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/go.mod h1:x7DCsMOv1taUwEWCzT4cmDeAkigA5/QCwUodaVOe8Ww=
|
github.com/gballet/go-libpcsclite v0.0.0-20190607065134-2772fd86a8ff/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 v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||||
github.com/glycerine/go-unsnap-stream v0.0.0-20180323001048-9f0cb55181dd/go.mod h1:/20jfyN9Y5QPEAprSgKAUr+glWDY39ZiUEAYOEv5dsE=
|
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/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-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
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-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
|
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
|
||||||
@ -146,6 +157,8 @@ github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80n
|
|||||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||||
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
github.com/go-ole/go-ole v1.2.1 h1:2lOsA72HgjxAuMlKpFiCbHTvu44PIVkZ5hqm3RSdI/E=
|
||||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-sourcemap/sourcemap v2.1.2+incompatible h1:0b/xya7BKGhXuqFESKM4oIiRo9WOt2ebz7KxfreD6ug=
|
github.com/go-sourcemap/sourcemap v2.1.2+incompatible h1:0b/xya7BKGhXuqFESKM4oIiRo9WOt2ebz7KxfreD6ug=
|
||||||
github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
github.com/go-sourcemap/sourcemap v2.1.2+incompatible/go.mod h1:F8jJfvm2KbVjc5NqelyYJmf/v5J0dwNLS2mL4sNA1Jg=
|
||||||
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
github.com/go-sql-driver/mysql v1.4.1/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
|
||||||
@ -178,6 +191,7 @@ github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEW
|
|||||||
github.com/golang/snappy v0.0.3/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 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
|
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219/go.mod h1:/X8TswGSh1pIozq4ZwCfxS0WA5JGXguxk94ar/4c87Y=
|
||||||
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
|
||||||
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
github.com/google/flatbuffers v1.11.0/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8=
|
||||||
@ -200,6 +214,7 @@ github.com/google/uuid v1.1.5/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
|
|||||||
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
|
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/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
|
||||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||||
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 h1:sezaKhEfPFg8W0Enm61B9Gs911H8iesGY5R8NDPtd1M=
|
github.com/graph-gophers/graphql-go v0.0.0-20201113091052-beb923fada29 h1:sezaKhEfPFg8W0Enm61B9Gs911H8iesGY5R8NDPtd1M=
|
||||||
@ -221,8 +236,13 @@ github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANyt
|
|||||||
github.com/influxdata/flux v0.65.1/go.mod h1:J754/zds0vvpfwuq7Gc2wRdVwEodfpCFM7mYlOw2LqY=
|
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 h1:WEypI1BQFTT4teLM+1qkEcvUi0dAvopAI/ir0vAiBg8=
|
||||||
github.com/influxdata/influxdb v1.8.3/go.mod h1:JugdFhsvvI8gadxOI6noqNeeBHvWNTbfYGtiAn+2jhI=
|
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/influxql v1.1.1-0.20200828144457-65d3ef77d385/go.mod h1:gHp9y86a/pxhjJ+zMjNXiQAA197Xk9wLxaz+fGG+kWk=
|
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-20180522152040-32c6aa80de5e/go.mod h1:4kt73NQhadE3daL3WhR5EJ/J2ocX0PZzwxQ0gXJ7oFE=
|
||||||
|
github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
|
||||||
|
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097 h1:vilfsDSy7TDxedi9gyBkMvAirat/oRcL0lFdJBf6tdM=
|
||||||
|
github.com/influxdata/line-protocol v0.0.0-20210311194329-9aa0e372d097/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo=
|
||||||
github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8=
|
github.com/influxdata/promql/v2 v2.12.0/go.mod h1:fxOPu+DY0bqCTCECchSRtWfc+0X19ybifQhZoQNF5D8=
|
||||||
github.com/influxdata/roaring v0.4.13-0.20180809181101-fc520f41fab6/go.mod h1:bSgUQ7q5ZLSO+bKBGqJiCBGAl+9DxyW63zLTujjUlOE=
|
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/tdigest v0.0.0-20181121200506-bf2b5ad3c0a9/go.mod h1:Js0mqiSBE6Ffsg94weZZ2c+v/ciT8QRHFOap7EKDrR0=
|
||||||
@ -232,7 +252,9 @@ github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH
|
|||||||
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 h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U=
|
||||||
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
|
github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU=
|
||||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
|
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
|
||||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||||
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8=
|
||||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||||
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
|
||||||
@ -263,18 +285,27 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
|||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
|
github.com/labstack/echo/v4 v4.2.1/go.mod h1:AA49e0DZ8kk5jTOOCKNuPR6oTnBS0dYiM4FW1e6jwpg=
|
||||||
|
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 h1:fQjYxZaynp97ozCzfOyOuAGOU4aU/z37zf/tOujFk7c=
|
||||||
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
|
github.com/leanovate/gopter v0.2.9/go.mod h1:U2L/78B+KVFIx2VmW6onHJQzXtFb+p5y3y2Sh+Jxxv8=
|
||||||
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
|
||||||
|
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/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.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||||
github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o=
|
github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
|
||||||
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
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-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
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 h1:oNAwILwmgWKFpuU+dXvI6dl9jG2mAWAZLX3r9s0PPiw=
|
||||||
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
|
||||||
github.com/mattn/go-isatty v0.0.4/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.5-0.20180830101745-3fb116b82035 h1:USWjF42jDCSEeikX/G1g40ZWnsPXN5WkZ4jMHZWyBK4=
|
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||||
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||||
github.com/mattn/go-runewidth v0.0.3/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 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.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
|
||||||
@ -337,6 +368,8 @@ github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40T
|
|||||||
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
|
github.com/retailnext/hllpp v1.0.1-0.20180308014038-101a6d2f8b52/go.mod h1:RDpi1RftBQPUCDRw6SmxeaREsAaRKnOclghuzp/WRzc=
|
||||||
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
|
github.com/rjeczalik/notify v0.9.1 h1:CLCKso/QK1snAlnhNR/CNvNiFU2saUtjV0bx3EwNeCE=
|
||||||
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
|
github.com/rjeczalik/notify v0.9.1/go.mod h1:rKwnCoCGeuQnwBtTSPL9Dad03Vh2n40ePRrjvIXnJho=
|
||||||
|
github.com/robertkrimen/otto v0.0.0-20211008084715-4eacda02dd21 h1:uMgr5kPPCGOlEPx6lE8GPYjFkAN4ZDA9FX++QjIZn6Q=
|
||||||
|
github.com/robertkrimen/otto v0.0.0-20211008084715-4eacda02dd21/go.mod h1:/mK7FZ3mFYEn9zvNPhpngTyatyehSwte5bJZ4ehL5Xw=
|
||||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||||
github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik=
|
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/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||||
@ -362,6 +395,7 @@ github.com/stretchr/testify v1.2.0/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
|
|||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
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.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.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
|
||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs=
|
github.com/syndtr/goleveldb v1.0.1-0.20210305035536-64b5b1c73954 h1:xQdMZ1WLrgkkvOZ/LDQxjVxMLdby7osSh4ZEVa5sIjs=
|
||||||
@ -374,6 +408,9 @@ github.com/tklauser/numcpus v0.2.2/go.mod h1:x3qojaO3uyYt0i56EW/VUYs7uBvdl2fkfZF
|
|||||||
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 h1:wHSqTBrZW24CsNJDfeh9Ex6Pm0Rcpc7qrgKBiL44vF4=
|
||||||
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
|
||||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||||
|
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/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
github.com/willf/bitset v1.1.3/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
|
||||||
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
github.com/xlab/treeprint v0.0.0-20180616005107-d6fb6747feb6/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||||
@ -391,6 +428,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U
|
|||||||
golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/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-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-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 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20180321215751-8460e604b9de/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
@ -438,11 +477,14 @@ golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/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-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/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-20201021035429-f5854403a974/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-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-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q=
|
|
||||||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d h1:20cMwl2fHAzkJMEA+8J4JgqBQcQGzbisXo31MIeenXI=
|
||||||
|
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-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-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@ -464,6 +506,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
|
|||||||
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/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-20181116152217-5ac8a444bdc5/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-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-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@ -471,23 +514,31 @@ golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-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-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-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/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-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/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-20200930185726-fdedc70b468f/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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/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-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-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210420205809-ac73e9fd8988/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 h1:b3NXsE2LusjYGGjL5bxEVZZORm/YEFFrWFjR8eFrw/c=
|
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912 h1:uCLL3g5wH2xjxVREVuAbP9JM5PPKjRbXKRa6IBjkzmU=
|
||||||
|
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/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 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@ -495,12 +546,14 @@ golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3
|
|||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
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 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/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-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324 h1:Hir2P/De0WpUhtrKGGjvSb2YxUgyZ7EFOSLIcSSpiwE=
|
|
||||||
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324/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/tools v0.0.0-20180525024113-a5b4c53f6e8b/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-20180917221912-90fa682c2a6e/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-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
@ -587,6 +640,9 @@ gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7
|
|||||||
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
|
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
|
||||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0=
|
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6 h1:a6cXbcDDUkSBlpnkWV1bJ+vv3mOgQEltEJ2rPxroVu0=
|
||||||
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
|
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20200619000410-60c24ae608a6/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
|
||||||
|
gopkg.in/readline.v1 v1.0.0-20160726135117-62c6fe619375/go.mod h1:lNEQeAhU009zbRxng+XOj5ITVgY24WcbNnQopyfKoYQ=
|
||||||
|
gopkg.in/sourcemap.v1 v1.0.5 h1:inv58fC9f9J3TK2Y2R1NPntXEn3/wjWHkonhIUODNTI=
|
||||||
|
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
|
||||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
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/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 h1:NdAVW6RYxDif9DhDHaAortIu956m2c0v+09AZBPTbE0=
|
||||||
@ -596,8 +652,9 @@ 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=
|
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
|
|
||||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
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 h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
|
@ -32,6 +32,7 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
"github.com/ethereum/go-ethereum/common/math"
|
||||||
|
"github.com/ethereum/go-ethereum/consensus"
|
||||||
"github.com/ethereum/go-ethereum/consensus/clique"
|
"github.com/ethereum/go-ethereum/consensus/clique"
|
||||||
"github.com/ethereum/go-ethereum/consensus/ethash"
|
"github.com/ethereum/go-ethereum/consensus/ethash"
|
||||||
"github.com/ethereum/go-ethereum/consensus/misc"
|
"github.com/ethereum/go-ethereum/consensus/misc"
|
||||||
@ -1175,7 +1176,8 @@ func FormatLogs(logs []vm.StructLog) []StructLogRes {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RPCMarshalHeader converts the given header to the RPC output .
|
// RPCMarshalHeader converts the given header to the RPC output .
|
||||||
func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
func RPCMarshalHeader(head *types.Header, engine consensus.Engine) map[string]interface{} {
|
||||||
|
miner, _ := engine.Author(head)
|
||||||
result := map[string]interface{}{
|
result := map[string]interface{}{
|
||||||
"number": (*hexutil.Big)(head.Number),
|
"number": (*hexutil.Big)(head.Number),
|
||||||
"hash": head.Hash(),
|
"hash": head.Hash(),
|
||||||
@ -1185,7 +1187,7 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
|||||||
"sha3Uncles": head.UncleHash,
|
"sha3Uncles": head.UncleHash,
|
||||||
"logsBloom": head.Bloom,
|
"logsBloom": head.Bloom,
|
||||||
"stateRoot": head.Root,
|
"stateRoot": head.Root,
|
||||||
"miner": head.Coinbase,
|
"miner": miner,
|
||||||
"difficulty": (*hexutil.Big)(head.Difficulty),
|
"difficulty": (*hexutil.Big)(head.Difficulty),
|
||||||
"extraData": hexutil.Bytes(head.Extra),
|
"extraData": hexutil.Bytes(head.Extra),
|
||||||
"size": hexutil.Uint64(head.Size()),
|
"size": hexutil.Uint64(head.Size()),
|
||||||
@ -1206,8 +1208,8 @@ func RPCMarshalHeader(head *types.Header) map[string]interface{} {
|
|||||||
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
|
// RPCMarshalBlock converts the given block to the RPC output which depends on fullTx. If inclTx is true transactions are
|
||||||
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
|
// returned. When fullTx is true the returned block contains full transaction details, otherwise it will only contain
|
||||||
// transaction hashes.
|
// transaction hashes.
|
||||||
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool, engine consensus.Engine) (map[string]interface{}, error) {
|
||||||
fields := RPCMarshalHeader(block.Header())
|
fields := RPCMarshalHeader(block.Header(), engine)
|
||||||
fields["size"] = hexutil.Uint64(block.Size())
|
fields["size"] = hexutil.Uint64(block.Size())
|
||||||
|
|
||||||
if inclTx {
|
if inclTx {
|
||||||
@ -1242,7 +1244,7 @@ func RPCMarshalBlock(block *types.Block, inclTx bool, fullTx bool) (map[string]i
|
|||||||
// rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires
|
// rpcMarshalHeader uses the generalized output filler, then adds the total difficulty field, which requires
|
||||||
// a `PublicBlockchainAPI`.
|
// a `PublicBlockchainAPI`.
|
||||||
func (s *PublicBlockChainAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} {
|
func (s *PublicBlockChainAPI) rpcMarshalHeader(ctx context.Context, header *types.Header) map[string]interface{} {
|
||||||
fields := RPCMarshalHeader(header)
|
fields := RPCMarshalHeader(header, s.b.Engine())
|
||||||
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, header.Hash()))
|
fields["totalDifficulty"] = (*hexutil.Big)(s.b.GetTd(ctx, header.Hash()))
|
||||||
return fields
|
return fields
|
||||||
}
|
}
|
||||||
@ -1250,7 +1252,7 @@ func (s *PublicBlockChainAPI) rpcMarshalHeader(ctx context.Context, header *type
|
|||||||
// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires
|
// rpcMarshalBlock uses the generalized output filler, then adds the total difficulty field, which requires
|
||||||
// a `PublicBlockchainAPI`.
|
// a `PublicBlockchainAPI`.
|
||||||
func (s *PublicBlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
func (s *PublicBlockChainAPI) rpcMarshalBlock(ctx context.Context, b *types.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
|
||||||
fields, err := RPCMarshalBlock(b, inclTx, fullTx)
|
fields, err := RPCMarshalBlock(b, inclTx, fullTx, s.b.Engine())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -171,7 +171,7 @@ func (args *TransactionArgs) setDefaults(ctx context.Context, b Backend) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ToMessage converts th transaction arguments to the Message type used by the
|
// ToMessage converts the transaction arguments to the Message type used by the
|
||||||
// core evm. This method is used in calls and traces that do not require a real
|
// core evm. This method is used in calls and traces that do not require a real
|
||||||
// live transaction.
|
// live transaction.
|
||||||
func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (types.Message, error) {
|
func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (types.Message, error) {
|
||||||
@ -238,7 +238,7 @@ func (args *TransactionArgs) ToMessage(globalGasCap uint64, baseFee *big.Int) (t
|
|||||||
if args.AccessList != nil {
|
if args.AccessList != nil {
|
||||||
accessList = *args.AccessList
|
accessList = *args.AccessList
|
||||||
}
|
}
|
||||||
msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, false)
|
msg := types.NewMessage(addr, args.To, 0, value, gas, gasPrice, gasFeeCap, gasTipCap, data, accessList, true)
|
||||||
return msg, nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
|
|||||||
from := statedb.GetOrNewStateObject(bankAddr)
|
from := statedb.GetOrNewStateObject(bankAddr)
|
||||||
from.SetBalance(math.MaxBig256)
|
from.SetBalance(math.MaxBig256)
|
||||||
|
|
||||||
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, false)}
|
msg := callmsg{types.NewMessage(from.Address(), &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)}
|
||||||
|
|
||||||
context := core.NewEVMBlockContext(header, bc, nil)
|
context := core.NewEVMBlockContext(header, bc, nil)
|
||||||
txContext := core.NewEVMTxContext(msg)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
@ -150,7 +150,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, config *params.Chai
|
|||||||
header := lc.GetHeaderByHash(bhash)
|
header := lc.GetHeaderByHash(bhash)
|
||||||
state := light.NewState(ctx, header, lc.Odr())
|
state := light.NewState(ctx, header, lc.Odr())
|
||||||
state.SetBalance(bankAddr, math.MaxBig256)
|
state.SetBalance(bankAddr, math.MaxBig256)
|
||||||
msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, false)}
|
msg := callmsg{types.NewMessage(bankAddr, &testContractAddr, 0, new(big.Int), 100000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)}
|
||||||
context := core.NewEVMBlockContext(header, lc, nil)
|
context := core.NewEVMBlockContext(header, lc, nil)
|
||||||
txContext := core.NewEVMTxContext(msg)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
vmenv := vm.NewEVM(context, txContext, state, config, vm.Config{NoBaseFee: true})
|
vmenv := vm.NewEVM(context, txContext, state, config, vm.Config{NoBaseFee: true})
|
||||||
|
@ -194,7 +194,7 @@ func odrContractCall(ctx context.Context, db ethdb.Database, bc *core.BlockChain
|
|||||||
|
|
||||||
// Perform read-only call.
|
// Perform read-only call.
|
||||||
st.SetBalance(testBankAddress, math.MaxBig256)
|
st.SetBalance(testBankAddress, math.MaxBig256)
|
||||||
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, false)}
|
msg := callmsg{types.NewMessage(testBankAddress, &testContractAddr, 0, new(big.Int), 1000000, big.NewInt(params.InitialBaseFee), big.NewInt(params.InitialBaseFee), new(big.Int), data, nil, true)}
|
||||||
txContext := core.NewEVMTxContext(msg)
|
txContext := core.NewEVMTxContext(msg)
|
||||||
context := core.NewEVMBlockContext(header, chain, nil)
|
context := core.NewEVMBlockContext(header, chain, nil)
|
||||||
vmenv := vm.NewEVM(context, txContext, st, config, vm.Config{NoBaseFee: true})
|
vmenv := vm.NewEVM(context, txContext, st, config, vm.Config{NoBaseFee: true})
|
||||||
|
@ -28,6 +28,11 @@ type Config struct {
|
|||||||
InfluxDBUsername string `toml:",omitempty"`
|
InfluxDBUsername string `toml:",omitempty"`
|
||||||
InfluxDBPassword string `toml:",omitempty"`
|
InfluxDBPassword string `toml:",omitempty"`
|
||||||
InfluxDBTags string `toml:",omitempty"`
|
InfluxDBTags string `toml:",omitempty"`
|
||||||
|
|
||||||
|
EnableInfluxDBV2 bool `toml:",omitempty"`
|
||||||
|
InfluxDBToken string `toml:",omitempty"`
|
||||||
|
InfluxDBBucket string `toml:",omitempty"`
|
||||||
|
InfluxDBOrganization string `toml:",omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// DefaultConfig is the default config for metrics used in go-ethereum.
|
// DefaultConfig is the default config for metrics used in go-ethereum.
|
||||||
@ -42,4 +47,10 @@ var DefaultConfig = Config{
|
|||||||
InfluxDBUsername: "test",
|
InfluxDBUsername: "test",
|
||||||
InfluxDBPassword: "test",
|
InfluxDBPassword: "test",
|
||||||
InfluxDBTags: "host=localhost",
|
InfluxDBTags: "host=localhost",
|
||||||
|
|
||||||
|
// influxdbv2-specific flags
|
||||||
|
EnableInfluxDBV2: false,
|
||||||
|
InfluxDBToken: "test",
|
||||||
|
InfluxDBBucket: "geth",
|
||||||
|
InfluxDBOrganization: "geth",
|
||||||
}
|
}
|
||||||
|
223
metrics/influxdb/influxdbv2.go
Normal file
223
metrics/influxdb/influxdbv2.go
Normal file
@ -0,0 +1,223 @@
|
|||||||
|
//
|
||||||
|
// The go-ethereum library is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU Lesser General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU Lesser General Public License
|
||||||
|
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
package influxdb
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/log"
|
||||||
|
"github.com/ethereum/go-ethereum/metrics"
|
||||||
|
influxdb2 "github.com/influxdata/influxdb-client-go/v2"
|
||||||
|
"github.com/influxdata/influxdb-client-go/v2/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
type v2Reporter struct {
|
||||||
|
reg metrics.Registry
|
||||||
|
interval time.Duration
|
||||||
|
|
||||||
|
endpoint string
|
||||||
|
token string
|
||||||
|
bucket string
|
||||||
|
organization string
|
||||||
|
namespace string
|
||||||
|
tags map[string]string
|
||||||
|
|
||||||
|
client influxdb2.Client
|
||||||
|
write api.WriteAPI
|
||||||
|
|
||||||
|
cache map[string]int64
|
||||||
|
}
|
||||||
|
|
||||||
|
// InfluxDBWithTags starts a InfluxDB reporter which will post the from the given metrics.Registry at each d interval with the specified tags
|
||||||
|
func InfluxDBV2WithTags(r metrics.Registry, d time.Duration, endpoint string, token string, bucket string, organization string, namespace string, tags map[string]string) {
|
||||||
|
rep := &v2Reporter{
|
||||||
|
reg: r,
|
||||||
|
interval: d,
|
||||||
|
endpoint: endpoint,
|
||||||
|
token: token,
|
||||||
|
bucket: bucket,
|
||||||
|
organization: organization,
|
||||||
|
namespace: namespace,
|
||||||
|
tags: tags,
|
||||||
|
cache: make(map[string]int64),
|
||||||
|
}
|
||||||
|
|
||||||
|
rep.client = influxdb2.NewClient(rep.endpoint, rep.token)
|
||||||
|
defer rep.client.Close()
|
||||||
|
|
||||||
|
// async write client
|
||||||
|
rep.write = rep.client.WriteAPI(rep.organization, rep.bucket)
|
||||||
|
errorsCh := rep.write.Errors()
|
||||||
|
|
||||||
|
// have to handle write errors in a separate goroutine like this b/c the channel is unbuffered and will block writes if not read
|
||||||
|
go func() {
|
||||||
|
for err := range errorsCh {
|
||||||
|
log.Warn("write error", "err", err.Error())
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
rep.run()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *v2Reporter) run() {
|
||||||
|
intervalTicker := time.Tick(r.interval)
|
||||||
|
pingTicker := time.Tick(time.Second * 5)
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-intervalTicker:
|
||||||
|
r.send()
|
||||||
|
case <-pingTicker:
|
||||||
|
_, err := r.client.Health(context.Background())
|
||||||
|
if err != nil {
|
||||||
|
log.Warn("Got error from influxdb client health check", "err", err.Error())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *v2Reporter) send() {
|
||||||
|
r.reg.Each(func(name string, i interface{}) {
|
||||||
|
now := time.Now()
|
||||||
|
namespace := r.namespace
|
||||||
|
|
||||||
|
switch metric := i.(type) {
|
||||||
|
|
||||||
|
case metrics.Counter:
|
||||||
|
v := metric.Count()
|
||||||
|
l := r.cache[name]
|
||||||
|
|
||||||
|
measurement := fmt.Sprintf("%s%s.count", namespace, name)
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"value": v - l,
|
||||||
|
}
|
||||||
|
|
||||||
|
pt := influxdb2.NewPoint(measurement, r.tags, fields, now)
|
||||||
|
r.write.WritePoint(pt)
|
||||||
|
|
||||||
|
r.cache[name] = v
|
||||||
|
|
||||||
|
case metrics.Gauge:
|
||||||
|
ms := metric.Snapshot()
|
||||||
|
|
||||||
|
measurement := fmt.Sprintf("%s%s.gauge", namespace, name)
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"value": ms.Value(),
|
||||||
|
}
|
||||||
|
|
||||||
|
pt := influxdb2.NewPoint(measurement, r.tags, fields, now)
|
||||||
|
r.write.WritePoint(pt)
|
||||||
|
|
||||||
|
case metrics.GaugeFloat64:
|
||||||
|
ms := metric.Snapshot()
|
||||||
|
|
||||||
|
measurement := fmt.Sprintf("%s%s.gauge", namespace, name)
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"value": ms.Value(),
|
||||||
|
}
|
||||||
|
|
||||||
|
pt := influxdb2.NewPoint(measurement, r.tags, fields, now)
|
||||||
|
r.write.WritePoint(pt)
|
||||||
|
|
||||||
|
case metrics.Histogram:
|
||||||
|
ms := metric.Snapshot()
|
||||||
|
|
||||||
|
if ms.Count() > 0 {
|
||||||
|
ps := ms.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999})
|
||||||
|
measurement := fmt.Sprintf("%s%s.histogram", namespace, name)
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"count": ms.Count(),
|
||||||
|
"max": ms.Max(),
|
||||||
|
"mean": ms.Mean(),
|
||||||
|
"min": ms.Min(),
|
||||||
|
"stddev": ms.StdDev(),
|
||||||
|
"variance": ms.Variance(),
|
||||||
|
"p50": ps[0],
|
||||||
|
"p75": ps[1],
|
||||||
|
"p95": ps[2],
|
||||||
|
"p99": ps[3],
|
||||||
|
"p999": ps[4],
|
||||||
|
"p9999": ps[5],
|
||||||
|
}
|
||||||
|
|
||||||
|
pt := influxdb2.NewPoint(measurement, r.tags, fields, now)
|
||||||
|
r.write.WritePoint(pt)
|
||||||
|
}
|
||||||
|
|
||||||
|
case metrics.Meter:
|
||||||
|
ms := metric.Snapshot()
|
||||||
|
|
||||||
|
measurement := fmt.Sprintf("%s%s.meter", namespace, name)
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"count": ms.Count(),
|
||||||
|
"m1": ms.Rate1(),
|
||||||
|
"m5": ms.Rate5(),
|
||||||
|
"m15": ms.Rate15(),
|
||||||
|
"mean": ms.RateMean(),
|
||||||
|
}
|
||||||
|
|
||||||
|
pt := influxdb2.NewPoint(measurement, r.tags, fields, now)
|
||||||
|
r.write.WritePoint(pt)
|
||||||
|
|
||||||
|
case metrics.Timer:
|
||||||
|
ms := metric.Snapshot()
|
||||||
|
ps := ms.Percentiles([]float64{0.5, 0.75, 0.95, 0.99, 0.999, 0.9999})
|
||||||
|
|
||||||
|
measurement := fmt.Sprintf("%s%s.timer", namespace, name)
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"count": ms.Count(),
|
||||||
|
"max": ms.Max(),
|
||||||
|
"mean": ms.Mean(),
|
||||||
|
"min": ms.Min(),
|
||||||
|
"stddev": ms.StdDev(),
|
||||||
|
"variance": ms.Variance(),
|
||||||
|
"p50": ps[0],
|
||||||
|
"p75": ps[1],
|
||||||
|
"p95": ps[2],
|
||||||
|
"p99": ps[3],
|
||||||
|
"p999": ps[4],
|
||||||
|
"p9999": ps[5],
|
||||||
|
"m1": ms.Rate1(),
|
||||||
|
"m5": ms.Rate5(),
|
||||||
|
"m15": ms.Rate15(),
|
||||||
|
"meanrate": ms.RateMean(),
|
||||||
|
}
|
||||||
|
|
||||||
|
pt := influxdb2.NewPoint(measurement, r.tags, fields, now)
|
||||||
|
r.write.WritePoint(pt)
|
||||||
|
|
||||||
|
case metrics.ResettingTimer:
|
||||||
|
t := metric.Snapshot()
|
||||||
|
|
||||||
|
if len(t.Values()) > 0 {
|
||||||
|
ps := t.Percentiles([]float64{50, 95, 99})
|
||||||
|
val := t.Values()
|
||||||
|
|
||||||
|
measurement := fmt.Sprintf("%s%s.span", namespace, name)
|
||||||
|
fields := map[string]interface{}{
|
||||||
|
"count": len(val),
|
||||||
|
"max": val[len(val)-1],
|
||||||
|
"mean": t.Mean(),
|
||||||
|
"min": val[0],
|
||||||
|
"p50": ps[0],
|
||||||
|
"p95": ps[1],
|
||||||
|
"p99": ps[2],
|
||||||
|
}
|
||||||
|
|
||||||
|
pt := influxdb2.NewPoint(measurement, r.tags, fields, now)
|
||||||
|
r.write.WritePoint(pt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Force all unwritten data to be sent
|
||||||
|
r.write.Flush()
|
||||||
|
}
|
@ -67,12 +67,6 @@ var GoerliBootnodes = []string{
|
|||||||
"enode://a59e33ccd2b3e52d578f1fbd70c6f9babda2650f0760d6ff3b37742fdcdfdb3defba5d56d315b40c46b70198c7621e63ffa3f987389c7118634b0fefbbdfa7fd@51.15.119.157:40303",
|
"enode://a59e33ccd2b3e52d578f1fbd70c6f9babda2650f0760d6ff3b37742fdcdfdb3defba5d56d315b40c46b70198c7621e63ffa3f987389c7118634b0fefbbdfa7fd@51.15.119.157:40303",
|
||||||
}
|
}
|
||||||
|
|
||||||
// CalaverasBootnodes are the enode URLs of the P2P bootstrap nodes running on the
|
|
||||||
// Calaveras ephemeral test network.
|
|
||||||
var CalaverasBootnodes = []string{
|
|
||||||
"enode://9e1096aa59862a6f164994cb5cb16f5124d6c992cdbf4535ff7dea43ea1512afe5448dca9df1b7ab0726129603f1a3336b631e4d7a1a44c94daddd03241587f9@3.9.20.133:30303",
|
|
||||||
}
|
|
||||||
|
|
||||||
var V5Bootnodes = []string{
|
var V5Bootnodes = []string{
|
||||||
// Teku team's bootnode
|
// Teku team's bootnode
|
||||||
"enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA",
|
"enr:-KG4QOtcP9X1FbIMOe17QNMKqDxCpm14jcX5tiOE4_TyMrFqbmhPZHK_ZPG2Gxb1GE2xdtodOfx9-cgvNtxnRyHEmC0ghGV0aDKQ9aX9QgAAAAD__________4JpZIJ2NIJpcIQDE8KdiXNlY3AyNTZrMaEDhpehBDbZjM_L9ek699Y7vhUJ-eAdMyQW_Fil522Y0fODdGNwgiMog3VkcIIjKA",
|
||||||
|
@ -27,11 +27,10 @@ import (
|
|||||||
|
|
||||||
// Genesis hashes to enforce below configs on.
|
// Genesis hashes to enforce below configs on.
|
||||||
var (
|
var (
|
||||||
MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
|
MainnetGenesisHash = common.HexToHash("0xd4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3")
|
||||||
RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")
|
RopstenGenesisHash = common.HexToHash("0x41941023680923e0fe4d74a34bdac8141f2540e3ae90623718e47d66d1ca4a2d")
|
||||||
RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
|
RinkebyGenesisHash = common.HexToHash("0x6341fd3daf94b748c72ced5a5b26028f2474f5f00d824504e4fa37a75767e177")
|
||||||
GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
|
GoerliGenesisHash = common.HexToHash("0xbf7e331f7f7c1dd2e05159666b3bf8bc7a8a3a9eb1d518969eab529dd9b88c1a")
|
||||||
CalaverasGenesisHash = common.HexToHash("0xeb9233d066c275efcdfed8037f4fc082770176aefdbcb7691c71da412a5670f2")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TrustedCheckpoints associates each known checkpoint with the genesis hash of
|
// TrustedCheckpoints associates each known checkpoint with the genesis hash of
|
||||||
@ -221,27 +220,6 @@ var (
|
|||||||
Threshold: 2,
|
Threshold: 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
CalaverasChainConfig = &ChainConfig{
|
|
||||||
ChainID: big.NewInt(123),
|
|
||||||
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: nil,
|
|
||||||
BerlinBlock: big.NewInt(0),
|
|
||||||
LondonBlock: big.NewInt(500),
|
|
||||||
Clique: &CliqueConfig{
|
|
||||||
Period: 30,
|
|
||||||
Epoch: 30000,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
|
// AllEthashProtocolChanges contains every protocol change (EIPs) introduced
|
||||||
// and accepted by the Ethereum core developers into the Ethash consensus.
|
// and accepted by the Ethereum core developers into the Ethash consensus.
|
||||||
//
|
//
|
||||||
|
@ -23,7 +23,7 @@ import (
|
|||||||
const (
|
const (
|
||||||
VersionMajor = 1 // Major version component of the current release
|
VersionMajor = 1 // Major version component of the current release
|
||||||
VersionMinor = 10 // Minor version component of the current release
|
VersionMinor = 10 // Minor version component of the current release
|
||||||
VersionPatch = 7 // Patch version component of the current release
|
VersionPatch = 8 // Patch version component of the current release
|
||||||
VersionMeta = "stable" // Version metadata to append to the version string
|
VersionMeta = "stable" // Version metadata to append to the version string
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -19,12 +19,12 @@ package apitypes
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"math/big"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||||
"github.com/ethereum/go-ethereum/core/types"
|
"github.com/ethereum/go-ethereum/core/types"
|
||||||
"github.com/ethereum/go-ethereum/internal/ethapi"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ValidationInfo struct {
|
type ValidationInfo struct {
|
||||||
@ -97,23 +97,60 @@ func (args SendTxArgs) String() string {
|
|||||||
return err.Error()
|
return err.Error()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ToTransaction converts the arguments to a transaction.
|
||||||
func (args *SendTxArgs) ToTransaction() *types.Transaction {
|
func (args *SendTxArgs) ToTransaction() *types.Transaction {
|
||||||
txArgs := ethapi.TransactionArgs{
|
|
||||||
Gas: &args.Gas,
|
|
||||||
GasPrice: args.GasPrice,
|
|
||||||
MaxFeePerGas: args.MaxFeePerGas,
|
|
||||||
MaxPriorityFeePerGas: args.MaxPriorityFeePerGas,
|
|
||||||
Value: &args.Value,
|
|
||||||
Nonce: &args.Nonce,
|
|
||||||
Data: args.Data,
|
|
||||||
Input: args.Input,
|
|
||||||
AccessList: args.AccessList,
|
|
||||||
ChainID: args.ChainID,
|
|
||||||
}
|
|
||||||
// Add the To-field, if specified
|
// Add the To-field, if specified
|
||||||
|
var to *common.Address
|
||||||
if args.To != nil {
|
if args.To != nil {
|
||||||
to := args.To.Address()
|
dstAddr := args.To.Address()
|
||||||
txArgs.To = &to
|
to = &dstAddr
|
||||||
}
|
}
|
||||||
return txArgs.ToTransaction()
|
|
||||||
|
var input []byte
|
||||||
|
if args.Input != nil {
|
||||||
|
input = *args.Input
|
||||||
|
} else if args.Data != nil {
|
||||||
|
input = *args.Data
|
||||||
|
}
|
||||||
|
|
||||||
|
var data types.TxData
|
||||||
|
switch {
|
||||||
|
case args.MaxFeePerGas != nil:
|
||||||
|
al := types.AccessList{}
|
||||||
|
if args.AccessList != nil {
|
||||||
|
al = *args.AccessList
|
||||||
|
}
|
||||||
|
data = &types.DynamicFeeTx{
|
||||||
|
To: to,
|
||||||
|
ChainID: (*big.Int)(args.ChainID),
|
||||||
|
Nonce: uint64(args.Nonce),
|
||||||
|
Gas: uint64(args.Gas),
|
||||||
|
GasFeeCap: (*big.Int)(args.MaxFeePerGas),
|
||||||
|
GasTipCap: (*big.Int)(args.MaxPriorityFeePerGas),
|
||||||
|
Value: (*big.Int)(&args.Value),
|
||||||
|
Data: input,
|
||||||
|
AccessList: al,
|
||||||
|
}
|
||||||
|
case args.AccessList != nil:
|
||||||
|
data = &types.AccessListTx{
|
||||||
|
To: to,
|
||||||
|
ChainID: (*big.Int)(args.ChainID),
|
||||||
|
Nonce: uint64(args.Nonce),
|
||||||
|
Gas: uint64(args.Gas),
|
||||||
|
GasPrice: (*big.Int)(args.GasPrice),
|
||||||
|
Value: (*big.Int)(&args.Value),
|
||||||
|
Data: input,
|
||||||
|
AccessList: *args.AccessList,
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
data = &types.LegacyTx{
|
||||||
|
To: to,
|
||||||
|
Nonce: uint64(args.Nonce),
|
||||||
|
Gas: uint64(args.Gas),
|
||||||
|
GasPrice: (*big.Int)(args.GasPrice),
|
||||||
|
Value: (*big.Int)(&args.Value),
|
||||||
|
Data: input,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return types.NewTx(data)
|
||||||
}
|
}
|
||||||
|
@ -1,90 +0,0 @@
|
|||||||
// Code generated by github.com/fjl/gencodec. DO NOT EDIT.
|
|
||||||
|
|
||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"errors"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = (*vmExecMarshaling)(nil)
|
|
||||||
|
|
||||||
// MarshalJSON marshals as JSON.
|
|
||||||
func (v vmExec) MarshalJSON() ([]byte, error) {
|
|
||||||
type vmExec struct {
|
|
||||||
Address common.UnprefixedAddress `json:"address" gencodec:"required"`
|
|
||||||
Caller common.UnprefixedAddress `json:"caller" gencodec:"required"`
|
|
||||||
Origin common.UnprefixedAddress `json:"origin" gencodec:"required"`
|
|
||||||
Code hexutil.Bytes `json:"code" gencodec:"required"`
|
|
||||||
Data hexutil.Bytes `json:"data" gencodec:"required"`
|
|
||||||
Value *math.HexOrDecimal256 `json:"value" gencodec:"required"`
|
|
||||||
GasLimit math.HexOrDecimal64 `json:"gas" gencodec:"required"`
|
|
||||||
GasPrice *math.HexOrDecimal256 `json:"gasPrice" gencodec:"required"`
|
|
||||||
}
|
|
||||||
var enc vmExec
|
|
||||||
enc.Address = common.UnprefixedAddress(v.Address)
|
|
||||||
enc.Caller = common.UnprefixedAddress(v.Caller)
|
|
||||||
enc.Origin = common.UnprefixedAddress(v.Origin)
|
|
||||||
enc.Code = v.Code
|
|
||||||
enc.Data = v.Data
|
|
||||||
enc.Value = (*math.HexOrDecimal256)(v.Value)
|
|
||||||
enc.GasLimit = math.HexOrDecimal64(v.GasLimit)
|
|
||||||
enc.GasPrice = (*math.HexOrDecimal256)(v.GasPrice)
|
|
||||||
return json.Marshal(&enc)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UnmarshalJSON unmarshals from JSON.
|
|
||||||
func (v *vmExec) UnmarshalJSON(input []byte) error {
|
|
||||||
type vmExec struct {
|
|
||||||
Address *common.UnprefixedAddress `json:"address" gencodec:"required"`
|
|
||||||
Caller *common.UnprefixedAddress `json:"caller" gencodec:"required"`
|
|
||||||
Origin *common.UnprefixedAddress `json:"origin" gencodec:"required"`
|
|
||||||
Code *hexutil.Bytes `json:"code" gencodec:"required"`
|
|
||||||
Data *hexutil.Bytes `json:"data" gencodec:"required"`
|
|
||||||
Value *math.HexOrDecimal256 `json:"value" gencodec:"required"`
|
|
||||||
GasLimit *math.HexOrDecimal64 `json:"gas" gencodec:"required"`
|
|
||||||
GasPrice *math.HexOrDecimal256 `json:"gasPrice" gencodec:"required"`
|
|
||||||
}
|
|
||||||
var dec vmExec
|
|
||||||
if err := json.Unmarshal(input, &dec); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if dec.Address == nil {
|
|
||||||
return errors.New("missing required field 'address' for vmExec")
|
|
||||||
}
|
|
||||||
v.Address = common.Address(*dec.Address)
|
|
||||||
if dec.Caller == nil {
|
|
||||||
return errors.New("missing required field 'caller' for vmExec")
|
|
||||||
}
|
|
||||||
v.Caller = common.Address(*dec.Caller)
|
|
||||||
if dec.Origin == nil {
|
|
||||||
return errors.New("missing required field 'origin' for vmExec")
|
|
||||||
}
|
|
||||||
v.Origin = common.Address(*dec.Origin)
|
|
||||||
if dec.Code == nil {
|
|
||||||
return errors.New("missing required field 'code' for vmExec")
|
|
||||||
}
|
|
||||||
v.Code = *dec.Code
|
|
||||||
if dec.Data == nil {
|
|
||||||
return errors.New("missing required field 'data' for vmExec")
|
|
||||||
}
|
|
||||||
v.Data = *dec.Data
|
|
||||||
if dec.Value == nil {
|
|
||||||
return errors.New("missing required field 'value' for vmExec")
|
|
||||||
}
|
|
||||||
v.Value = (*big.Int)(dec.Value)
|
|
||||||
if dec.GasLimit == nil {
|
|
||||||
return errors.New("missing required field 'gas' for vmExec")
|
|
||||||
}
|
|
||||||
v.GasLimit = uint64(*dec.GasLimit)
|
|
||||||
if dec.GasPrice == nil {
|
|
||||||
return errors.New("missing required field 'gasPrice' for vmExec")
|
|
||||||
}
|
|
||||||
v.GasPrice = (*big.Int)(dec.GasPrice)
|
|
||||||
return nil
|
|
||||||
}
|
|
@ -34,12 +34,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
baseDir = filepath.Join(".", "testdata")
|
baseDir = filepath.Join(".", "testdata")
|
||||||
blockTestDir = filepath.Join(baseDir, "BlockchainTests")
|
blockTestDir = filepath.Join(baseDir, "BlockchainTests")
|
||||||
stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
|
stateTestDir = filepath.Join(baseDir, "GeneralStateTests")
|
||||||
//legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
|
legacyStateTestDir = filepath.Join(baseDir, "LegacyTests", "Constantinople", "GeneralStateTests")
|
||||||
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
|
transactionTestDir = filepath.Join(baseDir, "TransactionTests")
|
||||||
vmTestDir = filepath.Join(baseDir, "VMTests")
|
|
||||||
rlpTestDir = filepath.Join(baseDir, "RLPTests")
|
rlpTestDir = filepath.Join(baseDir, "RLPTests")
|
||||||
difficultyTestDir = filepath.Join(baseDir, "BasicTests")
|
difficultyTestDir = filepath.Join(baseDir, "BasicTests")
|
||||||
)
|
)
|
||||||
|
@ -45,8 +45,7 @@ func TestState(t *testing.T) {
|
|||||||
|
|
||||||
// Uses 1GB RAM per tested fork
|
// Uses 1GB RAM per tested fork
|
||||||
st.skipLoad(`^stStaticCall/static_Call1MB`)
|
st.skipLoad(`^stStaticCall/static_Call1MB`)
|
||||||
// Un-skip this when https://github.com/ethereum/tests/issues/908 is closed
|
|
||||||
st.skipLoad(`^stQuadraticComplexityTest/QuadraticComplexitySolidity_CallDataCopy`)
|
|
||||||
// Broken tests:
|
// Broken tests:
|
||||||
// Expected failures:
|
// Expected failures:
|
||||||
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/0`, "bug in test")
|
//st.fails(`^stRevertTest/RevertPrecompiledTouch(_storage)?\.json/Byzantium/0`, "bug in test")
|
||||||
@ -59,9 +58,7 @@ func TestState(t *testing.T) {
|
|||||||
// For Istanbul, older tests were moved into LegacyTests
|
// For Istanbul, older tests were moved into LegacyTests
|
||||||
for _, dir := range []string{
|
for _, dir := range []string{
|
||||||
stateTestDir,
|
stateTestDir,
|
||||||
// legacy state tests are disabled, due to them not being
|
legacyStateTestDir,
|
||||||
// regenerated for the no-sender-eoa change.
|
|
||||||
//legacyStateTestDir,
|
|
||||||
} {
|
} {
|
||||||
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
|
st.walk(t, dir, func(t *testing.T, name string, test *StateTest) {
|
||||||
for _, subtest := range test.Subtests() {
|
for _, subtest := range test.Subtests() {
|
||||||
|
@ -348,7 +348,7 @@ func (tx *stTransaction) toMessage(ps stPostState, baseFee *big.Int) (core.Messa
|
|||||||
}
|
}
|
||||||
|
|
||||||
msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, gasPrice,
|
msg := types.NewMessage(from, to, tx.Nonce, value, gasLimit, gasPrice,
|
||||||
tx.MaxFeePerGas, tx.MaxPriorityFeePerGas, data, accessList, true)
|
tx.MaxFeePerGas, tx.MaxPriorityFeePerGas, data, accessList, false)
|
||||||
return msg, nil
|
return msg, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -358,3 +358,7 @@ func rlpHash(x interface{}) (h common.Hash) {
|
|||||||
hw.Sum(h[:0])
|
hw.Sum(h[:0])
|
||||||
return h
|
return h
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func vmTestBlockHash(n uint64) common.Hash {
|
||||||
|
return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
|
||||||
|
}
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 5d534e37b80e9310e8c7751f805ca481a451123e
|
Subproject commit 6b85703b568f4456582a00665d8a3e5c3b20b484
|
@ -1,39 +0,0 @@
|
|||||||
// Copyright 2014 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestVM(t *testing.T) {
|
|
||||||
t.Parallel()
|
|
||||||
vmt := new(testMatcher)
|
|
||||||
vmt.slow("^vmPerformance")
|
|
||||||
vmt.fails("^vmSystemOperationsTest.json/createNameRegistrator$", "fails without parallel execution")
|
|
||||||
|
|
||||||
vmt.walk(t, vmTestDir, func(t *testing.T, name string, test *VMTest) {
|
|
||||||
withTrace(t, test.json.Exec.GasLimit, func(vmconfig vm.Config) error {
|
|
||||||
return vmt.checkFailure(t, test.Run(vmconfig, false))
|
|
||||||
})
|
|
||||||
withTrace(t, test.json.Exec.GasLimit, func(vmconfig vm.Config) error {
|
|
||||||
return vmt.checkFailure(t, test.Run(vmconfig, true))
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
@ -1,161 +0,0 @@
|
|||||||
// Copyright 2015 The go-ethereum Authors
|
|
||||||
// This file is part of the go-ethereum library.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is free software: you can redistribute it and/or modify
|
|
||||||
// it under the terms of the GNU Lesser General Public License as published by
|
|
||||||
// the Free Software Foundation, either version 3 of the License, or
|
|
||||||
// (at your option) any later version.
|
|
||||||
//
|
|
||||||
// The go-ethereum library is distributed in the hope that it will be useful,
|
|
||||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
// GNU Lesser General Public License for more details.
|
|
||||||
//
|
|
||||||
// You should have received a copy of the GNU Lesser General Public License
|
|
||||||
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
package tests
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"math/big"
|
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
|
||||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
|
||||||
"github.com/ethereum/go-ethereum/common/math"
|
|
||||||
"github.com/ethereum/go-ethereum/core"
|
|
||||||
"github.com/ethereum/go-ethereum/core/rawdb"
|
|
||||||
"github.com/ethereum/go-ethereum/core/state"
|
|
||||||
"github.com/ethereum/go-ethereum/core/vm"
|
|
||||||
"github.com/ethereum/go-ethereum/crypto"
|
|
||||||
"github.com/ethereum/go-ethereum/params"
|
|
||||||
)
|
|
||||||
|
|
||||||
// VMTest checks EVM execution without block or transaction context.
|
|
||||||
// See https://github.com/ethereum/tests/wiki/VM-Tests for the test format specification.
|
|
||||||
type VMTest struct {
|
|
||||||
json vmJSON
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *VMTest) UnmarshalJSON(data []byte) error {
|
|
||||||
return json.Unmarshal(data, &t.json)
|
|
||||||
}
|
|
||||||
|
|
||||||
type vmJSON struct {
|
|
||||||
Env stEnv `json:"env"`
|
|
||||||
Exec vmExec `json:"exec"`
|
|
||||||
Logs common.UnprefixedHash `json:"logs"`
|
|
||||||
GasRemaining *math.HexOrDecimal64 `json:"gas"`
|
|
||||||
Out hexutil.Bytes `json:"out"`
|
|
||||||
Pre core.GenesisAlloc `json:"pre"`
|
|
||||||
Post core.GenesisAlloc `json:"post"`
|
|
||||||
PostStateRoot common.Hash `json:"postStateRoot"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//go:generate gencodec -type vmExec -field-override vmExecMarshaling -out gen_vmexec.go
|
|
||||||
|
|
||||||
type vmExec struct {
|
|
||||||
Address common.Address `json:"address" gencodec:"required"`
|
|
||||||
Caller common.Address `json:"caller" gencodec:"required"`
|
|
||||||
Origin common.Address `json:"origin" gencodec:"required"`
|
|
||||||
Code []byte `json:"code" gencodec:"required"`
|
|
||||||
Data []byte `json:"data" gencodec:"required"`
|
|
||||||
Value *big.Int `json:"value" gencodec:"required"`
|
|
||||||
GasLimit uint64 `json:"gas" gencodec:"required"`
|
|
||||||
GasPrice *big.Int `json:"gasPrice" gencodec:"required"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type vmExecMarshaling struct {
|
|
||||||
Address common.UnprefixedAddress
|
|
||||||
Caller common.UnprefixedAddress
|
|
||||||
Origin common.UnprefixedAddress
|
|
||||||
Code hexutil.Bytes
|
|
||||||
Data hexutil.Bytes
|
|
||||||
Value *math.HexOrDecimal256
|
|
||||||
GasLimit math.HexOrDecimal64
|
|
||||||
GasPrice *math.HexOrDecimal256
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *VMTest) Run(vmconfig vm.Config, snapshotter bool) error {
|
|
||||||
snaps, statedb := MakePreState(rawdb.NewMemoryDatabase(), t.json.Pre, snapshotter)
|
|
||||||
if snapshotter {
|
|
||||||
preRoot := statedb.IntermediateRoot(false)
|
|
||||||
defer func() {
|
|
||||||
if _, err := snaps.Journal(preRoot); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
ret, gasRemaining, err := t.exec(statedb, vmconfig)
|
|
||||||
|
|
||||||
if t.json.GasRemaining == nil {
|
|
||||||
if err == nil {
|
|
||||||
return fmt.Errorf("gas unspecified (indicating an error), but VM returned no error")
|
|
||||||
}
|
|
||||||
if gasRemaining > 0 {
|
|
||||||
return fmt.Errorf("gas unspecified (indicating an error), but VM returned gas remaining > 0")
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
// Test declares gas, expecting outputs to match.
|
|
||||||
if !bytes.Equal(ret, t.json.Out) {
|
|
||||||
return fmt.Errorf("return data mismatch: got %x, want %x", ret, t.json.Out)
|
|
||||||
}
|
|
||||||
if gasRemaining != uint64(*t.json.GasRemaining) {
|
|
||||||
return fmt.Errorf("remaining gas %v, want %v", gasRemaining, *t.json.GasRemaining)
|
|
||||||
}
|
|
||||||
for addr, account := range t.json.Post {
|
|
||||||
for k, wantV := range account.Storage {
|
|
||||||
if haveV := statedb.GetState(addr, k); haveV != wantV {
|
|
||||||
return fmt.Errorf("wrong storage value at %x:\n got %x\n want %x", k, haveV, wantV)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if root := statedb.IntermediateRoot(false); root != t.json.PostStateRoot {
|
|
||||||
// return fmt.Errorf("post state root mismatch, got %x, want %x", root, t.json.PostStateRoot)
|
|
||||||
// }
|
|
||||||
if logs := rlpHash(statedb.Logs()); logs != common.Hash(t.json.Logs) {
|
|
||||||
return fmt.Errorf("post state logs hash mismatch: got %x, want %x", logs, t.json.Logs)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *VMTest) exec(statedb *state.StateDB, vmconfig vm.Config) ([]byte, uint64, error) {
|
|
||||||
evm := t.newEVM(statedb, vmconfig)
|
|
||||||
e := t.json.Exec
|
|
||||||
return evm.Call(vm.AccountRef(e.Caller), e.Address, e.Data, e.GasLimit, e.Value)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *VMTest) newEVM(statedb *state.StateDB, vmconfig vm.Config) *vm.EVM {
|
|
||||||
initialCall := true
|
|
||||||
canTransfer := func(db vm.StateDB, address common.Address, amount *big.Int) bool {
|
|
||||||
if initialCall {
|
|
||||||
initialCall = false
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return core.CanTransfer(db, address, amount)
|
|
||||||
}
|
|
||||||
transfer := func(db vm.StateDB, sender, recipient common.Address, amount *big.Int) {}
|
|
||||||
txContext := vm.TxContext{
|
|
||||||
Origin: t.json.Exec.Origin,
|
|
||||||
GasPrice: t.json.Exec.GasPrice,
|
|
||||||
}
|
|
||||||
context := vm.BlockContext{
|
|
||||||
CanTransfer: canTransfer,
|
|
||||||
Transfer: transfer,
|
|
||||||
GetHash: vmTestBlockHash,
|
|
||||||
Coinbase: t.json.Env.Coinbase,
|
|
||||||
BlockNumber: new(big.Int).SetUint64(t.json.Env.Number),
|
|
||||||
Time: new(big.Int).SetUint64(t.json.Env.Timestamp),
|
|
||||||
GasLimit: t.json.Env.GasLimit,
|
|
||||||
Difficulty: t.json.Env.Difficulty,
|
|
||||||
}
|
|
||||||
vmconfig.NoRecursion = true
|
|
||||||
return vm.NewEVM(context, txContext, statedb, params.MainnetChainConfig, vmconfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func vmTestBlockHash(n uint64) common.Hash {
|
|
||||||
return common.BytesToHash(crypto.Keccak256([]byte(big.NewInt(int64(n)).String())))
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user