Alex Vanin
4fc7478e1e
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>
98 lines
2 KiB
Go
98 lines
2 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"time"
|
|
|
|
"git.frostfs.info/TrueCloudLab/monza/internal/chain"
|
|
"github.com/nspcc-dev/neo-go/pkg/core/block"
|
|
"github.com/urfave/cli/v2"
|
|
)
|
|
|
|
func stutter(c *cli.Context) (err error) {
|
|
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
|
|
|
|
// parse blockchain info
|
|
cacheDir := c.String(cacheFlagKey)
|
|
if len(cacheDir) == 0 {
|
|
cacheDir, err = defaultConfigDir()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
blockchain, err := chain.Open(ctx, cacheDir, c.String(endpointFlagKey), false)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot initialize remote blockchain client: %w", err)
|
|
}
|
|
defer func() {
|
|
blockchain.Close()
|
|
cancel()
|
|
}()
|
|
|
|
// parse block indices
|
|
from, to, err := parseInterval(c.String(fromFlagKey), c.String(toFlagKey), blockchain.Client)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
threshold := c.Duration(stutterThresholdFlagKey)
|
|
|
|
// need at least two blocks
|
|
if to-from < 2 {
|
|
return errors.New("range must contain at least two blocks")
|
|
}
|
|
|
|
// fetch blocks
|
|
err = cacheBlocks(ctx, ¶ms{
|
|
from: from,
|
|
to: to,
|
|
blockchain: blockchain,
|
|
workers: int(c.Uint64(workersFlagKey)),
|
|
disableBar: c.Bool(disableProgressBarFlagKey),
|
|
})
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// process blocks one by one
|
|
var (
|
|
prev, curr *block.Block
|
|
prevTS, currTS time.Time
|
|
lastStutterBlock uint32
|
|
)
|
|
|
|
for i := from; i < to; i++ {
|
|
b, err := blockchain.Block(i)
|
|
if err != nil {
|
|
return fmt.Errorf("cannot fetch block %d: %w", i, err)
|
|
}
|
|
|
|
prev, prevTS = curr, currTS
|
|
curr = b
|
|
currTS = time.Unix(int64(b.Timestamp/1e3), 0)
|
|
if prev == nil { // first block case
|
|
continue
|
|
}
|
|
|
|
blockDelta := currTS.Sub(prevTS)
|
|
if blockDelta <= threshold {
|
|
continue
|
|
}
|
|
|
|
skippedBlocks := prev.Index - lastStutterBlock
|
|
if lastStutterBlock > 0 && skippedBlocks > 1 {
|
|
fmt.Printf("-- skipped %d blocks --\n", skippedBlocks-1)
|
|
}
|
|
|
|
PrintBlock(prev, "")
|
|
PrintBlock(curr, fmt.Sprintf("<- stutter for %s", blockDelta))
|
|
lastStutterBlock = curr.Index
|
|
}
|
|
|
|
return nil
|
|
}
|