2022-05-24 20:39:40 +02:00
// Copyright 2021 The go-ethereum Authors
2021-02-23 11:27:32 +01:00
// This file is part of go-ethereum.
//
// go-ethereum is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// go-ethereum is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
package main
import (
2021-11-02 18:31:45 +08:00
"bytes"
2021-02-23 11:27:32 +01:00
"fmt"
2023-09-25 11:16:36 +08:00
"math"
2021-02-23 11:27:32 +01:00
"os"
2021-11-02 18:31:45 +08:00
"os/signal"
2021-02-23 11:27:32 +01:00
"path/filepath"
2021-03-30 13:57:21 +02:00
"strconv"
2021-11-02 18:31:45 +08:00
"strings"
"syscall"
2021-02-23 11:27:32 +01:00
"time"
"github.com/ethereum/go-ethereum/cmd/utils"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/console/prompt"
"github.com/ethereum/go-ethereum/core/rawdb"
2022-01-18 11:30:41 +01:00
"github.com/ethereum/go-ethereum/core/state/snapshot"
2022-05-17 13:01:46 +02:00
"github.com/ethereum/go-ethereum/crypto"
2021-02-23 11:27:32 +01:00
"github.com/ethereum/go-ethereum/ethdb"
2022-07-25 17:07:44 +08:00
"github.com/ethereum/go-ethereum/internal/flags"
2021-02-23 11:27:32 +01:00
"github.com/ethereum/go-ethereum/log"
2021-03-30 13:57:21 +02:00
"github.com/ethereum/go-ethereum/trie"
2023-12-28 16:48:15 +08:00
"github.com/ethereum/go-ethereum/trie/triedb/pathdb"
2022-01-18 11:30:41 +01:00
"github.com/olekukonko/tablewriter"
2022-06-27 18:22:36 +02:00
"github.com/urfave/cli/v2"
2021-02-23 11:27:32 +01:00
)
var (
2022-06-27 18:22:36 +02:00
removedbCommand = & cli . Command {
Action : removeDB ,
2021-02-23 11:27:32 +01:00
Name : "removedb" ,
Usage : "Remove blockchain and state databases" ,
ArgsUsage : "" ,
2022-05-03 14:46:17 +08:00
Flags : utils . DatabasePathFlags ,
2021-02-23 11:27:32 +01:00
Description : `
Remove blockchain and state databases ` ,
}
2022-06-27 18:22:36 +02:00
dbCommand = & cli . Command {
2021-02-23 11:27:32 +01:00
Name : "db" ,
Usage : "Low level database operations" ,
ArgsUsage : "" ,
2022-06-27 18:22:36 +02:00
Subcommands : [ ] * cli . Command {
2021-02-23 11:27:32 +01:00
dbInspectCmd ,
dbStatCmd ,
dbCompactCmd ,
dbGetCmd ,
dbDeleteCmd ,
2023-12-28 16:48:15 +08:00
dbInspectTrieCmd ,
2021-02-23 11:27:32 +01:00
dbPutCmd ,
2021-03-30 13:57:21 +02:00
dbGetSlotsCmd ,
2021-04-13 15:45:30 +02:00
dbDumpFreezerIndex ,
2021-11-02 18:31:45 +08:00
dbImportCmd ,
dbExportCmd ,
2022-01-18 11:30:41 +01:00
dbMetadataCmd ,
2022-07-05 11:14:21 +08:00
ancientInspectCmd ,
2023-08-23 17:46:08 +08:00
// no legacy stored receipts for bsc
// dbMigrateFreezerCmd,
2022-05-17 13:01:46 +02:00
dbCheckStateContentCmd ,
2023-09-25 11:16:36 +08:00
dbHbss2PbssCmd ,
dbTrieGetCmd ,
dbTrieDeleteCmd ,
2021-02-23 11:27:32 +01:00
} ,
}
2022-06-27 18:22:36 +02:00
dbInspectCmd = & cli . Command {
Action : inspect ,
2021-02-23 11:27:32 +01:00
Name : "inspect" ,
ArgsUsage : "<prefix> <start>" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-03-23 02:06:30 +08:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-02-23 11:27:32 +01:00
Usage : "Inspect the storage size for each type of data in the database" ,
Description : ` This commands iterates the entire database. If the optional 'prefix' and 'start' arguments are provided, then the iteration is limited to the given subset of data. ` ,
}
2023-12-28 16:48:15 +08:00
dbInspectTrieCmd = & cli . Command {
Action : inspectTrie ,
Name : "inspect-trie" ,
ArgsUsage : "<blocknum> <jobnum>" ,
Flags : [ ] cli . Flag {
utils . DataDirFlag ,
utils . SyncModeFlag ,
} ,
Usage : "Inspect the MPT tree of the account and contract." ,
Description : ` This commands iterates the entrie WorldState. ` ,
}
2022-06-27 18:22:36 +02:00
dbCheckStateContentCmd = & cli . Command {
Action : checkStateContent ,
2022-05-17 13:01:46 +02:00
Name : "check-state-content" ,
ArgsUsage : "<start (optional)>" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( utils . NetworkFlags , utils . DatabasePathFlags ) ,
2022-05-17 13:01:46 +02:00
Usage : "Verify that state data is cryptographically correct" ,
Description : ` This command iterates the entire database for 32 - byte keys , looking for rlp - encoded trie nodes .
For each trie node encountered , it checks that the key corresponds to the keccak256 ( value ) . If this is not true , this indicates
a data corruption . ` ,
}
2023-09-25 11:16:36 +08:00
dbHbss2PbssCmd = & cli . Command {
Action : hbss2pbss ,
Name : "hbss-to-pbss" ,
ArgsUsage : "<jobnum (optional)>" ,
Flags : [ ] cli . Flag {
utils . DataDirFlag ,
utils . SyncModeFlag ,
2023-09-27 15:01:49 +08:00
utils . ForceFlag ,
utils . AncientFlag ,
2023-09-25 11:16:36 +08:00
} ,
Usage : "Convert Hash-Base to Path-Base trie node." ,
Description : ` This command iterates the entire trie node database and convert the hash-base node to path-base node. ` ,
}
dbTrieGetCmd = & cli . Command {
Action : dbTrieGet ,
Name : "trie-get" ,
Usage : "Show the value of a trie node path key" ,
ArgsUsage : "[trie owner] <path-base key>" ,
Flags : [ ] cli . Flag {
utils . DataDirFlag ,
utils . SyncModeFlag ,
2023-11-29 15:04:50 +08:00
utils . BSCMainnetFlag ,
2023-12-25 10:58:52 +08:00
utils . ChapelFlag ,
2023-09-25 11:16:36 +08:00
utils . StateSchemeFlag ,
} ,
Description : "This command looks up the specified trie node key from the database." ,
}
dbTrieDeleteCmd = & cli . Command {
Action : dbTrieDelete ,
Name : "trie-delete" ,
Usage : "delete the specify trie node" ,
ArgsUsage : "[trie owner] <hash-base key> | <path-base key>" ,
Flags : [ ] cli . Flag {
utils . DataDirFlag ,
utils . SyncModeFlag ,
2023-11-29 15:04:50 +08:00
utils . BSCMainnetFlag ,
2023-12-25 10:58:52 +08:00
utils . ChapelFlag ,
2023-09-25 11:16:36 +08:00
utils . StateSchemeFlag ,
} ,
Description : "This command delete the specify trie node from the database." ,
}
2022-06-27 18:22:36 +02:00
dbStatCmd = & cli . Command {
Action : dbStats ,
2021-02-23 11:27:32 +01:00
Name : "stats" ,
Usage : "Print leveldb statistics" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-03-23 02:06:30 +08:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-02-23 11:27:32 +01:00
}
2022-06-27 18:22:36 +02:00
dbCompactCmd = & cli . Command {
Action : dbCompact ,
2021-02-23 11:27:32 +01:00
Name : "compact" ,
Usage : "Compact leveldb database. WARNING: May take a very long time" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-03-23 02:06:30 +08:00
utils . SyncModeFlag ,
utils . CacheFlag ,
utils . CacheDatabaseFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-02-23 11:27:32 +01:00
Description : ` This command performs a database compaction .
WARNING : This operation may take a very long time to finish , and may cause database
corruption if it is aborted during execution ' ! ` ,
}
2022-06-27 18:22:36 +02:00
dbGetCmd = & cli . Command {
Action : dbGet ,
2021-03-23 02:06:30 +08:00
Name : "get" ,
Usage : "Show the value of a database key" ,
ArgsUsage : "<hex-encoded key>" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-03-23 02:06:30 +08:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-02-23 11:27:32 +01:00
Description : "This command looks up the specified database key from the database." ,
}
2022-06-27 18:22:36 +02:00
dbDeleteCmd = & cli . Command {
Action : dbDelete ,
2021-02-23 11:27:32 +01:00
Name : "delete" ,
Usage : "Delete a database key (WARNING: may corrupt your database)" ,
ArgsUsage : "<hex-encoded key>" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-03-23 02:06:30 +08:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-02-23 11:27:32 +01:00
Description : ` This command deletes the specified database key from the database .
WARNING : This is a low - level operation which may cause database corruption ! ` ,
}
2022-06-27 18:22:36 +02:00
dbPutCmd = & cli . Command {
Action : dbPut ,
2021-02-23 11:27:32 +01:00
Name : "put" ,
Usage : "Set the value of a database key (WARNING: may corrupt your database)" ,
ArgsUsage : "<hex-encoded key> <hex-encoded value>" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-03-23 02:06:30 +08:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-02-23 11:27:32 +01:00
Description : ` This command sets a given database key to the given value .
WARNING : This is a low - level operation which may cause database corruption ! ` ,
}
2022-06-27 18:22:36 +02:00
dbGetSlotsCmd = & cli . Command {
Action : dbDumpTrie ,
2021-03-30 13:57:21 +02:00
Name : "dumptrie" ,
Usage : "Show the storage key/values of a given storage trie" ,
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes
* trie: add docs
* trie: address comments
* cmd, core, eth, les, light, trie: trie id
* trie: add tests
* trie, core: updates
* trie: fix imports
* trie: add utility print-method for nodeset
* trie: import err
* trie: fix go vet warnings
Co-authored-by: Martin Holst Swende <martin@swende.se>
2022-09-27 16:01:02 +08:00
ArgsUsage : "<hex-encoded state root> <hex-encoded account hash> <hex-encoded storage trie root> <hex-encoded start (optional)> <int max elements (optional)>" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-03-30 13:57:21 +02:00
utils . SyncModeFlag ,
all: activate pbss as experimental feature from eth (#26274)
* all: activate pbss
* core/rawdb: fix compilation error
* cma, core, eth, les, trie: address comments
* cmd, core, eth, trie: polish code
* core, cmd, eth: address comments
* cmd, core, eth, les, light, tests: address comment
* cmd/utils: shorten log message
* trie/triedb/pathdb: limit node buffer size to 1gb
* cmd/utils: fix opening non-existing db
* cmd/utils: rename flag name
* cmd, core: group chain history flags and fix tests
* core, eth, trie: fix memory leak in snapshot generation
* cmd, eth, internal: deprecate flags
* all: enable state tests for pathdb, fixes
* cmd, core: polish code
* trie/triedb/pathdb: limit the node buffer size to 256mb
---------
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-08-11 03:21:36 +08:00
utils . StateSchemeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-03-30 13:57:21 +02:00
Description : "This command looks up the specified database key from the database." ,
}
2022-06-27 18:22:36 +02:00
dbDumpFreezerIndex = & cli . Command {
Action : freezerInspect ,
2021-04-13 15:45:30 +02:00
Name : "freezer-index" ,
2022-08-08 17:08:36 +08:00
Usage : "Dump out the index of a specific freezer table" ,
ArgsUsage : "<freezer-type> <table-type> <start (int)> <end (int)>" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-04-13 15:45:30 +02:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-04-13 15:45:30 +02:00
Description : "This command displays information about the freezer index." ,
}
2022-06-27 18:22:36 +02:00
dbImportCmd = & cli . Command {
Action : importLDBdata ,
2021-11-02 18:31:45 +08:00
Name : "import" ,
Usage : "Imports leveldb-data from an exported RLP dump." ,
ArgsUsage : "<dumpfile> <start (optional)" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-11-02 18:31:45 +08:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-11-02 18:31:45 +08:00
Description : "The import command imports the specific chain data from an RLP encoded stream." ,
}
2022-06-27 18:22:36 +02:00
dbExportCmd = & cli . Command {
Action : exportChaindata ,
2021-11-02 18:31:45 +08:00
Name : "export" ,
Usage : "Exports the chain data into an RLP dump. If the <dumpfile> has .gz suffix, gzip compression will be used." ,
ArgsUsage : "<type> <dumpfile>" ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2021-11-02 18:31:45 +08:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2021-11-02 18:31:45 +08:00
Description : "Exports the specified chain data to an RLP encoded stream, optionally gzip-compressed." ,
}
2022-06-27 18:22:36 +02:00
dbMetadataCmd = & cli . Command {
Action : showMetaData ,
2022-01-18 11:30:41 +01:00
Name : "metadata" ,
Usage : "Shows metadata about the chain status." ,
2022-07-25 17:07:44 +08:00
Flags : flags . Merge ( [ ] cli . Flag {
2022-01-18 11:30:41 +01:00
utils . SyncModeFlag ,
2022-05-03 14:46:17 +08:00
} , utils . NetworkFlags , utils . DatabasePathFlags ) ,
2022-01-18 11:30:41 +01:00
Description : "Shows metadata about the chain status." ,
}
2023-08-23 17:46:08 +08:00
ancientInspectCmd = & cli . Command {
Action : ancientInspect ,
2022-07-05 11:14:21 +08:00
Name : "inspect-reserved-oldest-blocks" ,
Flags : [ ] cli . Flag {
utils . DataDirFlag ,
} ,
Usage : "Inspect the ancientStore information" ,
Description : ` This commands will read current offset from kvdb , which is the current offset and starting BlockNumber
of ancientStore , will also displays the reserved number of blocks in ancientStore ` ,
}
2021-02-23 11:27:32 +01:00
)
func removeDB ( ctx * cli . Context ) error {
stack , config := makeConfigNode ( ctx )
// Remove the full node state database
path := stack . ResolvePath ( "chaindata" )
if common . FileExist ( path ) {
confirmAndRemoveDB ( path , "full node state database" )
} else {
log . Info ( "Full node state database missing" , "path" , path )
}
// Remove the full node ancient database
path = config . Eth . DatabaseFreezer
switch {
case path == "" :
path = filepath . Join ( stack . ResolvePath ( "chaindata" ) , "ancient" )
case ! filepath . IsAbs ( path ) :
path = config . Node . ResolvePath ( path )
}
if common . FileExist ( path ) {
confirmAndRemoveDB ( path , "full node ancient database" )
} else {
log . Info ( "Full node ancient database missing" , "path" , path )
}
// Remove the light node database
path = stack . ResolvePath ( "lightchaindata" )
if common . FileExist ( path ) {
confirmAndRemoveDB ( path , "light node database" )
} else {
log . Info ( "Light node database missing" , "path" , path )
}
return nil
}
// confirmAndRemoveDB prompts the user for a last confirmation and removes the
// folder if accepted.
func confirmAndRemoveDB ( database string , kind string ) {
confirm , err := prompt . Stdin . PromptConfirm ( fmt . Sprintf ( "Remove %s (%s)?" , kind , database ) )
switch {
case err != nil :
utils . Fatalf ( "%v" , err )
case ! confirm :
log . Info ( "Database deletion skipped" , "path" , database )
default :
start := time . Now ( )
filepath . Walk ( database , func ( path string , info os . FileInfo , err error ) error {
// If we're at the top level folder, recurse into
if path == database {
return nil
}
// Delete all the files, but not subfolders
if ! info . IsDir ( ) {
os . Remove ( path )
return nil
}
return filepath . SkipDir
} )
log . Info ( "Database successfully deleted" , "path" , database , "elapsed" , common . PrettyDuration ( time . Since ( start ) ) )
}
}
2023-12-28 16:48:15 +08:00
func inspectTrie ( ctx * cli . Context ) error {
if ctx . NArg ( ) < 1 {
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
if ctx . NArg ( ) > 3 {
return fmt . Errorf ( "Max 3 arguments: %v" , ctx . Command . ArgsUsage )
}
var (
blockNumber uint64
trieRootHash common . Hash
jobnum uint64
)
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
db := utils . MakeChainDatabase ( ctx , stack , true , false )
defer db . Close ( )
var headerBlockHash common . Hash
if ctx . NArg ( ) >= 1 {
if ctx . Args ( ) . Get ( 0 ) == "latest" {
headerHash := rawdb . ReadHeadHeaderHash ( db )
blockNumber = * ( rawdb . ReadHeaderNumber ( db , headerHash ) )
} else if ctx . Args ( ) . Get ( 0 ) == "snapshot" {
trieRootHash = rawdb . ReadSnapshotRoot ( db )
blockNumber = math . MaxUint64
} else {
var err error
blockNumber , err = strconv . ParseUint ( ctx . Args ( ) . Get ( 0 ) , 10 , 64 )
if err != nil {
return fmt . Errorf ( "failed to Parse blocknum, Args[0]: %v, err: %v" , ctx . Args ( ) . Get ( 0 ) , err )
}
}
if ctx . NArg ( ) == 1 {
jobnum = 1000
} else {
var err error
jobnum , err = strconv . ParseUint ( ctx . Args ( ) . Get ( 1 ) , 10 , 64 )
if err != nil {
return fmt . Errorf ( "failed to Parse jobnum, Args[1]: %v, err: %v" , ctx . Args ( ) . Get ( 1 ) , err )
}
}
if blockNumber != math . MaxUint64 {
headerBlockHash = rawdb . ReadCanonicalHash ( db , blockNumber )
if headerBlockHash == ( common . Hash { } ) {
return fmt . Errorf ( "ReadHeadBlockHash empry hash" )
}
blockHeader := rawdb . ReadHeader ( db , headerBlockHash , blockNumber )
trieRootHash = blockHeader . Root
}
if ( trieRootHash == common . Hash { } ) {
log . Error ( "Empty root hash" )
}
fmt . Printf ( "ReadBlockHeader, root: %v, blocknum: %v\n" , trieRootHash , blockNumber )
dbScheme := rawdb . ReadStateScheme ( db )
var config * trie . Config
if dbScheme == rawdb . PathScheme {
config = & trie . Config {
PathDB : pathdb . ReadOnly ,
}
} else if dbScheme == rawdb . HashScheme {
config = trie . HashDefaults
}
triedb := trie . NewDatabase ( db , config )
theTrie , err := trie . New ( trie . TrieID ( trieRootHash ) , triedb )
if err != nil {
fmt . Printf ( "fail to new trie tree, err: %v, rootHash: %v\n" , err , trieRootHash . String ( ) )
return err
}
theInspect , err := trie . NewInspector ( theTrie , triedb , trieRootHash , blockNumber , jobnum )
if err != nil {
return err
}
theInspect . Run ( )
theInspect . DisplayResult ( )
}
return nil
}
2021-02-23 11:27:32 +01:00
func inspect ( ctx * cli . Context ) error {
var (
prefix [ ] byte
start [ ] byte
)
if ctx . NArg ( ) > 2 {
2022-08-08 17:08:36 +08:00
return fmt . Errorf ( "max 2 arguments: %v" , ctx . Command . ArgsUsage )
2021-02-23 11:27:32 +01:00
}
if ctx . NArg ( ) >= 1 {
if d , err := hexutil . Decode ( ctx . Args ( ) . Get ( 0 ) ) ; err != nil {
return fmt . Errorf ( "failed to hex-decode 'prefix': %v" , err )
} else {
prefix = d
}
}
if ctx . NArg ( ) >= 2 {
if d , err := hexutil . Decode ( ctx . Args ( ) . Get ( 1 ) ) ; err != nil {
return fmt . Errorf ( "failed to hex-decode 'start': %v" , err )
} else {
start = d
}
}
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , true , false )
2021-03-23 02:06:30 +08:00
defer db . Close ( )
2021-02-23 11:27:32 +01:00
2021-03-23 02:06:30 +08:00
return rawdb . InspectDatabase ( db , prefix , start )
2021-02-23 11:27:32 +01:00
}
2022-07-05 11:14:21 +08:00
func ancientInspect ( ctx * cli . Context ) error {
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
db := utils . MakeChainDatabase ( ctx , stack , true , true )
defer db . Close ( )
return rawdb . AncientInspect ( db )
}
2022-05-17 13:01:46 +02:00
func checkStateContent ( ctx * cli . Context ) error {
var (
prefix [ ] byte
start [ ] byte
)
if ctx . NArg ( ) > 1 {
2022-05-30 18:37:42 +08:00
return fmt . Errorf ( "max 1 argument: %v" , ctx . Command . ArgsUsage )
2022-05-17 13:01:46 +02:00
}
if ctx . NArg ( ) > 0 {
if d , err := hexutil . Decode ( ctx . Args ( ) . First ( ) ) ; err != nil {
return fmt . Errorf ( "failed to hex-decode 'start': %v" , err )
} else {
start = d
}
}
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2023-08-23 17:46:08 +08:00
db := utils . MakeChainDatabase ( ctx , stack , true , false )
2022-05-17 13:01:46 +02:00
defer db . Close ( )
var (
it = rawdb . NewKeyLengthIterator ( db . NewIterator ( prefix , start ) , 32 )
hasher = crypto . NewKeccakState ( )
got = make ( [ ] byte , 32 )
errs int
count int
startTime = time . Now ( )
lastLog = time . Now ( )
)
for it . Next ( ) {
count ++
k := it . Key ( )
2022-05-30 18:37:42 +08:00
v := it . Value ( )
2022-05-17 13:01:46 +02:00
hasher . Reset ( )
hasher . Write ( v )
hasher . Read ( got )
if ! bytes . Equal ( k , got ) {
errs ++
2022-07-04 17:03:32 +09:00
fmt . Printf ( "Error at %#x\n" , k )
fmt . Printf ( " Hash: %#x\n" , got )
fmt . Printf ( " Data: %#x\n" , v )
2022-05-17 13:01:46 +02:00
}
if time . Since ( lastLog ) > 8 * time . Second {
log . Info ( "Iterating the database" , "at" , fmt . Sprintf ( "%#x" , k ) , "elapsed" , common . PrettyDuration ( time . Since ( startTime ) ) )
lastLog = time . Now ( )
}
}
if err := it . Error ( ) ; err != nil {
return err
}
log . Info ( "Iterated the state content" , "errors" , errs , "items" , count )
return nil
}
2022-05-06 19:28:42 +08:00
func showLeveldbStats ( db ethdb . KeyValueStater ) {
2021-02-23 11:27:32 +01:00
if stats , err := db . Stat ( "leveldb.stats" ) ; err != nil {
log . Warn ( "Failed to read database stats" , "error" , err )
} else {
fmt . Println ( stats )
}
if ioStats , err := db . Stat ( "leveldb.iostats" ) ; err != nil {
log . Warn ( "Failed to read database iostats" , "error" , err )
} else {
fmt . Println ( ioStats )
}
}
func dbStats ( ctx * cli . Context ) error {
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2021-03-23 02:06:30 +08:00
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , true , false )
2021-03-23 02:06:30 +08:00
defer db . Close ( )
2021-02-23 11:27:32 +01:00
showLeveldbStats ( db )
return nil
}
func dbCompact ( ctx * cli . Context ) error {
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2021-03-23 02:06:30 +08:00
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , false , false )
2021-03-23 02:06:30 +08:00
defer db . Close ( )
log . Info ( "Stats before compaction" )
2021-02-23 11:27:32 +01:00
showLeveldbStats ( db )
2021-03-23 02:06:30 +08:00
2021-02-23 11:27:32 +01:00
log . Info ( "Triggering compaction" )
2021-03-23 02:06:30 +08:00
if err := db . Compact ( nil , nil ) ; err != nil {
2021-02-23 11:27:32 +01:00
log . Info ( "Compact err" , "error" , err )
2021-03-23 02:06:30 +08:00
return err
2021-02-23 11:27:32 +01:00
}
2021-03-23 02:06:30 +08:00
log . Info ( "Stats after compaction" )
2021-02-23 11:27:32 +01:00
showLeveldbStats ( db )
2021-03-23 02:06:30 +08:00
return nil
2021-02-23 11:27:32 +01:00
}
// dbGet shows the value of a given database key
func dbGet ( ctx * cli . Context ) error {
if ctx . NArg ( ) != 1 {
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2021-03-23 02:06:30 +08:00
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , true , false )
2021-02-23 11:27:32 +01:00
defer db . Close ( )
2021-03-23 02:06:30 +08:00
2022-04-27 08:37:48 +02:00
key , err := common . ParseHexOrString ( ctx . Args ( ) . Get ( 0 ) )
2021-02-23 11:27:32 +01:00
if err != nil {
log . Info ( "Could not decode the key" , "error" , err )
return err
}
2021-10-18 13:18:49 +03:00
2021-02-23 11:27:32 +01:00
data , err := db . Get ( key )
if err != nil {
2022-07-18 13:22:56 +02:00
log . Info ( "Get operation failed" , "key" , fmt . Sprintf ( "%#x" , key ) , "error" , err )
2021-02-23 11:27:32 +01:00
return err
}
2021-03-23 02:06:30 +08:00
fmt . Printf ( "key %#x: %#x\n" , key , data )
2021-02-23 11:27:32 +01:00
return nil
}
2023-09-25 11:16:36 +08:00
// dbTrieGet shows the value of a given database key
func dbTrieGet ( ctx * cli . Context ) error {
if ctx . NArg ( ) < 1 || ctx . NArg ( ) > 2 {
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
db := utils . MakeChainDatabase ( ctx , stack , false , false )
defer db . Close ( )
scheme := ctx . String ( utils . StateSchemeFlag . Name )
if scheme == "" {
scheme = rawdb . HashScheme
}
if scheme == rawdb . PathScheme {
var (
pathKey [ ] byte
owner [ ] byte
err error
)
if ctx . NArg ( ) == 1 {
pathKey , err = hexutil . Decode ( ctx . Args ( ) . Get ( 0 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
nodeVal , hash := rawdb . ReadAccountTrieNode ( db , pathKey )
log . Info ( "TrieGet result " , "PathKey" , common . Bytes2Hex ( pathKey ) , "Hash: " , hash , "node: " , trie . NodeString ( hash . Bytes ( ) , nodeVal ) )
} else if ctx . NArg ( ) == 2 {
owner , err = hexutil . Decode ( ctx . Args ( ) . Get ( 0 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
pathKey , err = hexutil . Decode ( ctx . Args ( ) . Get ( 1 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
nodeVal , hash := rawdb . ReadStorageTrieNode ( db , common . BytesToHash ( owner ) , pathKey )
log . Info ( "TrieGet result " , "PathKey: " , common . Bytes2Hex ( pathKey ) , "Owner: " , common . BytesToHash ( owner ) , "Hash: " , hash , "node: " , trie . NodeString ( hash . Bytes ( ) , nodeVal ) )
}
} else if scheme == rawdb . HashScheme {
if ctx . NArg ( ) == 1 {
hashKey , err := hexutil . Decode ( ctx . Args ( ) . Get ( 0 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
val , err := db . Get ( hashKey )
if err != nil {
log . Error ( "db get failed, " , "error: " , err )
return err
}
log . Info ( "TrieGet result " , "HashKey: " , common . BytesToHash ( hashKey ) , "node: " , trie . NodeString ( hashKey , val ) )
} else {
log . Error ( "args too much" )
}
}
return nil
}
// dbTrieDelete delete the trienode of a given database key
func dbTrieDelete ( ctx * cli . Context ) error {
if ctx . NArg ( ) < 1 || ctx . NArg ( ) > 2 {
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
db := utils . MakeChainDatabase ( ctx , stack , false , false )
defer db . Close ( )
scheme := ctx . String ( utils . StateSchemeFlag . Name )
if scheme == "" {
scheme = rawdb . HashScheme
}
if scheme == rawdb . PathScheme {
var (
pathKey [ ] byte
owner [ ] byte
err error
)
if ctx . NArg ( ) == 1 {
pathKey , err = hexutil . Decode ( ctx . Args ( ) . Get ( 0 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
rawdb . DeleteAccountTrieNode ( db , pathKey )
} else if ctx . NArg ( ) == 2 {
owner , err = hexutil . Decode ( ctx . Args ( ) . Get ( 0 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
pathKey , err = hexutil . Decode ( ctx . Args ( ) . Get ( 1 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
rawdb . DeleteStorageTrieNode ( db , common . BytesToHash ( owner ) , pathKey )
}
} else if scheme == rawdb . HashScheme {
if ctx . NArg ( ) == 1 {
hashKey , err := hexutil . Decode ( ctx . Args ( ) . Get ( 0 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
err = db . Delete ( hashKey )
if err != nil {
log . Error ( "db delete failed" , "err" , err )
return err
}
} else {
log . Error ( "args too much" )
}
}
return nil
}
2021-02-23 11:27:32 +01:00
// dbDelete deletes a key from the database
func dbDelete ( ctx * cli . Context ) error {
if ctx . NArg ( ) != 1 {
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2021-03-23 02:06:30 +08:00
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , false , false )
2021-02-23 11:27:32 +01:00
defer db . Close ( )
2021-03-23 02:06:30 +08:00
2022-04-27 08:37:48 +02:00
key , err := common . ParseHexOrString ( ctx . Args ( ) . Get ( 0 ) )
2021-02-23 11:27:32 +01:00
if err != nil {
log . Info ( "Could not decode the key" , "error" , err )
return err
}
2021-03-23 02:06:30 +08:00
data , err := db . Get ( key )
if err == nil {
fmt . Printf ( "Previous value: %#x\n" , data )
}
2021-02-23 11:27:32 +01:00
if err = db . Delete ( key ) ; err != nil {
2022-07-18 13:22:56 +02:00
log . Info ( "Delete operation returned an error" , "key" , fmt . Sprintf ( "%#x" , key ) , "error" , err )
2021-02-23 11:27:32 +01:00
return err
}
return nil
}
// dbPut overwrite a value in the database
func dbPut ( ctx * cli . Context ) error {
if ctx . NArg ( ) != 2 {
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2021-03-23 02:06:30 +08:00
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , false , false )
2021-02-23 11:27:32 +01:00
defer db . Close ( )
2021-03-23 02:06:30 +08:00
2021-02-23 11:27:32 +01:00
var (
key [ ] byte
value [ ] byte
data [ ] byte
err error
)
2022-04-27 08:37:48 +02:00
key , err = common . ParseHexOrString ( ctx . Args ( ) . Get ( 0 ) )
2021-02-23 11:27:32 +01:00
if err != nil {
log . Info ( "Could not decode the key" , "error" , err )
return err
}
value , err = hexutil . Decode ( ctx . Args ( ) . Get ( 1 ) )
if err != nil {
log . Info ( "Could not decode the value" , "error" , err )
return err
}
data , err = db . Get ( key )
if err == nil {
2021-03-23 02:06:30 +08:00
fmt . Printf ( "Previous value: %#x\n" , data )
2021-02-23 11:27:32 +01:00
}
return db . Put ( key , value )
}
2021-03-30 13:57:21 +02:00
// dbDumpTrie shows the key-value slots of a given storage trie
func dbDumpTrie ( ctx * cli . Context ) error {
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes
* trie: add docs
* trie: address comments
* cmd, core, eth, les, light, trie: trie id
* trie: add tests
* trie, core: updates
* trie: fix imports
* trie: add utility print-method for nodeset
* trie: import err
* trie: fix go vet warnings
Co-authored-by: Martin Holst Swende <martin@swende.se>
2022-09-27 16:01:02 +08:00
if ctx . NArg ( ) < 3 {
2021-03-30 13:57:21 +02:00
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , true , false )
2021-03-30 13:57:21 +02:00
defer db . Close ( )
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes
* trie: add docs
* trie: address comments
* cmd, core, eth, les, light, trie: trie id
* trie: add tests
* trie, core: updates
* trie: fix imports
* trie: add utility print-method for nodeset
* trie: import err
* trie: fix go vet warnings
Co-authored-by: Martin Holst Swende <martin@swende.se>
2022-09-27 16:01:02 +08:00
all: activate pbss as experimental feature from eth (#26274)
* all: activate pbss
* core/rawdb: fix compilation error
* cma, core, eth, les, trie: address comments
* cmd, core, eth, trie: polish code
* core, cmd, eth: address comments
* cmd, core, eth, les, light, tests: address comment
* cmd/utils: shorten log message
* trie/triedb/pathdb: limit node buffer size to 1gb
* cmd/utils: fix opening non-existing db
* cmd/utils: rename flag name
* cmd, core: group chain history flags and fix tests
* core, eth, trie: fix memory leak in snapshot generation
* cmd, eth, internal: deprecate flags
* all: enable state tests for pathdb, fixes
* cmd, core: polish code
* trie/triedb/pathdb: limit the node buffer size to 256mb
---------
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-08-11 03:21:36 +08:00
triedb := utils . MakeTrieDatabase ( ctx , db , false , true )
defer triedb . Close ( )
2021-03-30 13:57:21 +02:00
var (
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes
* trie: add docs
* trie: address comments
* cmd, core, eth, les, light, trie: trie id
* trie: add tests
* trie, core: updates
* trie: fix imports
* trie: add utility print-method for nodeset
* trie: import err
* trie: fix go vet warnings
Co-authored-by: Martin Holst Swende <martin@swende.se>
2022-09-27 16:01:02 +08:00
state [ ] byte
storage [ ] byte
account [ ] byte
start [ ] byte
max = int64 ( - 1 )
err error
2021-03-30 13:57:21 +02:00
)
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes
* trie: add docs
* trie: address comments
* cmd, core, eth, les, light, trie: trie id
* trie: add tests
* trie, core: updates
* trie: fix imports
* trie: add utility print-method for nodeset
* trie: import err
* trie: fix go vet warnings
Co-authored-by: Martin Holst Swende <martin@swende.se>
2022-09-27 16:01:02 +08:00
if state , err = hexutil . Decode ( ctx . Args ( ) . Get ( 0 ) ) ; err != nil {
log . Info ( "Could not decode the state root" , "error" , err )
2021-03-30 13:57:21 +02:00
return err
}
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes
* trie: add docs
* trie: address comments
* cmd, core, eth, les, light, trie: trie id
* trie: add tests
* trie, core: updates
* trie: fix imports
* trie: add utility print-method for nodeset
* trie: import err
* trie: fix go vet warnings
Co-authored-by: Martin Holst Swende <martin@swende.se>
2022-09-27 16:01:02 +08:00
if account , err = hexutil . Decode ( ctx . Args ( ) . Get ( 1 ) ) ; err != nil {
log . Info ( "Could not decode the account hash" , "error" , err )
return err
}
if storage , err = hexutil . Decode ( ctx . Args ( ) . Get ( 2 ) ) ; err != nil {
log . Info ( "Could not decode the storage trie root" , "error" , err )
return err
}
if ctx . NArg ( ) > 3 {
if start , err = hexutil . Decode ( ctx . Args ( ) . Get ( 3 ) ) ; err != nil {
2021-03-30 13:57:21 +02:00
log . Info ( "Could not decode the seek position" , "error" , err )
return err
}
}
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes
* trie: add docs
* trie: address comments
* cmd, core, eth, les, light, trie: trie id
* trie: add tests
* trie, core: updates
* trie: fix imports
* trie: add utility print-method for nodeset
* trie: import err
* trie: fix go vet warnings
Co-authored-by: Martin Holst Swende <martin@swende.se>
2022-09-27 16:01:02 +08:00
if ctx . NArg ( ) > 4 {
if max , err = strconv . ParseInt ( ctx . Args ( ) . Get ( 4 ) , 10 , 64 ) ; err != nil {
2021-03-30 13:57:21 +02:00
log . Info ( "Could not decode the max count" , "error" , err )
return err
}
}
cmd, core, eth, les, light: track deleted nodes (#25757)
* cmd, core, eth, les, light: track deleted nodes
* trie: add docs
* trie: address comments
* cmd, core, eth, les, light, trie: trie id
* trie: add tests
* trie, core: updates
* trie: fix imports
* trie: add utility print-method for nodeset
* trie: import err
* trie: fix go vet warnings
Co-authored-by: Martin Holst Swende <martin@swende.se>
2022-09-27 16:01:02 +08:00
id := trie . StorageTrieID ( common . BytesToHash ( state ) , common . BytesToHash ( account ) , common . BytesToHash ( storage ) )
all: activate pbss as experimental feature from eth (#26274)
* all: activate pbss
* core/rawdb: fix compilation error
* cma, core, eth, les, trie: address comments
* cmd, core, eth, trie: polish code
* core, cmd, eth: address comments
* cmd, core, eth, les, light, tests: address comment
* cmd/utils: shorten log message
* trie/triedb/pathdb: limit node buffer size to 1gb
* cmd/utils: fix opening non-existing db
* cmd/utils: rename flag name
* cmd, core: group chain history flags and fix tests
* core, eth, trie: fix memory leak in snapshot generation
* cmd, eth, internal: deprecate flags
* all: enable state tests for pathdb, fixes
* cmd, core: polish code
* trie/triedb/pathdb: limit the node buffer size to 256mb
---------
Co-authored-by: Martin Holst Swende <martin@swende.se>
Co-authored-by: Péter Szilágyi <peterke@gmail.com>
2023-08-11 03:21:36 +08:00
theTrie , err := trie . New ( id , triedb )
2021-03-30 13:57:21 +02:00
if err != nil {
return err
}
cmd, core/state, eth, tests, trie: improve state reader (#27428)
The state availability is checked during the creation of a state reader.
- In hash-based database, if the specified root node does not exist on disk disk, then
the state reader won't be created and an error will be returned.
- In path-based database, if the specified state layer is not available, then the
state reader won't be created and an error will be returned.
This change also contains a stricter semantics regarding the `Commit` operation: once it has been performed, the trie is no longer usable, and certain operations will return an error.
2023-06-21 03:31:45 +08:00
trieIt , err := theTrie . NodeIterator ( start )
2021-03-30 13:57:21 +02:00
if err != nil {
return err
}
var count int64
cmd, core/state, eth, tests, trie: improve state reader (#27428)
The state availability is checked during the creation of a state reader.
- In hash-based database, if the specified root node does not exist on disk disk, then
the state reader won't be created and an error will be returned.
- In path-based database, if the specified state layer is not available, then the
state reader won't be created and an error will be returned.
This change also contains a stricter semantics regarding the `Commit` operation: once it has been performed, the trie is no longer usable, and certain operations will return an error.
2023-06-21 03:31:45 +08:00
it := trie . NewIterator ( trieIt )
2021-03-30 13:57:21 +02:00
for it . Next ( ) {
if max > 0 && count == max {
fmt . Printf ( "Exiting after %d values\n" , count )
break
}
fmt . Printf ( " %d. key %#x: %#x\n" , count , it . Key , it . Value )
count ++
}
return it . Err
}
2021-04-13 15:45:30 +02:00
func freezerInspect ( ctx * cli . Context ) error {
2022-08-08 17:08:36 +08:00
if ctx . NArg ( ) < 4 {
2021-04-13 15:45:30 +02:00
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
2022-08-08 17:08:36 +08:00
var (
freezer = ctx . Args ( ) . Get ( 0 )
table = ctx . Args ( ) . Get ( 1 )
)
start , err := strconv . ParseInt ( ctx . Args ( ) . Get ( 2 ) , 10 , 64 )
if err != nil {
log . Info ( "Could not read start-param" , "err" , err )
2021-04-13 15:45:30 +02:00
return err
}
2022-08-08 17:08:36 +08:00
end , err := strconv . ParseInt ( ctx . Args ( ) . Get ( 3 ) , 10 , 64 )
if err != nil {
log . Info ( "Could not read count param" , "err" , err )
2021-04-13 15:45:30 +02:00
return err
}
stack , _ := makeConfigNode ( ctx )
2023-01-16 03:57:27 -05:00
ancient := stack . ResolveAncient ( "chaindata" , ctx . String ( utils . AncientFlag . Name ) )
stack . Close ( )
2022-08-08 17:08:36 +08:00
return rawdb . InspectFreezerTable ( ancient , freezer , table , start , end )
2021-10-18 13:18:49 +03:00
}
2021-11-02 18:31:45 +08:00
func importLDBdata ( ctx * cli . Context ) error {
start := 0
switch ctx . NArg ( ) {
case 1 :
break
case 2 :
s , err := strconv . Atoi ( ctx . Args ( ) . Get ( 1 ) )
if err != nil {
return fmt . Errorf ( "second arg must be an integer: %v" , err )
}
start = s
default :
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
var (
fName = ctx . Args ( ) . Get ( 0 )
stack , _ = makeConfigNode ( ctx )
interrupt = make ( chan os . Signal , 1 )
stop = make ( chan struct { } )
)
defer stack . Close ( )
signal . Notify ( interrupt , syscall . SIGINT , syscall . SIGTERM )
defer signal . Stop ( interrupt )
defer close ( interrupt )
go func ( ) {
if _ , ok := <- interrupt ; ok {
log . Info ( "Interrupted during ldb import, stopping at next batch" )
}
close ( stop )
} ( )
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , false , false )
2021-11-02 18:31:45 +08:00
return utils . ImportLDBData ( db , fName , int64 ( start ) , stop )
}
type preimageIterator struct {
iter ethdb . Iterator
}
func ( iter * preimageIterator ) Next ( ) ( byte , [ ] byte , [ ] byte , bool ) {
for iter . iter . Next ( ) {
key := iter . iter . Key ( )
if bytes . HasPrefix ( key , rawdb . PreimagePrefix ) && len ( key ) == ( len ( rawdb . PreimagePrefix ) + common . HashLength ) {
return utils . OpBatchAdd , key , iter . iter . Value ( ) , true
}
}
return 0 , nil , nil , false
}
func ( iter * preimageIterator ) Release ( ) {
iter . iter . Release ( )
}
type snapshotIterator struct {
init bool
account ethdb . Iterator
storage ethdb . Iterator
}
func ( iter * snapshotIterator ) Next ( ) ( byte , [ ] byte , [ ] byte , bool ) {
if ! iter . init {
iter . init = true
return utils . OpBatchDel , rawdb . SnapshotRootKey , nil , true
}
for iter . account . Next ( ) {
key := iter . account . Key ( )
if bytes . HasPrefix ( key , rawdb . SnapshotAccountPrefix ) && len ( key ) == ( len ( rawdb . SnapshotAccountPrefix ) + common . HashLength ) {
return utils . OpBatchAdd , key , iter . account . Value ( ) , true
}
}
for iter . storage . Next ( ) {
key := iter . storage . Key ( )
if bytes . HasPrefix ( key , rawdb . SnapshotStoragePrefix ) && len ( key ) == ( len ( rawdb . SnapshotStoragePrefix ) + 2 * common . HashLength ) {
return utils . OpBatchAdd , key , iter . storage . Value ( ) , true
}
}
return 0 , nil , nil , false
}
func ( iter * snapshotIterator ) Release ( ) {
iter . account . Release ( )
iter . storage . Release ( )
}
// chainExporters defines the export scheme for all exportable chain data.
var chainExporters = map [ string ] func ( db ethdb . Database ) utils . ChainDataIterator {
"preimage" : func ( db ethdb . Database ) utils . ChainDataIterator {
iter := db . NewIterator ( rawdb . PreimagePrefix , nil )
return & preimageIterator { iter : iter }
} ,
"snapshot" : func ( db ethdb . Database ) utils . ChainDataIterator {
account := db . NewIterator ( rawdb . SnapshotAccountPrefix , nil )
storage := db . NewIterator ( rawdb . SnapshotStoragePrefix , nil )
return & snapshotIterator { account : account , storage : storage }
} ,
}
func exportChaindata ( ctx * cli . Context ) error {
if ctx . NArg ( ) < 2 {
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
// Parse the required chain data type, make sure it's supported.
kind := ctx . Args ( ) . Get ( 0 )
kind = strings . ToLower ( strings . Trim ( kind , " " ) )
exporter , ok := chainExporters [ kind ]
if ! ok {
var kinds [ ] string
for kind := range chainExporters {
kinds = append ( kinds , kind )
}
return fmt . Errorf ( "invalid data type %s, supported types: %s" , kind , strings . Join ( kinds , ", " ) )
}
var (
stack , _ = makeConfigNode ( ctx )
interrupt = make ( chan os . Signal , 1 )
stop = make ( chan struct { } )
)
defer stack . Close ( )
signal . Notify ( interrupt , syscall . SIGINT , syscall . SIGTERM )
defer signal . Stop ( interrupt )
defer close ( interrupt )
go func ( ) {
if _ , ok := <- interrupt ; ok {
log . Info ( "Interrupted during db export, stopping at next batch" )
}
close ( stop )
} ( )
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , true , false )
2021-11-02 18:31:45 +08:00
return utils . ExportChaindata ( ctx . Args ( ) . Get ( 1 ) , kind , exporter ( db ) , stop )
}
2022-01-18 11:30:41 +01:00
func showMetaData ( ctx * cli . Context ) error {
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
2022-07-05 11:14:21 +08:00
db := utils . MakeChainDatabase ( ctx , stack , true , false )
2022-01-18 11:30:41 +01:00
ancients , err := db . Ancients ( )
if err != nil {
fmt . Fprintf ( os . Stderr , "Error accessing ancients: %v" , err )
}
2023-03-08 15:39:13 +08:00
data := rawdb . ReadChainMetadata ( db )
data = append ( data , [ ] string { "frozen" , fmt . Sprintf ( "%d items" , ancients ) } )
data = append ( data , [ ] string { "snapshotGenerator" , snapshot . ParseGeneratorStatus ( rawdb . ReadSnapshotGenerator ( db ) ) } )
2022-01-18 11:30:41 +01:00
if b := rawdb . ReadHeadBlock ( db ) ; b != nil {
data = append ( data , [ ] string { "headBlock.Hash" , fmt . Sprintf ( "%v" , b . Hash ( ) ) } )
data = append ( data , [ ] string { "headBlock.Root" , fmt . Sprintf ( "%v" , b . Root ( ) ) } )
2022-07-04 17:03:32 +09:00
data = append ( data , [ ] string { "headBlock.Number" , fmt . Sprintf ( "%d (%#x)" , b . Number ( ) , b . Number ( ) ) } )
2022-01-18 11:30:41 +01:00
}
if h := rawdb . ReadHeadHeader ( db ) ; h != nil {
data = append ( data , [ ] string { "headHeader.Hash" , fmt . Sprintf ( "%v" , h . Hash ( ) ) } )
data = append ( data , [ ] string { "headHeader.Root" , fmt . Sprintf ( "%v" , h . Root ) } )
2022-07-04 17:03:32 +09:00
data = append ( data , [ ] string { "headHeader.Number" , fmt . Sprintf ( "%d (%#x)" , h . Number , h . Number ) } )
2022-01-18 11:30:41 +01:00
}
table := tablewriter . NewWriter ( os . Stdout )
table . SetHeader ( [ ] string { "Field" , "Value" } )
table . AppendBulk ( data )
table . Render ( )
return nil
}
2023-09-25 11:16:36 +08:00
func hbss2pbss ( ctx * cli . Context ) error {
if ctx . NArg ( ) > 1 {
return fmt . Errorf ( "required arguments: %v" , ctx . Command . ArgsUsage )
}
var jobnum uint64
var err error
if ctx . NArg ( ) == 1 {
jobnum , err = strconv . ParseUint ( ctx . Args ( ) . Get ( 0 ) , 10 , 64 )
if err != nil {
return fmt . Errorf ( "failed to Parse jobnum, Args[1]: %v, err: %v" , ctx . Args ( ) . Get ( 1 ) , err )
}
} else {
// by default
jobnum = 1000
}
2023-09-27 15:01:49 +08:00
force := ctx . Bool ( utils . ForceFlag . Name )
2023-09-25 11:16:36 +08:00
stack , _ := makeConfigNode ( ctx )
defer stack . Close ( )
db := utils . MakeChainDatabase ( ctx , stack , false , false )
db . Sync ( )
defer db . Close ( )
2023-09-27 15:01:49 +08:00
// convert hbss trie node to pbss trie node
lastStateID := rawdb . ReadPersistentStateID ( db )
if lastStateID == 0 || force {
config := trie . HashDefaults
triedb := trie . NewDatabase ( db , config )
triedb . Cap ( 0 )
log . Info ( "hbss2pbss triedb" , "scheme" , triedb . Scheme ( ) )
defer triedb . Close ( )
headerHash := rawdb . ReadHeadHeaderHash ( db )
blockNumber := rawdb . ReadHeaderNumber ( db , headerHash )
if blockNumber == nil {
log . Error ( "read header number failed." )
return fmt . Errorf ( "read header number failed" )
}
2023-09-25 11:16:36 +08:00
2023-09-27 15:01:49 +08:00
log . Info ( "hbss2pbss converting" , "HeaderHash: " , headerHash . String ( ) , ", blockNumber: " , * blockNumber )
2023-09-25 11:16:36 +08:00
2023-09-27 15:01:49 +08:00
var headerBlockHash common . Hash
var trieRootHash common . Hash
2023-09-25 11:16:36 +08:00
2023-09-27 15:01:49 +08:00
if * blockNumber != math . MaxUint64 {
headerBlockHash = rawdb . ReadCanonicalHash ( db , * blockNumber )
if headerBlockHash == ( common . Hash { } ) {
return fmt . Errorf ( "ReadHeadBlockHash empty hash" )
}
blockHeader := rawdb . ReadHeader ( db , headerBlockHash , * blockNumber )
trieRootHash = blockHeader . Root
fmt . Println ( "Canonical Hash: " , headerBlockHash . String ( ) , ", TrieRootHash: " , trieRootHash . String ( ) )
}
if ( trieRootHash == common . Hash { } ) {
log . Error ( "Empty root hash" )
return fmt . Errorf ( "Empty root hash." )
}
2023-09-25 11:16:36 +08:00
2023-09-27 15:01:49 +08:00
id := trie . StateTrieID ( trieRootHash )
theTrie , err := trie . New ( id , triedb )
if err != nil {
log . Error ( "fail to new trie tree" , "err" , err , "rootHash" , err , trieRootHash . String ( ) )
return err
2023-09-25 11:16:36 +08:00
}
2023-09-27 15:01:49 +08:00
h2p , err := trie . NewHbss2Pbss ( theTrie , triedb , trieRootHash , * blockNumber , jobnum )
if err != nil {
log . Error ( "fail to new hash2pbss" , "err" , err , "rootHash" , err , trieRootHash . String ( ) )
return err
}
h2p . Run ( )
} else {
log . Info ( "Convert hbss to pbss success. Nothing to do." )
2023-09-25 11:16:36 +08:00
}
2023-09-27 15:01:49 +08:00
// repair state ancient offset
lastStateID = rawdb . ReadPersistentStateID ( db )
if lastStateID == 0 {
log . Error ( "Convert hbss to pbss trie node error. The last state id is still 0" )
}
ancient := stack . ResolveAncient ( "chaindata" , ctx . String ( utils . AncientFlag . Name ) )
err = rawdb . ResetStateFreezerTableOffset ( ancient , lastStateID )
2023-09-25 11:16:36 +08:00
if err != nil {
2023-09-27 15:01:49 +08:00
log . Error ( "Reset state freezer table offset failed" , "error" , err )
2023-09-25 11:16:36 +08:00
return err
}
2023-09-27 15:01:49 +08:00
// prune hbss trie node
err = rawdb . PruneHashTrieNodeInDataBase ( db )
2023-09-25 11:16:36 +08:00
if err != nil {
2023-09-27 15:01:49 +08:00
log . Error ( "Prune Hash trie node in database failed" , "error" , err )
2023-09-25 11:16:36 +08:00
return err
}
return nil
}