github.com/unicornultrafoundation/go-u2u@v1.0.0-rc1.0.20240205080301-e74a83d3fadc/cmd/u2u/launcher/export.go (about) 1 package launcher 2 3 import ( 4 "compress/gzip" 5 "io" 6 "os" 7 "strconv" 8 "strings" 9 "time" 10 11 "gopkg.in/urfave/cli.v1" 12 13 "github.com/status-im/keycard-go/hexutils" 14 "github.com/syndtr/goleveldb/leveldb/opt" 15 16 "github.com/unicornultrafoundation/go-u2u/cmd/utils" 17 "github.com/unicornultrafoundation/go-u2u/common" 18 "github.com/unicornultrafoundation/go-u2u/log" 19 "github.com/unicornultrafoundation/go-u2u/rlp" 20 21 "github.com/unicornultrafoundation/go-helios/hash" 22 "github.com/unicornultrafoundation/go-helios/native/idx" 23 "github.com/unicornultrafoundation/go-helios/u2udb/batched" 24 "github.com/unicornultrafoundation/go-helios/u2udb/pebble" 25 26 "github.com/unicornultrafoundation/go-u2u/gossip" 27 "github.com/unicornultrafoundation/go-u2u/utils/dbutil/autocompact" 28 ) 29 30 var ( 31 eventsFileHeader = hexutils.HexToBytes("7e995678") 32 eventsFileVersion = hexutils.HexToBytes("00010001") 33 ) 34 35 // statsReportLimit is the time limit during import and export after which we 36 // always print out progress. This avoids the user wondering what's going on. 37 const statsReportLimit = 8 * time.Second 38 39 func exportEvents(ctx *cli.Context) error { 40 if len(ctx.Args()) < 1 { 41 utils.Fatalf("This command requires an argument.") 42 } 43 44 cfg := makeAllConfigs(ctx) 45 46 rawDbs := makeDirectDBsProducer(cfg) 47 gdb := makeGossipStore(rawDbs, cfg) 48 defer gdb.Close() 49 50 fn := ctx.Args().First() 51 52 // Open the file handle and potentially wrap with a gzip stream 53 fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm) 54 if err != nil { 55 return err 56 } 57 defer fh.Close() 58 59 var writer io.Writer = fh 60 if strings.HasSuffix(fn, ".gz") { 61 writer = gzip.NewWriter(writer) 62 defer writer.(*gzip.Writer).Close() 63 } 64 65 from := idx.Epoch(1) 66 if len(ctx.Args()) > 1 { 67 n, err := strconv.ParseUint(ctx.Args().Get(1), 10, 32) 68 if err != nil { 69 return err 70 } 71 from = idx.Epoch(n) 72 } 73 to := idx.Epoch(0) 74 if len(ctx.Args()) > 2 { 75 n, err := strconv.ParseUint(ctx.Args().Get(2), 10, 32) 76 if err != nil { 77 return err 78 } 79 to = idx.Epoch(n) 80 } 81 82 log.Info("Exporting events to file", "file", fn) 83 // Write header and version 84 _, err = writer.Write(append(eventsFileHeader, eventsFileVersion...)) 85 if err != nil { 86 return err 87 } 88 err = exportTo(writer, gdb, from, to) 89 if err != nil { 90 utils.Fatalf("Export error: %v\n", err) 91 } 92 93 return nil 94 } 95 96 // exportTo writer the active chain. 97 func exportTo(w io.Writer, gdb *gossip.Store, from, to idx.Epoch) (err error) { 98 start, reported := time.Now(), time.Time{} 99 100 var ( 101 counter int 102 last hash.Event 103 ) 104 gdb.ForEachEventRLP(from.Bytes(), func(id hash.Event, event rlp.RawValue) bool { 105 if to >= from && id.Epoch() > to { 106 return false 107 } 108 counter++ 109 _, err = w.Write(event) 110 if err != nil { 111 return false 112 } 113 last = id 114 if counter%100 == 1 && time.Since(reported) >= statsReportLimit { 115 log.Info("Exporting events", "last", last.String(), "exported", counter, "elapsed", common.PrettyDuration(time.Since(start))) 116 reported = time.Now() 117 } 118 return true 119 }) 120 log.Info("Exported events", "last", last.String(), "exported", counter, "elapsed", common.PrettyDuration(time.Since(start))) 121 122 return 123 } 124 125 func exportEvmKeys(ctx *cli.Context) error { 126 if len(ctx.Args()) < 1 { 127 utils.Fatalf("This command requires an argument.") 128 } 129 130 cfg := makeAllConfigs(ctx) 131 132 rawDbs := makeDirectDBsProducer(cfg) 133 gdb := makeGossipStore(rawDbs, cfg) 134 defer gdb.Close() 135 136 fn := ctx.Args().First() 137 138 keysDB_, err := pebble.New(fn, 1024*opt.MiB, utils.MakeDatabaseHandles()/2, nil, nil) 139 if err != nil { 140 return err 141 } 142 keysDB := batched.Wrap(autocompact.Wrap2M(keysDB_, opt.GiB, 16*opt.GiB, true, "evm-keys")) 143 defer keysDB.Close() 144 145 it := gdb.EvmStore().EvmDb.NewIterator(nil, nil) 146 // iterate only over MPT data 147 it = mptAndPreimageIterator{it} 148 defer it.Release() 149 150 log.Info("Exporting EVM keys", "dir", fn) 151 for it.Next() { 152 if err := keysDB.Put(it.Key(), []byte{0}); err != nil { 153 return err 154 } 155 } 156 log.Info("Exported EVM keys", "dir", fn) 157 return nil 158 }