Skip to content
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

feat(dot/state): Implement online pruning of state tries. #1596

Merged
merged 28 commits into from
Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
18b8798
Implement state trie online pruning.
arijitAD May 17, 2021
4b49d26
Test state trie diff
arijitAD May 19, 2021
2325f98
Implement state trie online pruning
arijitAD May 22, 2021
238222d
Self review.
arijitAD May 27, 2021
7efc326
Merge branch 'development' into state-trie-online-pruning
arijitAD May 27, 2021
52705d5
Minor fix.
arijitAD May 27, 2021
00f54e6
Fix pruning for non canoncial chain.
arijitAD May 31, 2021
2b725f1
Move online pruner to storage state
arijitAD Jun 1, 2021
97ea1a1
Address comments.
arijitAD Jun 1, 2021
724dfe4
Merge branch 'development' into state-trie-online-pruning
arijitAD Jun 1, 2021
224dd60
Remove prune check from offline pruning.
arijitAD Jun 1, 2021
d0f765b
Merge branch 'development' into state-trie-online-pruning
arijitAD Jun 1, 2021
ff357b0
Add test for online pruning.
arijitAD Jun 3, 2021
862d706
Address comments.
arijitAD Jun 3, 2021
3790939
Merge branch 'development' into state-trie-online-pruning
arijitAD Jun 3, 2021
6a3e5af
Merge branch 'development' into state-trie-online-pruning
arijitAD Jun 4, 2021
402a642
Address comments.
arijitAD Jun 4, 2021
c219412
Merge branch 'development' into state-trie-online-pruning
arijitAD Jun 4, 2021
e2844a3
Temp
arijitAD Jun 8, 2021
abbf298
Merge remote-tracking branch 'origin/development' into state-trie-onl…
arijitAD Jun 8, 2021
a7cb2f1
Address comments.
arijitAD Jun 14, 2021
82b11d6
Minor change.
arijitAD Jun 14, 2021
b07af75
Minor fix.
arijitAD Jun 14, 2021
83f33c7
Merge remote-tracking branch 'origin/development' into state-trie-onl…
arijitAD Jun 14, 2021
3a8300b
Merge branch 'development' into state-trie-online-pruning
noot Jun 14, 2021
8faf10c
Fix tests.
arijitAD Jun 14, 2021
30289d2
Fix failing test.
arijitAD Jun 16, 2021
626f3b4
Merge remote-tracking branch 'origin/development' into state-trie-onl…
arijitAD Jun 17, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions cmd/gossamer/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,9 @@ func setDotGlobalConfigFromToml(tomlCfg *ctoml.Config, cfg *dot.GlobalConfig) {
}

cfg.MetricsPort = tomlCfg.Global.MetricsPort

cfg.RetainBlocks = tomlCfg.Global.RetainBlocks
cfg.GCMode = tomlCfg.Global.GCMode
}
}

Expand Down Expand Up @@ -472,6 +475,8 @@ func setDotGlobalConfigFromFlags(ctx *cli.Context, cfg *dot.GlobalConfig) {
cfg.MetricsPort = uint32(metricsPort)
}

cfg.RetainBlocks = ctx.GlobalInt64(RetainBlockNumberFlag.Name)
cfg.GCMode = ctx.GlobalString(GCModeFlag.Name)
cfg.NoTelemetry = ctx.Bool("no-telemetry")
}

Expand Down
12 changes: 7 additions & 5 deletions cmd/gossamer/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,13 @@ func dotConfigToToml(dcfg *dot.Config) *ctoml.Config {
cfg := &ctoml.Config{}

cfg.Global = ctoml.GlobalConfig{
Name: dcfg.Global.Name,
ID: dcfg.Global.ID,
BasePath: dcfg.Global.BasePath,
LogLvl: dcfg.Global.LogLvl.String(),
MetricsPort: dcfg.Global.MetricsPort,
Name: dcfg.Global.Name,
ID: dcfg.Global.ID,
BasePath: dcfg.Global.BasePath,
LogLvl: dcfg.Global.LogLvl.String(),
MetricsPort: dcfg.Global.MetricsPort,
RetainBlocks: dcfg.Global.RetainBlocks,
GCMode: dcfg.Global.GCMode,
}

cfg.Log = ctoml.LogConfig{
Expand Down
8 changes: 8 additions & 0 deletions cmd/gossamer/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,13 @@ var (
Usage: "Retain number of block from latest block while pruning",
Value: 256,
}

// GCModeFlag sets the blockchain GC mode. It's either full or archive.
GCModeFlag = cli.StringFlag{
Name: "gcmode",
noot marked this conversation as resolved.
Show resolved Hide resolved
Usage: `Blockchain garbage collection mode ("full", "archive")`,
Value: "full",
noot marked this conversation as resolved.
Show resolved Hide resolved
}
)

// flag sets that are shared by multiple commands
Expand All @@ -302,6 +309,7 @@ var (
DBPathFlag,
BloomFilterSizeFlag,
RetainBlockNumberFlag,
GCModeFlag,
}

// StartupFlags are flags that are valid for use with the root command and the export subcommand
Expand Down
10 changes: 9 additions & 1 deletion cmd/gossamer/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,14 @@ func gossamerAction(ctx *cli.Context) error {
return err
}

if cfg.Global.RetainBlocks < 256 {
noot marked this conversation as resolved.
Show resolved Hide resolved
return fmt.Errorf("--%s cannot be less than 256", RetainBlockNumberFlag.Name)
}

if cfg.Global.GCMode != "full" && cfg.Global.GCMode != "archive" {
return fmt.Errorf("--%s must be either 'full' or 'archive'", GCModeFlag.Name)
}

cfg.Global.LogLvl = lvl

// expand data directory and update node configuration (performed separately
Expand Down Expand Up @@ -448,7 +456,7 @@ func pruneState(ctx *cli.Context) error {
return err
}

logger.Info("Pruner initialised")
logger.Info("Offline pruner initialised")

err = pruner.SetBloomFilter()
if err != nil {
Expand Down
2 changes: 2 additions & 0 deletions dot/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ type GlobalConfig struct {
PublishMetrics bool
MetricsPort uint32
NoTelemetry bool
RetainBlocks int64
GCMode string
}

// LogConfig represents the log levels for individual packages
Expand Down
12 changes: 7 additions & 5 deletions dot/config/toml/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,13 @@ type Config struct {

// GlobalConfig is to marshal/unmarshal toml global config vars
type GlobalConfig struct {
Name string `toml:"name,omitempty"`
ID string `toml:"id,omitempty"`
BasePath string `toml:"basepath,omitempty"`
LogLvl string `toml:"log,omitempty"`
MetricsPort uint32 `toml:"metrics-port,omitempty"`
Name string `toml:"name,omitempty"`
ID string `toml:"id,omitempty"`
BasePath string `toml:"basepath,omitempty"`
LogLvl string `toml:"log,omitempty"`
MetricsPort uint32 `toml:"metrics-port,omitempty"`
RetainBlocks int64 `toml:"retain-blocks,omitempty"`
GCMode string `toml:"gc-mode,omitempty"`
}

// LogConfig represents the log levels for individual packages
Expand Down
14 changes: 12 additions & 2 deletions dot/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,16 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore, stopFunc func()) (*Node,
// Network Service
var networkSrvc *network.Service

var pruner state.Pruner
if cfg.Global.GCMode == "full" {
pruner, err = state.CreatePruner(stateSrvc.DB(), cfg.Global.RetainBlocks)
if err != nil {
return nil, err
}
} else {
pruner = &state.ArchivalNodePruner{}
}

// check if network service is enabled
if enabled := networkServiceEnabled(cfg); enabled {
// create network service and append network service to node services
Expand All @@ -262,7 +272,7 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore, stopFunc func()) (*Node,
}

// create BABE service
bp, err := createBABEService(cfg, rt, stateSrvc, ks.Babe)
bp, err := createBABEService(cfg, rt, stateSrvc, ks.Babe, pruner)
if err != nil {
return nil, err
}
Expand All @@ -283,7 +293,7 @@ func NewNode(cfg *Config, ks *keystore.GlobalKeystore, stopFunc func()) (*Node,
nodeSrvcs = append(nodeSrvcs, fg)

// Syncer
syncer, err := createSyncService(cfg, stateSrvc, bp, fg, dh, ver, rt)
syncer, err := createSyncService(cfg, stateSrvc, bp, fg, dh, ver, rt, pruner)
if err != nil {
return nil, err
}
Expand Down
6 changes: 4 additions & 2 deletions dot/services.go
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ func createRuntime(cfg *Config, st *state.Service, ks *keystore.GlobalKeystore,
return rt, nil
}

func createBABEService(cfg *Config, rt runtime.Instance, st *state.Service, ks keystore.Keystore) (*babe.Service, error) {
func createBABEService(cfg *Config, rt runtime.Instance, st *state.Service, ks keystore.Keystore, pruner state.Pruner) (*babe.Service, error) {
logger.Info(
"creating BABE service...",
"authority", cfg.Core.BabeAuthority,
Expand All @@ -192,6 +192,7 @@ func createBABEService(cfg *Config, rt runtime.Instance, st *state.Service, ks k
SlotDuration: cfg.Core.SlotDuration, // TODO: remove this, should only be modified via runtime constant
Authority: cfg.Core.BabeAuthority,
IsDev: cfg.Global.ID == "dev",
Pruner: pruner,
}

if cfg.Core.BabeAuthority {
Expand Down Expand Up @@ -376,7 +377,7 @@ func createBlockVerifier(st *state.Service) (*babe.VerificationManager, error) {
return ver, nil
}

func createSyncService(cfg *Config, st *state.Service, bp sync.BlockProducer, fg sync.FinalityGadget, dh *core.DigestHandler, verifier *babe.VerificationManager, rt runtime.Instance) (*sync.Service, error) {
func createSyncService(cfg *Config, st *state.Service, bp sync.BlockProducer, fg sync.FinalityGadget, dh *core.DigestHandler, verifier *babe.VerificationManager, rt runtime.Instance, pruner state.Pruner) (*sync.Service, error) {
syncCfg := &sync.Config{
LogLvl: cfg.Log.SyncLvl,
BlockState: st.Block,
Expand All @@ -387,6 +388,7 @@ func createSyncService(cfg *Config, st *state.Service, bp sync.BlockProducer, fg
Verifier: verifier,
Runtime: rt,
DigestHandler: dh,
Pruner: pruner,
}

return sync.NewService(syncCfg)
Expand Down
5 changes: 3 additions & 2 deletions dot/services_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"time"

"github.com/ChainSafe/gossamer/dot/network"
"github.com/ChainSafe/gossamer/dot/state"
"github.com/ChainSafe/gossamer/dot/types"
"github.com/ChainSafe/gossamer/lib/keystore"
"github.com/ChainSafe/gossamer/lib/utils"
Expand Down Expand Up @@ -136,7 +137,7 @@ func TestCreateSyncService(t *testing.T) {
ver, err := createBlockVerifier(stateSrvc)
require.NoError(t, err)

_, err = createSyncService(cfg, stateSrvc, nil, nil, nil, ver, rt)
_, err = createSyncService(cfg, stateSrvc, nil, nil, nil, ver, rt, &state.ArchivalNodePruner{})
require.NoError(t, err)
}

Expand Down Expand Up @@ -233,7 +234,7 @@ func TestCreateBABEService(t *testing.T) {
rt, err := createRuntime(cfg, stateSrvc, ks, &network.Service{})
require.NoError(t, err)

bs, err := createBABEService(cfg, rt, stateSrvc, ks.Babe)
bs, err := createBABEService(cfg, rt, stateSrvc, ks.Babe, &state.ArchivalNodePruner{})
require.NoError(t, err)
require.NotNil(t, bs)
}
Expand Down
16 changes: 8 additions & 8 deletions dot/state/prune.go → dot/state/offline_pruner.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ import (
"github.com/dgraph-io/badger/v2/pb"
)

// Pruner is an offline tool to prune the stale state with the help of
// bloom filter, The workflow of pruner is very simple:
// OfflinePruner is a tool to prune the stale state with the help of
// bloom filter, The workflow of Pruner is very simple:
// - iterate the storage state, reconstruct the relevant state tries
// - iterate the database, stream all the targeted keys to new DB
type Pruner struct {
type OfflinePruner struct {
inputDB *chaindb.BadgerDB
storageState *StorageState
blockState *BlockState
Expand All @@ -30,8 +30,8 @@ type Pruner struct {
prunedDBPath string
}

// NewPruner creates an instance of Pruner.
func NewPruner(inputDBPath, prunedDBPath string, bloomSize uint64, retainBlockNum int64) (*Pruner, error) {
// NewPruner creates an instance of OfflinePruner.
func NewPruner(inputDBPath, prunedDBPath string, bloomSize uint64, retainBlockNum int64) (*OfflinePruner, error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func NewPruner(inputDBPath, prunedDBPath string, bloomSize uint64, retainBlockNum int64) (*OfflinePruner, error) {
func NewOfflinePruner(inputDBPath, prunedDBPath string, bloomSize uint64, retainBlockNum int64) (*OfflinePruner, error) {

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

db, err := utils.LoadChainDB(inputDBPath)
if err != nil {
return nil, fmt.Errorf("failed to load DB %w", err)
Expand Down Expand Up @@ -67,7 +67,7 @@ func NewPruner(inputDBPath, prunedDBPath string, bloomSize uint64, retainBlockNu
return nil, fmt.Errorf("failed to create new storage state %w", err)
}

return &Pruner{
return &OfflinePruner{
inputDB: db,
storageState: storageState,
blockState: blockState,
Expand All @@ -80,7 +80,7 @@ func NewPruner(inputDBPath, prunedDBPath string, bloomSize uint64, retainBlockNu
}

// SetBloomFilter loads keys with storage prefix of last `retainBlockNum` blocks into the bloom filter
func (p *Pruner) SetBloomFilter() error {
func (p *OfflinePruner) SetBloomFilter() error {
defer p.inputDB.Close() // nolint: errcheck
finalisedHash, err := p.blockState.GetFinalizedHash(0, 0)
if err != nil {
Expand Down Expand Up @@ -134,7 +134,7 @@ func (p *Pruner) SetBloomFilter() error {
}

// Prune starts streaming the data from input db to the pruned db.
func (p *Pruner) Prune() error {
func (p *OfflinePruner) Prune() error {
inputDB, err := utils.LoadBadgerDB(p.inputDBPath)
if err != nil {
return fmt.Errorf("failed to load DB %w", err)
Expand Down
Loading