-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[R4R]offline block prune #543
Conversation
306e6c7
to
2b0d305
Compare
e33105f
to
4046f25
Compare
4fe76ff
to
cad935c
Compare
cad935c
to
fa8de66
Compare
cmd/geth/snapshot.go
Outdated
}, | ||
Description: ` | ||
Offline prune for block data. | ||
For AncientFlag, please specify the absolute path of node/geth/chaindata. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it have to be absolute
path?
cmd/geth/snapshot.go
Outdated
return nil | ||
} | ||
|
||
func getAncientPath(ctx *cli.Context) string { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let us follow the same code style. Please remove this func, but use ctx.GlobalString(utils.AncientFlag.Name)
directly.
cmd/geth/snapshot.go
Outdated
defer stack.Close() | ||
|
||
chaindb := utils.MakeChainDatabaseForBlockPrune(ctx, stack, false) | ||
chaindb.Close() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you meaning defer chaindb.Close()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this is for closing it on purpose, because in the later code, there'll be many times of open/close the same db, crash will occur if did not close it.
cmd/geth/snapshot.go
Outdated
oldAncientPath = path + "/ancient" | ||
newAncientPath = path + "/ancient_back" | ||
} else { | ||
utils.Fatalf("Prune failed, did not specify the AncientPath %v") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Better have a default ancient
path.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You have %v
here , but no arg.
cmd/geth/snapshot.go
Outdated
return errors.New("Prune failed, did not specify the AncientPath") | ||
} | ||
|
||
//TODO for filelock |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will we have file lock?
cmd/geth/snapshot.go
Outdated
// if err != nil { | ||
// utils.Fatalf("Failed to read genesis file: %v", err) | ||
// } | ||
for _, name := range []string{"chaindata"} { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why range a slice that only have one const item?
cmd/geth/snapshot.go
Outdated
root := stack.ResolvePath(name) | ||
switch { | ||
case oldAncientPath == "": | ||
oldAncientPath = filepath.Join(root, "ancient") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not possible to happen, since you forbidden it to be empty in previous logic.
cmd/geth/snapshot.go
Outdated
} | ||
pruner, err := pruner.NewBlockPruner(chaindb, stack, oldAncientPath) | ||
if err != nil { | ||
utils.Fatalf("Failed to create block pruner", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Get err arg here, but no %v
cmd/geth/snapshot.go
Outdated
log.Info("geth block offline pruning backup successfully") | ||
|
||
//After backing up successfully, rename the new ancientdb name to the original one, and delete the old ancientdb | ||
if err := pruner.BlockPrune(oldAncientPath, newAncientPath); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is quite weried you already pass oldAncientPath
when NewBlockPruner
, but pass it again when doing BlockPruneBackUp
, it is duplicated.
cmd/utils/flags.go
Outdated
err error | ||
chainDb ethdb.Database | ||
) | ||
if ctx.GlobalString(SyncModeFlag.Name) == "light" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if sync mode is light
, there is no need to do block prune
node/node.go
Outdated
// OpenDatabaseWithFreezerForPruneBlock opens an existing database with the given name (or | ||
// creates one if no previous can be found) from within the node's data directory, | ||
// also attaching a chain freezer to it. If the node is an ephemeral one, a memory database is returned. | ||
func (n *Node) OpenDatabaseWithFreezerForPruneBlock(name string, cache, handles int, freezer, namespace string, readonly bool) (ethdb.Database, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please try not to invent new function, too many duplicated code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These new functions were the function without freeze go-routine running, to avoid the case that freeze go-routine did not stop while db closing.
node/node.go
Outdated
// creates one if no previous can be found) from within the node's data directory, | ||
// also attaching a chain freezer to it. If the node is an ephemeral one, a | ||
// memory database is returned. | ||
func (n *Node) OpenDatabaseWithFreezerBackup(offset uint64, name string, cache, handles int, freezer, namespace string, readonly bool) (ethdb.Database, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here
core/state/pruner/pruner.go
Outdated
return errors.New("can't access the freezer or it's empty, abort") | ||
} | ||
// Get the actual start block number. | ||
startBlockNumber := frozen - 128 + oldOffSet |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
128
is a magic number here, please use constant value.
* offline block prune * update * update * update and add unit test * addressed comments from walt * Addressed comments from walt and Igor * ensure MPT and snapshot matched * add one more parameter to indicate blockprune * update the logic of creating freezerDb * update flag command description * expose the function for db inspect the offset/startBlockNumber * add flags to inspect prune info * rename flag of reserved-recent-blocks to block-amount-reserved * addressed comments from walt * handle the case of command interruption * refined goimports * addressed comments from walt * change the logic as restarting prune after interruption * addressed comments * reclaimed freezer logic * introduce flag to enable/disable check between MPT and snapshot * update the logic of frozen field in freezerDB * update the code in all places related to freezer change * addressed comments from dylan * update the logic for backup block difficulty * addressed comments from dylan
* offline block prune * update * update * update and add unit test * addressed comments from walt * Addressed comments from walt and Igor * ensure MPT and snapshot matched * add one more parameter to indicate blockprune * update the logic of creating freezerDb * update flag command description * expose the function for db inspect the offset/startBlockNumber * add flags to inspect prune info * rename flag of reserved-recent-blocks to block-amount-reserved * addressed comments from walt * handle the case of command interruption * refined goimports * addressed comments from walt * change the logic as restarting prune after interruption * addressed comments * reclaimed freezer logic * introduce flag to enable/disable check between MPT and snapshot * update the logic of frozen field in freezerDB * update the code in all places related to freezer change * addressed comments from dylan * update the logic for backup block difficulty * addressed comments from dylan
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
Signed-off-by: jsvisa <delweng@gmail.com>
Signed-off-by: Delweng <delweng@gmail.com>
* core/state: typo Signed-off-by: Delweng <delweng@gmail.com> * core/rawdb: backport from bnb-chain/bsc#543 Signed-off-by: Delweng <delweng@gmail.com> * eth,ethdb,node,core/state: backport from bnb-chain/bsc#543 Signed-off-by: Delweng <delweng@gmail.com> * eth,core: backport from bnb-chain/bsc#543 Signed-off-by: Delweng <delweng@gmail.com> * cmd: open db with freeze disabled Signed-off-by: Delweng <delweng@gmail.com> * cli: snapshot prune-block Signed-off-by: Delweng <delweng@gmail.com> * fix typo Signed-off-by: Delweng <delweng@gmail.com> * cli/snapshot: fix the issue of dup open db error Signed-off-by: Delweng <delweng@gmail.com> * cli/snapshot: resolve datadir and ancient before backup Signed-off-by: Delweng <delweng@gmail.com> * core: more prune-block log Signed-off-by: Delweng <delweng@gmail.com> * core: truncatetail missing f.offset Signed-off-by: Delweng <delweng@gmail.com> * core/rawdb: indextx adjust offset of pruned block Signed-off-by: Delweng <delweng@gmail.com> * core/rawdb: freezer batch should implement the offset commit, ref bnb-chain/bsc#1005 Signed-off-by: Delweng <delweng@gmail.com> * core: check of ancientdb, backport bnb-chain/bsc#817 Signed-off-by: Delweng <delweng@gmail.com> * core/state: read raw borReceipt to backup Signed-off-by: Delweng <delweng@gmail.com> * core/rawdb: bor receipt maybe in []Receipt or Receipt RLP format Signed-off-by: Delweng <delweng@gmail.com> * core/state: typo and error msg Signed-off-by: Delweng <delweng@gmail.com> * core/rawdb: offSet -> offset Signed-off-by: Delweng <delweng@gmail.com> * cli/snapshot: comment Signed-off-by: Delweng <delweng@gmail.com> * cli/snapshot: add prune-block doc Signed-off-by: Delweng <delweng@gmail.com> * docs: add prune-block document Signed-off-by: Delweng <delweng@gmail.com> * core/rawdb: print wrong bor-receipt length Signed-off-by: Delweng <delweng@gmail.com> * internal/cli: add snapshot prune block tests (referenced from bsc's PR) * improve errors * cmd, core, eth, internal: fix lint * internal/cli: refactor snapshot prune block test * fix linters in tests * internal/cli: add inspect-ancient-db command, update docs * pruner: use a generic function for simplification * internal/cli: fixes for inspect-db command * internal/cli: improve pruning tests * core/rawdb: update end block calculation logic in inspect command * core/rawdb: improve checks db initialisation * core/rawdb: remove offset check * update mocks for span, ethdb and add command in makefile * docs/cli: update docs with inspect command * go mod tidy * refactor and resolve conflicts * resolve more conflicts * refactor * explicitly read node for hash scheme * add check for hash scheme, fix tests * fix typo * update docs and add warning * raise error if pbss is enabled * revert read raw bor receipt change * consensus/bor: handle nil header case in get root hash * address comments * core/rawdb: check chain continuity by matching parent hash * core/rawdb: account for pruned ancient blocks * go mod tidy * fix tests * fix tests --------- Signed-off-by: Delweng <delweng@gmail.com> Co-authored-by: Delweng <delweng@gmail.com>
Description
This is for the off-line block prune, in bsc storage, there's db wrapper of ancientDb(freezer) and kvDb(levelDB), the space was mainly occupied by ancientDb, the purpose of this is to prune and remain the specific number of old blocks in ancientDb by specifying the amount of blocks you'd like to remain after pruning in the CLI flag. Then the pruner will prune and only remain this specified amount backward, this first block is not necessarily the genesis block because we may prune many rounds. Actually we can prune and remain any amount of blocks as long as the amount specified did exceed the number of blocks inside ancientDb
###Example:
Assume all blocks in ancientDb are [0,1,... 1000], if pruning amount of 500 blocks, then [0,...499] will be pruned, the data in ancientDb will be [500, 1000]. The next round for pruning will start with BlockNumber 500.
Brief Coding workflow is as follows
Self Test
./geth --config ./config.toml --datadir ./node --cache 12000 --rpc.allow-unprotected-txs --txlookuplimit 0 --syncmode full --usb
, after a while until there's enough old block for pruning in ancientDb../geth snapshot prune-block --datadir ./node --datadir.ancient ./chaindata/ancient --block-amount-reserved 10000
. This will prune and reserve 10000 blocks.Passed and get a new ancientDb with amount of 10000 blocks
inspect-reserved-oldest-blocks
, can be used for checking information of ancientStore like offset and reserved items amount after pruning done../geth db inspect-reserved-oldest-blocks --datadir ./node
+--------------------------------+--------------------------------+--------+
| DATABASE | CATEGORY | ITEMS |
+--------------------------------+--------------------------------+--------+
| Offset/StartBlockNumber | Offset/StartBlockNumber after | 302672 |
| | BlockPrune | |
| Amount of remained items in | remaining items after | 10000 |
| AncientStore | BlockPrune | |
+--------------------------------+--------------------------------+--------+
| ANCIENTSTORE INFORMATION AFTER |
| OFFLINE BLOCKPRUNE |
+--------------------------------+--------------------------------+--------+
Running command
e.g.
./geth snapshot prune-block --datadir ./node --datadir.ancient ./chaindata/ancient --block-amount-reserved 9000 --triesInMemory 32 --check-snapshot-with-mpt
--block-amount-reserved: Amount of blocks want to reserve.
--triesInMemory(optional): The layer of tries trees that keep in memory.
--check-snapshot-with-mpt(optinal): Indicate if enable/disable checking for the match between MPT and snapshot.
Check the info of ancientDB
./geth db inspect-reserved-oldest-blocks --datadir ./node
Result
Preflight checks
make build
)make test
)