github.com/amazechain/amc@v0.1.3/cmd/amc/exportcmd.go (about)

     1  // Copyright 2023 The AmazeChain Authors
     2  // This file is part of the AmazeChain library.
     3  //
     4  // The AmazeChain library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The AmazeChain library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the AmazeChain library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  package main
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"fmt"
    23  	"github.com/amazechain/amc/common/account"
    24  	common "github.com/amazechain/amc/common/types"
    25  	"github.com/amazechain/amc/internal/node"
    26  	"github.com/amazechain/amc/log"
    27  	"github.com/amazechain/amc/modules"
    28  	"github.com/amazechain/amc/params"
    29  	"github.com/amazechain/amc/turbo/backup"
    30  	"github.com/holiman/uint256"
    31  	"github.com/ledgerwatch/erigon-lib/kv"
    32  	"github.com/urfave/cli/v2"
    33  	"math/big"
    34  	"os"
    35  	"time"
    36  )
    37  
    38  var (
    39  	exportCommand = &cli.Command{
    40  		Name:        "export",
    41  		Usage:       "Export AmazeChain data",
    42  		ArgsUsage:   "",
    43  		Description: ``,
    44  		Subcommands: []*cli.Command{
    45  			{
    46  				Name:      "txs",
    47  				Usage:     "Export All AmazeChain Transactions",
    48  				ArgsUsage: "",
    49  				Action:    exportTransactions,
    50  				Flags: []cli.Flag{
    51  					DataDirFlag,
    52  				},
    53  				Description: ``,
    54  			},
    55  			{
    56  				Name:      "balance",
    57  				Usage:     "Export All AmazeChain account balance",
    58  				ArgsUsage: "",
    59  				Action:    exportBalance,
    60  				Flags: []cli.Flag{
    61  					DataDirFlag,
    62  				},
    63  				Description: ``,
    64  			},
    65  			{
    66  				Name:      "dbState",
    67  				Usage:     "Export All MDBX Buckets disk space",
    68  				ArgsUsage: "",
    69  				Action:    exportDBState,
    70  				Flags: []cli.Flag{
    71  					DataDirFlag,
    72  				},
    73  				Description: ``,
    74  			},
    75  			{
    76  				Name:      "dbCopy",
    77  				Usage:     "copy data from '--chaindata' to '--chaindata.to'",
    78  				ArgsUsage: "",
    79  				Action:    dbCopy,
    80  				Flags: []cli.Flag{
    81  					FromDataDirFlag,
    82  					ToDataDirFlag,
    83  				},
    84  				Description: ``,
    85  			},
    86  		},
    87  	}
    88  )
    89  
    90  func exportTransactions(ctx *cli.Context) error {
    91  
    92  	stack, err := node.NewNode(ctx, &DefaultConfig)
    93  	if err != nil {
    94  		return err
    95  	}
    96  
    97  	blockChain := stack.BlockChain()
    98  	defer stack.Close()
    99  
   100  	currentBlock := blockChain.CurrentBlock()
   101  
   102  	for i := uint64(0); i < currentBlock.Number64().Uint64(); i++ {
   103  
   104  		block, err := blockChain.GetBlockByNumber(uint256.NewInt(i + 1))
   105  		if err != nil {
   106  			panic("cannot get block")
   107  		}
   108  		for _, transaction := range block.Transactions() {
   109  			if transaction.To() == nil {
   110  				continue
   111  			}
   112  			fmt.Printf("%d,%s,%s,%d,%s,%.2f\n",
   113  				block.Number64().Uint64(),
   114  				time.Unix(int64(block.Time()), 0).Format(time.RFC3339),
   115  				transaction.From().Hex(),
   116  				transaction.Nonce(),
   117  				transaction.To().Hex(),
   118  				new(big.Float).Quo(new(big.Float).SetInt(transaction.Value().ToBig()), new(big.Float).SetInt(big.NewInt(params.AMT))),
   119  			)
   120  		}
   121  	}
   122  
   123  	return nil
   124  }
   125  
   126  func exportBalance(ctx *cli.Context) error {
   127  
   128  	stack, err := node.NewNode(ctx, &DefaultConfig)
   129  	if err != nil {
   130  		return err
   131  	}
   132  	db := stack.Database()
   133  	defer stack.Close()
   134  
   135  	roTX, err := db.BeginRo(ctx.Context)
   136  	if err != nil {
   137  		return err
   138  	}
   139  	defer roTX.Rollback()
   140  	//kv.ReadAhead(ctx.Context, roTX.(kv.RoDB), atomic.NewBool(false), name, nil, 1<<32-1) // MaxUint32
   141  	//
   142  	srcC, err := roTX.Cursor("Account")
   143  	if err != nil {
   144  		return err
   145  	}
   146  
   147  	for k, v, err := srcC.First(); k != nil; k, v, err = srcC.Next() {
   148  		if err != nil {
   149  			return err
   150  		}
   151  		var acc account.StateAccount
   152  		if err = acc.DecodeForStorage(v); err != nil {
   153  			return err
   154  		}
   155  
   156  		fmt.Printf("%x, %.2f\n",
   157  			k,
   158  			new(big.Float).Quo(new(big.Float).SetInt(acc.Balance.ToBig()), new(big.Float).SetInt(big.NewInt(params.AMT))),
   159  		)
   160  	}
   161  
   162  	return nil
   163  }
   164  
   165  func exportDBState(ctx *cli.Context) error {
   166  
   167  	stack, err := node.NewNode(ctx, &DefaultConfig)
   168  	if err != nil {
   169  		return err
   170  	}
   171  	db := stack.Database()
   172  	defer stack.Close()
   173  
   174  	var tsize uint64
   175  
   176  	roTX, err := db.BeginRo(ctx.Context)
   177  	if err != nil {
   178  		return err
   179  	}
   180  	defer roTX.Rollback()
   181  
   182  	migrator, ok := roTX.(kv.BucketMigrator)
   183  	if !ok {
   184  		return fmt.Errorf("cannot open db as BucketMigrator")
   185  	}
   186  	Buckets, err := migrator.ListBuckets()
   187  	for _, Bucket := range Buckets {
   188  		size, _ := roTX.BucketSize(Bucket)
   189  		tsize += size
   190  		Cursor, _ := roTX.Cursor(Bucket)
   191  		count, _ := Cursor.Count()
   192  		Cursor.Close()
   193  		if count != 0 {
   194  			fmt.Printf("%30v count %10d size: %s \r\n", Bucket, count, common.StorageSize(size))
   195  		}
   196  	}
   197  	fmt.Printf("total %s \n", common.StorageSize(tsize))
   198  	return nil
   199  }
   200  
   201  func dbCopy(ctx *cli.Context) error {
   202  
   203  	modules.AmcInit()
   204  	kv.ChaindataTablesCfg = modules.AmcTableCfg
   205  
   206  	fromChaindata := ctx.String(FromDataDirFlag.Name)
   207  	toChaindata := ctx.String(ToDataDirFlag.Name)
   208  
   209  	if f, err := os.Stat(fromChaindata); err != nil || !f.IsDir() {
   210  		log.Errorf("fromChaindata do not exists or is not a dir, err: %s", err)
   211  		return err
   212  	}
   213  	if f, err := os.Stat(toChaindata); err != nil || !f.IsDir() {
   214  		log.Errorf("toChaindata do not exists or is not a dir, err: %s", err)
   215  		return err
   216  	}
   217  
   218  	from, to := backup.OpenPair(fromChaindata, toChaindata, kv.ChainDB, 0)
   219  	err := backup.Kv2kv(ctx.Context, from, to, nil, backup.ReadAheadThreads)
   220  	if err != nil && !errors.Is(err, context.Canceled) {
   221  		if !errors.Is(err, context.Canceled) {
   222  			log.Error(err.Error())
   223  		}
   224  		return nil
   225  	}
   226  
   227  	return nil
   228  }