monza/flags.go

177 lines
4.6 KiB
Go
Raw Normal View History

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"
)
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,
}
)
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)
}