Skip to content

Commit 359906c

Browse files
RealUnclekeefel
RealUncle
authored andcommitted
implement the framework of fast node
1 parent 21a3b11 commit 359906c

18 files changed

+454
-61
lines changed

cmd/geth/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ var (
115115
utils.WhitelistFlag,
116116
utils.BloomFilterSizeFlag,
117117
utils.TriesInMemoryFlag,
118+
utils.AllowInsecureNoTriesFlag,
118119
utils.CacheFlag,
119120
utils.CacheDatabaseFlag,
120121
utils.CacheTrieFlag,

cmd/geth/snapshot.go

+74-2
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package main
1818

1919
import (
2020
"bytes"
21+
"encoding/json"
2122
"errors"
2223
"fmt"
2324
"os"
@@ -29,13 +30,16 @@ import (
2930

3031
"github.com/ethereum/go-ethereum/cmd/utils"
3132
"github.com/ethereum/go-ethereum/common"
33+
"github.com/ethereum/go-ethereum/core"
3234
"github.com/ethereum/go-ethereum/core/rawdb"
3335
"github.com/ethereum/go-ethereum/core/state"
3436
"github.com/ethereum/go-ethereum/core/state/pruner"
3537
"github.com/ethereum/go-ethereum/core/state/snapshot"
3638
"github.com/ethereum/go-ethereum/crypto"
39+
"github.com/ethereum/go-ethereum/eth/ethconfig"
3740
"github.com/ethereum/go-ethereum/ethdb"
3841
"github.com/ethereum/go-ethereum/log"
42+
"github.com/ethereum/go-ethereum/metrics"
3943
"github.com/ethereum/go-ethereum/node"
4044
"github.com/ethereum/go-ethereum/rlp"
4145
"github.com/ethereum/go-ethereum/trie"
@@ -129,6 +133,32 @@ geth snapshot verify-state <state-root>
129133
will traverse the whole accounts and storages set based on the specified
130134
snapshot and recalculate the root hash of state for verification.
131135
In other words, this command does the snapshot to trie conversion.
136+
`,
137+
},
138+
{
139+
Name: "insecure-prune-all",
140+
Usage: "Prune all trie state data except genesis block, it will break storage for fullnode, only suitable for fast node " +
141+
"who do not need trie storage at all",
142+
ArgsUsage: "<genesisPath>",
143+
Action: utils.MigrateFlags(pruneAllState),
144+
Category: "MISCELLANEOUS COMMANDS",
145+
Flags: []cli.Flag{
146+
utils.DataDirFlag,
147+
utils.AncientFlag,
148+
utils.RopstenFlag,
149+
utils.RinkebyFlag,
150+
utils.GoerliFlag,
151+
},
152+
Description: `
153+
will prune all historical trie state data except genesis block.
154+
All trie nodes will be deleted from the database.
155+
156+
It expects the genesis file as argument.
157+
158+
WARNING: It's necessary to delete the trie clean cache after the pruning.
159+
If you specify another directory for the trie clean cache via "--cache.trie.journal"
160+
during the use of Geth, please also specify it here for correct deletion. Otherwise
161+
the trie clean cache with default directory will be deleted.
132162
`,
133163
},
134164
{
@@ -195,7 +225,7 @@ func accessDb(ctx *cli.Context, stack *node.Node) (ethdb.Database, error) {
195225
}
196226
headHeader := headBlock.Header()
197227
//Make sure the MPT and snapshot matches before pruning, otherwise the node can not start.
198-
snaptree, err := snapshot.New(chaindb, trie.NewDatabase(chaindb), 256, TriesInMemory, headBlock.Root(), false, false, false)
228+
snaptree, err := snapshot.New(chaindb, trie.NewDatabase(chaindb), 256, TriesInMemory, headBlock.Root(), false, false, false, false)
199229
if err != nil {
200230
log.Error("snaptree error", "err", err)
201231
return nil, err // The relevant snapshot(s) might not exist
@@ -362,6 +392,48 @@ func pruneState(ctx *cli.Context) error {
362392
return nil
363393
}
364394

395+
func pruneAllState(ctx *cli.Context) error {
396+
stack, _ := makeConfigNode(ctx)
397+
defer stack.Close()
398+
399+
genesisPath := ctx.Args().First()
400+
if len(genesisPath) == 0 {
401+
utils.Fatalf("Must supply path to genesis JSON file")
402+
}
403+
file, err := os.Open(genesisPath)
404+
if err != nil {
405+
utils.Fatalf("Failed to read genesis file: %v", err)
406+
}
407+
defer file.Close()
408+
409+
g := new(core.Genesis)
410+
if err := json.NewDecoder(file).Decode(g); err != nil {
411+
cfg := gethConfig{
412+
Eth: ethconfig.Defaults,
413+
Node: defaultNodeConfig(),
414+
Metrics: metrics.DefaultConfig,
415+
}
416+
417+
// Load config file.
418+
if err := loadConfig(genesisPath, &cfg); err != nil {
419+
utils.Fatalf("%v", err)
420+
}
421+
g = cfg.Eth.Genesis
422+
}
423+
424+
chaindb := utils.MakeChainDatabase(ctx, stack, false, false)
425+
pruner, err := pruner.NewAllPruner(chaindb)
426+
if err != nil {
427+
log.Error("Failed to open snapshot tree", "err", err)
428+
return err
429+
}
430+
if err = pruner.PruneAll(g); err != nil {
431+
log.Error("Failed to prune state", "err", err)
432+
return err
433+
}
434+
return nil
435+
}
436+
365437
func verifyState(ctx *cli.Context) error {
366438
stack, _ := makeConfigNode(ctx)
367439
defer stack.Close()
@@ -372,7 +444,7 @@ func verifyState(ctx *cli.Context) error {
372444
log.Error("Failed to load head block")
373445
return errors.New("no head block")
374446
}
375-
snaptree, err := snapshot.New(chaindb, trie.NewDatabase(chaindb), 256, 128, headBlock.Root(), false, false, false)
447+
snaptree, err := snapshot.New(chaindb, trie.NewDatabase(chaindb), 256, 128, headBlock.Root(), false, false, false, false)
376448
if err != nil {
377449
log.Error("Failed to open snapshot tree", "err", err)
378450
return err

cmd/utils/flags.go

+7
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,10 @@ var (
264264
Usage: "The layer of tries trees that keep in memory",
265265
Value: 128,
266266
}
267+
AllowInsecureNoTriesFlag = cli.BoolTFlag{
268+
Name: "allow-insecure-no-tries",
269+
Usage: `Disable the tries state root verification, the state consistency is no longer 100% guaranteed, diffsync is not allowed if enabled. Do not enable it unless you know exactly what the consequence it will cause.`,
270+
}
267271
OverrideBerlinFlag = cli.Uint64Flag{
268272
Name: "override.berlin",
269273
Usage: "Manually specify Berlin fork-block, overriding the bundled setting",
@@ -1666,6 +1670,9 @@ func SetEthConfig(ctx *cli.Context, stack *node.Node, cfg *ethconfig.Config) {
16661670
if ctx.GlobalIsSet(TriesInMemoryFlag.Name) {
16671671
cfg.TriesInMemory = ctx.GlobalUint64(TriesInMemoryFlag.Name)
16681672
}
1673+
if ctx.GlobalIsSet(AllowInsecureNoTriesFlag.Name) {
1674+
cfg.NoTries = ctx.GlobalBool(AllowInsecureNoTriesFlag.Name)
1675+
}
16691676
if ctx.GlobalIsSet(CacheFlag.Name) || ctx.GlobalIsSet(CacheSnapshotFlag.Name) {
16701677
cfg.SnapshotCache = ctx.GlobalInt(CacheFlag.Name) * ctx.GlobalInt(CacheSnapshotFlag.Name) / 100
16711678
}

core/block_validator.go

-6
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,6 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
7070
}
7171

7272
validateFuns := []func() error{
73-
func() error {
74-
if v.bc.HasBlockAndState(block.Hash(), block.NumberU64()) {
75-
return ErrKnownBlock
76-
}
77-
return nil
78-
},
7973
func() error {
8074
if hash := types.DeriveSha(block.Transactions(), trie.NewStackTrie(nil)); hash != header.TxHash {
8175
return fmt.Errorf("transaction root hash mismatch: have %x, want %x", hash, header.TxHash)

core/blockchain.go

+12-1
Original file line numberDiff line numberDiff line change
@@ -141,6 +141,7 @@ type CacheConfig struct {
141141
SnapshotLimit int // Memory allowance (MB) to use for caching snapshot entries in memory
142142
Preimages bool // Whether to store preimage of trie key to the disk
143143
TriesInMemory uint64 // How many tries keeps in memory
144+
NoTries bool // Insecure settings. Do not have any tries in databases if enabled.
144145

145146
SnapshotWait bool // Wait for snapshot construction on startup. TODO(karalabe): This is a dirty hack for testing, nuke it
146147
}
@@ -284,6 +285,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
284285
Cache: cacheConfig.TrieCleanLimit,
285286
Journal: cacheConfig.TrieCleanJournal,
286287
Preimages: cacheConfig.Preimages,
288+
NoTries: cacheConfig.NoTries,
287289
}),
288290
triesInMemory: cacheConfig.TriesInMemory,
289291
quit: make(chan struct{}),
@@ -439,7 +441,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, chainConfig *par
439441
log.Warn("Enabling snapshot recovery", "chainhead", head.NumberU64(), "diskbase", *layer)
440442
recover = true
441443
}
442-
bc.snaps, _ = snapshot.New(bc.db, bc.stateCache.TrieDB(), bc.cacheConfig.SnapshotLimit, int(bc.cacheConfig.TriesInMemory), head.Root(), !bc.cacheConfig.SnapshotWait, true, recover)
444+
bc.snaps, _ = snapshot.New(bc.db, bc.stateCache.TrieDB(), bc.cacheConfig.SnapshotLimit, int(bc.cacheConfig.TriesInMemory), head.Root(), !bc.cacheConfig.SnapshotWait, true, recover, bc.stateCache.NoTries())
443445
}
444446
// do options before start any routine
445447
for _, option := range options {
@@ -1097,6 +1099,9 @@ func (bc *BlockChain) HasState(hash common.Hash) bool {
10971099
return true
10981100
}
10991101
}
1102+
if bc.stateCache.NoTries() {
1103+
return bc.snaps != nil && bc.snaps.Snapshot(hash) != nil
1104+
}
11001105
_, err := bc.stateCache.OpenTrie(hash)
11011106
return err == nil
11021107
}
@@ -1109,6 +1114,9 @@ func (bc *BlockChain) HasBlockAndState(hash common.Hash, number uint64) bool {
11091114
if block == nil {
11101115
return false
11111116
}
1117+
if bc.stateCache.NoTries() {
1118+
return bc.snaps != nil && bc.snaps.Snapshot(block.Root()) != nil
1119+
}
11121120
return bc.HasState(block.Root())
11131121
}
11141122

@@ -2105,6 +2113,9 @@ func (bc *BlockChain) insertChain(chain types.Blocks, verifySeals bool) (int, er
21052113
if err != nil {
21062114
return it.index, err
21072115
}
2116+
if statedb.NoTrie() {
2117+
statedb.SetCurrentRoot(block.Root())
2118+
}
21082119
bc.updateHighestVerifiedHeader(block.Header())
21092120

21102121
// Enable prefetching to pull in trie node paths while processing transactions

core/state/database.go

+23-1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@ type Database interface {
7474

7575
// Purge cache
7676
Purge()
77+
78+
// NoTries returns whether the database has tries storage.
79+
NoTries() bool
7780
}
7881

7982
// Trie is a Ethereum Merkle Patricia trie.
@@ -134,10 +137,12 @@ func NewDatabase(db ethdb.Database) Database {
134137
func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database {
135138
csc, _ := lru.New(codeSizeCacheSize)
136139
cc, _ := lru.New(codeCacheSize)
140+
noTries := config != nil && config.NoTries
137141
return &cachingDB{
138142
db: trie.NewDatabaseWithConfig(db, config),
139143
codeSizeCache: csc,
140144
codeCache: cc,
145+
noTries: noTries,
141146
}
142147
}
143148

@@ -146,15 +151,19 @@ func NewDatabaseWithConfigAndCache(db ethdb.Database, config *trie.Config) Datab
146151
cc, _ := lru.New(codeCacheSize)
147152
atc, _ := lru.New(accountTrieCacheSize)
148153
stc, _ := lru.New(storageTrieCacheSize)
154+
noTries := config != nil && config.NoTries
149155

150156
database := &cachingDB{
151157
db: trie.NewDatabaseWithConfig(db, config),
152158
codeSizeCache: csc,
153159
codeCache: cc,
154160
accountTrieCache: atc,
155161
storageTrieCache: stc,
162+
noTries: noTries,
163+
}
164+
if !noTries {
165+
go database.purgeLoop()
156166
}
157-
go database.purgeLoop()
158167
return database
159168
}
160169

@@ -164,6 +173,7 @@ type cachingDB struct {
164173
codeCache *lru.Cache
165174
accountTrieCache *lru.Cache
166175
storageTrieCache *lru.Cache
176+
noTries bool
167177
}
168178

169179
type triePair struct {
@@ -187,6 +197,9 @@ func (db *cachingDB) purgeLoop() {
187197

188198
// OpenTrie opens the main account trie at a specific root hash.
189199
func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
200+
if db.noTries {
201+
return trie.NewEmptyTrie(), nil
202+
}
190203
if db.accountTrieCache != nil {
191204
if tr, exist := db.accountTrieCache.Get(root); exist {
192205
return tr.(Trie).(*trie.SecureTrie).Copy(), nil
@@ -201,6 +214,9 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
201214

202215
// OpenStorageTrie opens the storage trie of an account.
203216
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
217+
if db.noTries {
218+
return trie.NewEmptyTrie(), nil
219+
}
204220
if db.storageTrieCache != nil {
205221
if tries, exist := db.storageTrieCache.Get(addrHash); exist {
206222
triesPairs := tries.([3]*triePair)
@@ -246,6 +262,10 @@ func (db *cachingDB) CacheStorage(addrHash common.Hash, root common.Hash, t Trie
246262
}
247263
}
248264

265+
func (db *cachingDB) NoTries() bool {
266+
return db.noTries
267+
}
268+
249269
func (db *cachingDB) Purge() {
250270
if db.storageTrieCache != nil {
251271
db.storageTrieCache.Purge()
@@ -263,6 +283,8 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
263283
switch t := t.(type) {
264284
case *trie.SecureTrie:
265285
return t.Copy()
286+
case *trie.EmptyTrie:
287+
return t.Copy()
266288
default:
267289
panic(fmt.Errorf("unknown trie type %T", t))
268290
}

0 commit comments

Comments
 (0)