monza/flags.go
Alex Vanin 4fc7478e1e [#1] Add '-f' flag to overwrite local cache
Sometimes multiple environments have blockchains with
the same magic number. In this case, user should not
reuse cached chain, because cache contains magic number
to identify different chains. With new '-f' flag user
will be able to repopulate cache with new data for the
chain with the same magic number.

Signed-off-by: Alex Vanin <a.vanin@yadro.com>
2023-10-19 17:20:45 +03:00

183 lines
4.8 KiB
Go

package main
import (
"fmt"
"strconv"
"strings"
"time"
"github.com/nspcc-dev/neo-go/pkg/core/native/nativenames"
"github.com/nspcc-dev/neo-go/pkg/rpcclient"
"github.com/nspcc-dev/neo-go/pkg/util"
"github.com/urfave/cli/v2"
)
const (
endpointFlagKey = "rpc-endpoint"
fromFlagKey = "from"
toFlagKey = "to"
notificationFlagKey = "notification"
cacheFlagKey = "cache"
workersFlagKey = "workers"
disableProgressBarFlagKey = "disable-progress-bar"
stutterThresholdFlagKey = "threshold"
forceCacheRewriteKey = "force"
)
var (
endpointFlag = &cli.StringFlag{
Name: endpointFlagKey,
Aliases: []string{"r"},
Usage: "N3 RPC endpoint",
Required: true,
}
fromFlag = &cli.StringFlag{
Name: fromFlagKey,
Usage: "starting block (can be relative value with minus prefix, e.g. 'm100')",
Required: true,
Value: "",
}
toFlag = &cli.StringFlag{
Name: toFlagKey,
Usage: "ending block (can be relative value with plus prefix, e.g. 'p100' or omitted for latest block in chain)",
Required: false,
Value: "",
}
notificationFlag = &cli.StringSliceFlag{
Name: notificationFlagKey,
Aliases: []string{"n"},
Usage: "'notification:contract' pair (specify LE script hash, '*' for any contract or 'gas' and 'neo' strings)",
Required: true,
Value: nil,
}
cacheFlag = &cli.StringFlag{
Name: cacheFlagKey,
Aliases: []string{"c"},
Usage: "path to the blockchain cache (default: $HOME/.config/monza)",
Value: "",
}
workersFlag = &cli.Uint64Flag{
Name: workersFlagKey,
Aliases: []string{"w"},
Usage: "amount of workers for parallel block fetch",
Value: 3,
}
disableProgressBarFlag = &cli.BoolFlag{
Name: disableProgressBarFlagKey,
Usage: "disable progress bar output",
}
stutterThresholdFlag = &cli.DurationFlag{
Name: stutterThresholdFlagKey,
Aliases: []string{"t"},
Usage: "duration limit between block timestamps",
Value: 20 * time.Second,
}
forceCacheRewriteFlag = &cli.BoolFlag{
Name: forceCacheRewriteKey,
Aliases: []string{"f"},
Usage: "force blockchain cache rewrite",
}
)
func parseNotifications(notifications []string, cli *rpcclient.Client) (map[string]*util.Uint160, error) {
res := make(map[string]*util.Uint160, len(notifications))
for _, n := range notifications {
pair := strings.Split(n, ":")
if len(pair) != 2 {
return nil, fmt.Errorf("invalid notification %s", n)
}
name := pair[0]
switch contractName := strings.ToLower(pair[1]); contractName {
case "*":
res[name] = nil
case "gas":
state, err := cli.GetContractStateByAddressOrName(nativenames.Gas)
if err != nil {
return nil, fmt.Errorf("invalid contract name %s", contractName)
}
res[name] = &state.Hash
case "neo":
state, err := cli.GetContractStateByAddressOrName(nativenames.Neo)
if err != nil {
return nil, fmt.Errorf("invalid contract name %s", contractName)
}
res[name] = &state.Hash
default:
u160, err := util.Uint160DecodeStringLE(contractName)
if err != nil {
return nil, fmt.Errorf("invalid contract name %s", contractName)
}
res[name] = &u160
}
}
return res, nil
}
func parseInterval(fromStr, toStr string, cli *rpcclient.Client) (from, to uint32, err error) {
switch { // parse from value and return result if it is relative
case len(fromStr) == 0:
return 0, 0, ErrInvalidInterval(fromStr, toStr)
case fromStr[0] == 'm':
v, err := strconv.Atoi(fromStr[1:])
if err != nil || v <= 0 {
return 0, 0, ErrInvalidInterval(fromStr, toStr)
}
h, err := cli.GetBlockCount()
if err != nil {
return 0, 0, fmt.Errorf("latest block index unavailable: %w", err)
}
if uint32(v) >= h {
return 0, 0, fmt.Errorf("latest block is less than from value, from:%s, to:%d", fromStr, h)
}
return h - uint32(v), h, nil
default:
v, err := strconv.Atoi(fromStr)
if err != nil || v <= 0 {
return 0, 0, ErrInvalidInterval(fromStr, toStr)
}
from = uint32(v)
}
switch { // parse to value
case len(toStr) == 0:
h, err := cli.GetBlockCount()
if err != nil {
return 0, 0, fmt.Errorf("latest block index unavailable: %w", err)
}
if h <= from {
return 0, 0, fmt.Errorf("latest block is less than from value, from:%d, to:%d", from, h)
}
return from, h, nil
case toStr[0] == 'p':
v, err := strconv.Atoi(toStr[1:])
if err != nil || v <= 0 {
return 0, 0, ErrInvalidInterval(fromStr, toStr)
}
return from, from + uint32(v), nil
default:
v, err := strconv.Atoi(toStr)
if err != nil || v <= 0 {
return 0, 0, ErrInvalidInterval(fromStr, toStr)
}
if uint32(v) <= from {
return 0, 0, ErrInvalidInterval(fromStr, toStr)
}
return from, uint32(v), nil
}
}
func ErrInvalidInterval(from, to string) error {
return fmt.Errorf("invalid block interval from:%s to:%s", from, to)
}