package main import ( "bytes" "encoding/hex" "fmt" "os" "strconv" "github.com/pkg/errors" "github.com/urfave/cli/v2" "gitlab.com/jaxnet/jaxnetd/types/pow" ) func (app *App) SyncHeadersCmd(c *cli.Context) error { path := c.String(flagDataDir) res, err := app.TxMan.RPC().ListShards() if err != nil { return cli.NewExitError(errors.Wrap(err, "unable to get list of available shards"), 1) } fmt.Printf("%d shards are available\n", len(res.Shards)) out, err := openFile(path, "headers.csv") if err != nil { return cli.NewExitError(errors.Wrap(err, "unable to open out file"), 1) } outFullData, err := openFile(path, "full_headers.csv") if err != nil { return cli.NewExitError(errors.Wrap(err, "unable to open out file"), 1) } defer out.Close() defer outFullData.Close() _, _ = fmt.Fprintf(out, "%v,%v,%v,%v,%v,%v,%v,%v,%v\n", "chain", "height", "hash", "blocks_mmr", "pow_hash", "bits", "target", "nonce", "time", ) _, _ = fmt.Fprintf(outFullData, "%v,%v,%v,%v\n", "chain", "height", "hash", "raw_data", ) _, best, err := app.TxMan.RPC().ForBeacon().GetBestBlock() if err != nil { return cli.NewExitError(errors.Wrap(err, "unable to GetBestBlock"), 1) } for height := int64(1); height < int64(best); height++ { fmt.Printf("\r\033[0K Processing: chain %s block %d ...", "beacon", height) hash, err := app.TxMan.RPC().ForBeacon().GetBlockHash(height) if err != nil { return cli.NewExitError(errors.Wrapf(err, "unable to get block hash by height(%d)", height), 1) } header, err := app.TxMan.RPC().ForBeacon().GetBeaconBlockHeader(hash) if err != nil { return cli.NewExitError(errors.Wrapf(err, "unable to get block by hash(%s)", hash), 1) } _, _ = fmt.Fprintf(out, "%v,%v,%v,%v,%v,%v,%v,%v,%v\n", "beacon", height, hash.String(), header.PrevBlocksMMRRoot(), header.PoWHash(), fmt.Sprintf("%08x", header.Bits()), fmt.Sprintf("%064x", pow.CompactToBig(header.Bits())), header.BeaconHeader().Nonce(), header.Timestamp().Unix(), ) buf := bytes.NewBuffer(nil) _ = header.Write(buf) _, _ = fmt.Fprintf(outFullData, "%v,%v,%v,%v\n", "beacon", height, hash.String(), hex.EncodeToString(buf.Bytes()), ) } for shardID := uint32(1); shardID < uint32(len(res.Shards)); shardID++ { fmt.Println() _, best, err := app.TxMan.RPC().ForShard(shardID).GetBestBlock() if err != nil { return cli.NewExitError(errors.Wrap(err, "unable to GetBestBlock"), 1) } for height := int64(1); height < int64(best); height++ { fmt.Printf("\r\033[0K Processing: chain %s block %d ...", "shard_"+strconv.Itoa(int(shardID)), height) hash, err := app.TxMan.RPC().ForShard(shardID).GetBlockHash(height) if err != nil { return cli.NewExitError(errors.Wrapf(err, "unable to get block hash by height(%d)", height), 1) } header, err := app.TxMan.RPC().ForShard(shardID).GetShardBlockHeader(hash) if err != nil { return cli.NewExitError(errors.Wrapf(err, "unable to get block by hash(%s)", hash), 1) } _, _ = fmt.Fprintf(out, "%v,%v,%v,%v,%v,%v,%v,%v,%v\n", "shard_"+strconv.Itoa(int(shardID)), height, hash.String(), header.PrevBlocksMMRRoot(), header.PoWHash(), fmt.Sprintf("%08x", header.Bits()), fmt.Sprintf("%064x", pow.CompactToBig(header.Bits())), header.BeaconHeader().Nonce(), header.Timestamp().Unix(), ) buf := bytes.NewBuffer(nil) _ = header.Write(buf) _, _ = fmt.Fprintf(outFullData, "%v,%v,%v,%v\n", "shard_"+strconv.Itoa(int(shardID)), height, hash.String(), hex.EncodeToString(buf.Bytes()), ) } } return nil } func openFile(path, name string) (*os.File, error) { if _, err := os.Stat(path + "/" + name); os.IsNotExist(err) { os.MkdirAll(path, 0700) // Create file } return os.OpenFile(path+"/"+name, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0755) }