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