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 }