github.com/palisadeinc/bor@v0.0.0-20230615125219-ab7196213d15/internal/cli/snapshot.go (about) 1 // Snapshot related commands 2 3 package cli 4 5 import ( 6 "strings" 7 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/core/state/pruner" 10 "github.com/ethereum/go-ethereum/internal/cli/flagset" 11 "github.com/ethereum/go-ethereum/internal/cli/server" 12 "github.com/ethereum/go-ethereum/log" 13 "github.com/ethereum/go-ethereum/node" 14 15 "github.com/mitchellh/cli" 16 ) 17 18 // SnapshotCommand is the command to group the snapshot commands 19 type SnapshotCommand struct { 20 UI cli.Ui 21 } 22 23 // MarkDown implements cli.MarkDown interface 24 func (a *SnapshotCommand) MarkDown() string { 25 items := []string{ 26 "# snapshot", 27 "The ```snapshot``` command groups snapshot related actions:", 28 "- [```snapshot prune-state```](./snapshot_prune-state.md): Prune state databases at the given datadir location.", 29 } 30 31 return strings.Join(items, "\n\n") 32 } 33 34 // Help implements the cli.Command interface 35 func (c *SnapshotCommand) Help() string { 36 return `Usage: bor snapshot <subcommand> 37 38 This command groups snapshot related actions. 39 40 Prune the state trie: 41 42 $ bor snapshot prune-state` 43 } 44 45 // Synopsis implements the cli.Command interface 46 func (c *SnapshotCommand) Synopsis() string { 47 return "Snapshot related commands" 48 } 49 50 // Run implements the cli.Command interface 51 func (c *SnapshotCommand) Run(args []string) int { 52 return cli.RunResultHelp 53 } 54 55 type PruneStateCommand struct { 56 *Meta 57 58 datadirAncient string 59 cache uint64 60 cacheTrie uint64 61 cacheTrieJournal string 62 bloomfilterSize uint64 63 } 64 65 // MarkDown implements cli.MarkDown interface 66 func (c *PruneStateCommand) MarkDown() string { 67 items := []string{ 68 "# Prune state", 69 "The ```bor snapshot prune-state``` command will prune historical state data with the help of the state snapshot. All trie nodes and contract codes that do not belong to the specified version state will be deleted from the database. After pruning, only two version states are available: genesis and the specific one.", 70 c.Flags().MarkDown(), 71 } 72 73 return strings.Join(items, "\n\n") 74 } 75 76 // Help implements the cli.Command interface 77 func (c *PruneStateCommand) Help() string { 78 return `Usage: bor snapshot prune-state <datadir> 79 80 This command will prune state databases at the given datadir location` + c.Flags().Help() 81 } 82 83 // Synopsis implements the cli.Command interface 84 func (c *PruneStateCommand) Synopsis() string { 85 return "Prune state databases" 86 } 87 88 // Flags: datadir, datadir.ancient, cache.trie.journal, bloomfilter.size 89 func (c *PruneStateCommand) Flags() *flagset.Flagset { 90 flags := c.NewFlagSet("prune-state") 91 92 flags.StringFlag(&flagset.StringFlag{ 93 Name: "datadir.ancient", 94 Value: &c.datadirAncient, 95 Usage: "Path of the ancient data directory to store information", 96 Default: "", 97 }) 98 99 flags.Uint64Flag(&flagset.Uint64Flag{ 100 Name: "cache", 101 Usage: "Megabytes of memory allocated to internal caching", 102 Value: &c.cache, 103 Default: 1024.0, 104 Group: "Cache", 105 }) 106 107 flags.Uint64Flag(&flagset.Uint64Flag{ 108 Name: "cache.trie", 109 Usage: "Percentage of cache memory allowance to use for trie caching", 110 Value: &c.cacheTrie, 111 Default: 25, 112 Group: "Cache", 113 }) 114 115 flags.StringFlag(&flagset.StringFlag{ 116 Name: "cache.trie.journal", 117 Value: &c.cacheTrieJournal, 118 Usage: "Path of the trie journal directory to store information", 119 Default: trieCacheJournalPath, 120 Group: "Cache", 121 }) 122 123 flags.Uint64Flag(&flagset.Uint64Flag{ 124 Name: "bloomfilter.size", 125 Value: &c.bloomfilterSize, 126 Usage: "Size of the bloom filter", 127 Default: 2048, 128 }) 129 130 return flags 131 } 132 133 // Run implements the cli.Command interface 134 func (c *PruneStateCommand) Run(args []string) int { 135 flags := c.Flags() 136 137 if err := flags.Parse(args); err != nil { 138 c.UI.Error(err.Error()) 139 return 1 140 } 141 142 datadir := c.dataDir 143 if datadir == "" { 144 c.UI.Error("datadir is required") 145 return 1 146 } 147 148 // Create the node 149 node, err := node.New(&node.Config{ 150 DataDir: datadir, 151 }) 152 153 if err != nil { 154 c.UI.Error(err.Error()) 155 return 1 156 } 157 158 dbHandles, err := server.MakeDatabaseHandles(0) 159 if err != nil { 160 c.UI.Error(err.Error()) 161 return 1 162 } 163 164 chaindb, err := node.OpenDatabaseWithFreezer(chaindataPath, int(c.cache), dbHandles, c.datadirAncient, "", false) 165 166 if err != nil { 167 c.UI.Error(err.Error()) 168 return 1 169 } 170 171 pruner, err := pruner.NewPruner(chaindb, node.ResolvePath(""), node.ResolvePath(c.cacheTrieJournal), c.bloomfilterSize) 172 if err != nil { 173 log.Error("Failed to open snapshot tree", "err", err) 174 return 1 175 } 176 177 if err = pruner.Prune(common.Hash{}); err != nil { 178 log.Error("Failed to prune state", "err", err) 179 return 1 180 } 181 182 return 0 183 }