package utils import ( "context" "crypto/rand" "encoding/json" "errors" "fmt" "math/big" "os" "path/filepath" "time" "github.com/modern-go/reflect2" "github.com/scroll-tech/go-ethereum/core" ) // TryTimes try run several times until the function return true. func TryTimes(times int, run func() bool) bool { for i := 0; i < times; i++ { if run() { return true } time.Sleep(time.Millisecond * 500) } return false } // LoopWithContext Run the f func with context periodically. func LoopWithContext(ctx context.Context, period time.Duration, f func(ctx context.Context)) { tick := time.NewTicker(period) defer tick.Stop() for ; ; <-tick.C { select { case <-ctx.Done(): return default: f(ctx) } } } // Loop Run the f func periodically. func Loop(ctx context.Context, period time.Duration, f func()) { tick := time.NewTicker(period) defer tick.Stop() for ; ; <-tick.C { select { case <-ctx.Done(): return default: f() } } } // IsNil Check if the interface is empty. func IsNil(i interface{}) bool { return i == nil || reflect2.IsNil(i) } // RandomURL return a random port endpoint. func RandomURL() string { id, _ := rand.Int(rand.Reader, big.NewInt(5000-1)) return fmt.Sprintf("localhost:%d", 10000+2000+id.Int64()) } // ReadGenesis parses and returns the genesis file at the given path func ReadGenesis(genesisPath string) (*core.Genesis, error) { file, err := os.Open(filepath.Clean(genesisPath)) if err != nil { return nil, err } genesis := new(core.Genesis) if err := json.NewDecoder(file).Decode(genesis); err != nil { return nil, errors.Join(err, file.Close()) } return genesis, file.Close() }