| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | // Copyright 2017 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of the go-ethereum library. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU Lesser General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // The go-ethereum library 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 Lesser General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU Lesser General Public License | 
					
						
							|  |  |  | // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | package state | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 	"errors" | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	"fmt" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 	"github.com/VictoriaMetrics/fastcache" | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/rawdb" | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/trie" | 
					
						
							|  |  |  | 	lru "github.com/hashicorp/golang-lru" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const ( | 
					
						
							|  |  |  | 	// Number of codehash->size associations to keep. | 
					
						
							|  |  |  | 	codeSizeCacheSize = 100000 | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Cache size granted for caching clean code. | 
					
						
							|  |  |  | 	codeCacheSize = 64 * 1024 * 1024 | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Database wraps access to tries and contract code. | 
					
						
							|  |  |  | type Database interface { | 
					
						
							|  |  |  | 	// OpenTrie opens the main account trie. | 
					
						
							|  |  |  | 	OpenTrie(root common.Hash) (Trie, error) | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// OpenStorageTrie opens the storage trie of an account. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	OpenStorageTrie(addrHash, root common.Hash) (Trie, error) | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	// CopyTrie returns an independent copy of the given trie. | 
					
						
							|  |  |  | 	CopyTrie(Trie) Trie | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// ContractCode retrieves a particular contract's code. | 
					
						
							|  |  |  | 	ContractCode(addrHash, codeHash common.Hash) ([]byte, error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// ContractCodeSize retrieves a particular contracts code's size. | 
					
						
							|  |  |  | 	ContractCodeSize(addrHash, codeHash common.Hash) (int, error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TrieDB retrieves the low level trie database used for data storage. | 
					
						
							|  |  |  | 	TrieDB() *trie.Database | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | // Trie is a Ethereum Merkle Patricia trie. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | type Trie interface { | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | 	// GetKey returns the sha3 preimage of a hashed key that was previously used | 
					
						
							|  |  |  | 	// to store a value. | 
					
						
							|  |  |  | 	// | 
					
						
							|  |  |  | 	// TODO(fjl): remove this when SecureTrie is removed | 
					
						
							|  |  |  | 	GetKey([]byte) []byte | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// TryGet returns the value for key stored in the trie. The value bytes must | 
					
						
							|  |  |  | 	// not be modified by the caller. If a node was not found in the database, a | 
					
						
							|  |  |  | 	// trie.MissingNodeError is returned. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	TryGet(key []byte) ([]byte, error) | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// TryUpdate associates key with value in the trie. If value has length zero, any | 
					
						
							|  |  |  | 	// existing value is deleted from the trie. The value bytes must not be modified | 
					
						
							|  |  |  | 	// by the caller while they are stored in the trie. If a node was not found in the | 
					
						
							|  |  |  | 	// database, a trie.MissingNodeError is returned. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	TryUpdate(key, value []byte) error | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// TryDelete removes any existing value for key from the trie. If a node was not | 
					
						
							|  |  |  | 	// found in the database, a trie.MissingNodeError is returned. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	TryDelete(key []byte) error | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Hash returns the root hash of the trie. It does not write to the database and | 
					
						
							|  |  |  | 	// can be used even if the trie doesn't have one. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	Hash() common.Hash | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Commit writes all nodes to the trie's memory database, tracking the internal | 
					
						
							|  |  |  | 	// and external (for account tries) references. | 
					
						
							|  |  |  | 	Commit(onleaf trie.LeafCallback) (common.Hash, error) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// NodeIterator returns an iterator that returns nodes of the trie. Iteration | 
					
						
							|  |  |  | 	// starts at the key after the given start key. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	NodeIterator(startKey []byte) trie.NodeIterator | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Prove constructs a Merkle proof for key. The result contains all encoded nodes | 
					
						
							|  |  |  | 	// on the path to the value at key. The value itself is also included in the last | 
					
						
							|  |  |  | 	// node and can be retrieved by verifying the proof. | 
					
						
							|  |  |  | 	// | 
					
						
							|  |  |  | 	// If the trie does not contain a value for key, the returned proof contains all | 
					
						
							|  |  |  | 	// nodes of the longest existing prefix of the key (at least the root), ending | 
					
						
							|  |  |  | 	// with the node that proves the absence of the key. | 
					
						
							| 
									
										
										
											
												all: integrate the freezer with fast sync
* all: freezer style syncing
core, eth, les, light: clean up freezer relative APIs
core, eth, les, trie, ethdb, light: clean a bit
core, eth, les, light: add unit tests
core, light: rewrite setHead function
core, eth: fix downloader unit tests
core: add receipt chain insertion test
core: use constant instead of hardcoding table name
core: fix rollback
core: fix setHead
core/rawdb: remove canonical block first and then iterate side chain
core/rawdb, ethdb: add hasAncient interface
eth/downloader: calculate ancient limit via cht first
core, eth, ethdb: lots of fixes
* eth/downloader: print ancient disable log only for fast sync
											
										 
											2019-04-25 22:59:48 +08:00
										 |  |  | 	Prove(key []byte, fromLevel uint, proofDb ethdb.KeyValueWriter) error | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // NewDatabase creates a backing store for state. The returned database is safe for | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | // concurrent use, but does not retain any recent trie nodes in memory. To keep some | 
					
						
							| 
									
										
										
										
											2020-11-18 17:51:33 +08:00
										 |  |  | // historical state in memory, use the NewDatabaseWithConfig constructor. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | func NewDatabase(db ethdb.Database) Database { | 
					
						
							| 
									
										
										
										
											2020-11-18 17:51:33 +08:00
										 |  |  | 	return NewDatabaseWithConfig(db, nil) | 
					
						
							| 
									
										
										
										
											2018-11-12 18:47:34 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-11-18 17:51:33 +08:00
										 |  |  | // NewDatabaseWithConfig creates a backing store for state. The returned database | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | // is safe for concurrent use and retains a lot of collapsed RLP trie nodes in a | 
					
						
							|  |  |  | // large memory cache. | 
					
						
							| 
									
										
										
										
											2020-11-18 17:51:33 +08:00
										 |  |  | func NewDatabaseWithConfig(db ethdb.Database, config *trie.Config) Database { | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	csc, _ := lru.New(codeSizeCacheSize) | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 	return &cachingDB{ | 
					
						
							| 
									
										
										
										
											2020-11-18 17:51:33 +08:00
										 |  |  | 		db:            trie.NewDatabaseWithConfig(db, config), | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 		codeSizeCache: csc, | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 		codeCache:     fastcache.New(codeCacheSize), | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type cachingDB struct { | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | 	db            *trie.Database | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	codeSizeCache *lru.Cache | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 	codeCache     *fastcache.Cache | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-03-14 15:25:12 +02:00
										 |  |  | // OpenTrie opens the main account trie at a specific root hash. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 	tr, err := trie.NewSecure(root, db.db) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tr, nil | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | // OpenStorageTrie opens the storage trie of an account. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) { | 
					
						
							| 
									
										
										
										
											2020-02-05 13:12:09 +01:00
										 |  |  | 	tr, err := trie.NewSecure(root, db.db) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tr, nil | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | // CopyTrie returns an independent copy of the given trie. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | func (db *cachingDB) CopyTrie(t Trie) Trie { | 
					
						
							|  |  |  | 	switch t := t.(type) { | 
					
						
							|  |  |  | 	case *trie.SecureTrie: | 
					
						
							|  |  |  | 		return t.Copy() | 
					
						
							|  |  |  | 	default: | 
					
						
							|  |  |  | 		panic(fmt.Errorf("unknown trie type %T", t)) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | // ContractCode retrieves a particular contract's code. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) { | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 	if code := db.codeCache.Get(nil, codeHash.Bytes()); len(code) > 0 { | 
					
						
							|  |  |  | 		return code, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	code := rawdb.ReadCode(db.db.DiskDB(), codeHash) | 
					
						
							|  |  |  | 	if len(code) > 0 { | 
					
						
							|  |  |  | 		db.codeCache.Set(codeHash.Bytes(), code) | 
					
						
							|  |  |  | 		db.codeSizeCache.Add(codeHash, len(code)) | 
					
						
							|  |  |  | 		return code, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return nil, errors.New("not found") | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ContractCodeWithPrefix retrieves a particular contract's code. If the | 
					
						
							|  |  |  | // code can't be found in the cache, then check the existence with **new** | 
					
						
							|  |  |  | // db scheme. | 
					
						
							|  |  |  | func (db *cachingDB) ContractCodeWithPrefix(addrHash, codeHash common.Hash) ([]byte, error) { | 
					
						
							|  |  |  | 	if code := db.codeCache.Get(nil, codeHash.Bytes()); len(code) > 0 { | 
					
						
							|  |  |  | 		return code, nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	code := rawdb.ReadCodeWithPrefix(db.db.DiskDB(), codeHash) | 
					
						
							|  |  |  | 	if len(code) > 0 { | 
					
						
							|  |  |  | 		db.codeCache.Set(codeHash.Bytes(), code) | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 		db.codeSizeCache.Add(codeHash, len(code)) | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 		return code, nil | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-08-21 20:10:40 +08:00
										 |  |  | 	return nil, errors.New("not found") | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | // ContractCodeSize retrieves a particular contracts code's size. | 
					
						
							| 
									
										
										
										
											2017-06-27 15:57:06 +02:00
										 |  |  | func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) { | 
					
						
							|  |  |  | 	if cached, ok := db.codeSizeCache.Get(codeHash); ok { | 
					
						
							|  |  |  | 		return cached.(int), nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	code, err := db.ContractCode(addrHash, codeHash) | 
					
						
							|  |  |  | 	return len(code), err | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2018-02-05 18:40:32 +02:00
										 |  |  | // TrieDB retrieves any intermediate trie-node caching layer. | 
					
						
							|  |  |  | func (db *cachingDB) TrieDB() *trie.Database { | 
					
						
							|  |  |  | 	return db.db | 
					
						
							|  |  |  | } |