github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/core/state/database.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:35</date>
    10  //</624450079750623232>
    11  
    12  
    13  package state
    14  
    15  import (
    16  	"fmt"
    17  	"sync"
    18  
    19  	"github.com/ethereum/go-ethereum/common"
    20  	"github.com/ethereum/go-ethereum/ethdb"
    21  	"github.com/ethereum/go-ethereum/trie"
    22  	lru "github.com/hashicorp/golang-lru"
    23  )
    24  
    25  //Trie cache generation limit after which to evict trie nodes from memory.
    26  var MaxTrieCacheGen = uint16(120)
    27  
    28  const (
    29  //要保留的过去尝试次数。此值的选择方式如下:
    30  //合理的链条重铺深度将达到现有的三重。
    31  	maxPastTries = 12
    32  
    33  //要保留的codehash->大小关联数。
    34  	codeSizeCacheSize = 100000
    35  )
    36  
    37  //数据库将访问权限包装为“尝试”和“合同代码”。
    38  type Database interface {
    39  //opentrie打开主帐户trie。
    40  	OpenTrie(root common.Hash) (Trie, error)
    41  
    42  //openstoragetrie打开帐户的存储trie。
    43  	OpenStorageTrie(addrHash, root common.Hash) (Trie, error)
    44  
    45  //copy trie返回给定trie的独立副本。
    46  	CopyTrie(Trie) Trie
    47  
    48  //ContractCode检索特定合同的代码。
    49  	ContractCode(addrHash, codeHash common.Hash) ([]byte, error)
    50  
    51  //ContractCodeSize检索特定合同代码的大小。
    52  	ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
    53  
    54  //triedb检索用于数据存储的低级trie数据库。
    55  	TrieDB() *trie.Database
    56  }
    57  
    58  //特里亚是以太梅克尔特里亚。
    59  type Trie interface {
    60  	TryGet(key []byte) ([]byte, error)
    61  	TryUpdate(key, value []byte) error
    62  	TryDelete(key []byte) error
    63  	Commit(onleaf trie.LeafCallback) (common.Hash, error)
    64  	Hash() common.Hash
    65  	NodeIterator(startKey []byte) trie.NodeIterator
    66  GetKey([]byte) []byte //TODO(FJL):移除SecureTrie时移除此项
    67  	Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error
    68  }
    69  
    70  //NeXDATA为状态创建后备存储。返回的数据库是安全的
    71  //并发使用并在内存中保留一些最近扩展的trie节点。保持
    72  //内存中的更多历史状态,请使用newdatabasewithcache构造函数。
    73  func NewDatabase(db ethdb.Database) Database {
    74  	return NewDatabaseWithCache(db, 0)
    75  }
    76  
    77  //NeXDATA为状态创建后备存储。返回的数据库是安全的
    78  //在内存中同时使用并保留最近扩展的两个trie节点,如
    79  //以及一个大内存缓存中的许多折叠的rlp trie节点。
    80  func NewDatabaseWithCache(db ethdb.Database, cache int) Database {
    81  	csc, _ := lru.New(codeSizeCacheSize)
    82  	return &cachingDB{
    83  		db:            trie.NewDatabaseWithCache(db, cache),
    84  		codeSizeCache: csc,
    85  	}
    86  }
    87  
    88  type cachingDB struct {
    89  	db            *trie.Database
    90  	mu            sync.Mutex
    91  	pastTries     []*trie.SecureTrie
    92  	codeSizeCache *lru.Cache
    93  }
    94  
    95  //opentrie打开主帐户trie。
    96  func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
    97  	db.mu.Lock()
    98  	defer db.mu.Unlock()
    99  
   100  	for i := len(db.pastTries) - 1; i >= 0; i-- {
   101  		if db.pastTries[i].Hash() == root {
   102  			return cachedTrie{db.pastTries[i].Copy(), db}, nil
   103  		}
   104  	}
   105  	tr, err := trie.NewSecure(root, db.db, MaxTrieCacheGen)
   106  	if err != nil {
   107  		return nil, err
   108  	}
   109  	return cachedTrie{tr, db}, nil
   110  }
   111  
   112  func (db *cachingDB) pushTrie(t *trie.SecureTrie) {
   113  	db.mu.Lock()
   114  	defer db.mu.Unlock()
   115  
   116  	if len(db.pastTries) >= maxPastTries {
   117  		copy(db.pastTries, db.pastTries[1:])
   118  		db.pastTries[len(db.pastTries)-1] = t
   119  	} else {
   120  		db.pastTries = append(db.pastTries, t)
   121  	}
   122  }
   123  
   124  //openstoragetrie打开帐户的存储trie。
   125  func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
   126  	return trie.NewSecure(root, db.db, 0)
   127  }
   128  
   129  //copy trie返回给定trie的独立副本。
   130  func (db *cachingDB) CopyTrie(t Trie) Trie {
   131  	switch t := t.(type) {
   132  	case cachedTrie:
   133  		return cachedTrie{t.SecureTrie.Copy(), db}
   134  	case *trie.SecureTrie:
   135  		return t.Copy()
   136  	default:
   137  		panic(fmt.Errorf("unknown trie type %T", t))
   138  	}
   139  }
   140  
   141  //ContractCode检索特定合同的代码。
   142  func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) {
   143  	code, err := db.db.Node(codeHash)
   144  	if err == nil {
   145  		db.codeSizeCache.Add(codeHash, len(code))
   146  	}
   147  	return code, err
   148  }
   149  
   150  //ContractCodeSize检索特定合同代码的大小。
   151  func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) {
   152  	if cached, ok := db.codeSizeCache.Get(codeHash); ok {
   153  		return cached.(int), nil
   154  	}
   155  	code, err := db.ContractCode(addrHash, codeHash)
   156  	return len(code), err
   157  }
   158  
   159  //triedb检索任何中间trie节点缓存层。
   160  func (db *cachingDB) TrieDB() *trie.Database {
   161  	return db.db
   162  }
   163  
   164  //cachedtrie在提交时将其trie插入cachingdb。
   165  type cachedTrie struct {
   166  	*trie.SecureTrie
   167  	db *cachingDB
   168  }
   169  
   170  func (m cachedTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) {
   171  	root, err := m.SecureTrie.Commit(onleaf)
   172  	if err == nil {
   173  		m.db.pushTrie(m.SecureTrie)
   174  	}
   175  	return root, err
   176  }
   177  
   178  func (m cachedTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error {
   179  	return m.SecureTrie.Prove(key, fromLevel, proofDb)
   180  }
   181