github.com/linapex/ethereum-dpos-chinese@v0.0.0-20190316121959-b78b3a4a1ece/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 12:09:34</date> 10 //</624342617307484160> 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缓存生成限制,在此之后将trie节点从内存中逐出。 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 //在低级存储层和 73 //高级Trie抽象。 74 func NewDatabase(db ethdb.Database) Database { 75 csc, _ := lru.New(codeSizeCacheSize) 76 return &cachingDB{ 77 db: trie.NewDatabase(db), 78 codeSizeCache: csc, 79 } 80 } 81 82 type cachingDB struct { 83 db *trie.Database 84 mu sync.Mutex 85 pastTries []*trie.SecureTrie 86 codeSizeCache *lru.Cache 87 } 88 89 //opentrie打开主帐户trie。 90 func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) { 91 db.mu.Lock() 92 defer db.mu.Unlock() 93 94 for i := len(db.pastTries) - 1; i >= 0; i-- { 95 if db.pastTries[i].Hash() == root { 96 return cachedTrie{db.pastTries[i].Copy(), db}, nil 97 } 98 } 99 tr, err := trie.NewSecure(root, db.db, MaxTrieCacheGen) 100 if err != nil { 101 return nil, err 102 } 103 return cachedTrie{tr, db}, nil 104 } 105 106 func (db *cachingDB) pushTrie(t *trie.SecureTrie) { 107 db.mu.Lock() 108 defer db.mu.Unlock() 109 110 if len(db.pastTries) >= maxPastTries { 111 copy(db.pastTries, db.pastTries[1:]) 112 db.pastTries[len(db.pastTries)-1] = t 113 } else { 114 db.pastTries = append(db.pastTries, t) 115 } 116 } 117 118 //openstoragetrie打开帐户的存储trie。 119 func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) { 120 return trie.NewSecure(root, db.db, 0) 121 } 122 123 //copy trie返回给定trie的独立副本。 124 func (db *cachingDB) CopyTrie(t Trie) Trie { 125 switch t := t.(type) { 126 case cachedTrie: 127 return cachedTrie{t.SecureTrie.Copy(), db} 128 case *trie.SecureTrie: 129 return t.Copy() 130 default: 131 panic(fmt.Errorf("unknown trie type %T", t)) 132 } 133 } 134 135 //ContractCode检索特定合同的代码。 136 func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) { 137 code, err := db.db.Node(codeHash) 138 if err == nil { 139 db.codeSizeCache.Add(codeHash, len(code)) 140 } 141 return code, err 142 } 143 144 //ContractCodeSize检索特定合同代码的大小。 145 func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) { 146 if cached, ok := db.codeSizeCache.Get(codeHash); ok { 147 return cached.(int), nil 148 } 149 code, err := db.ContractCode(addrHash, codeHash) 150 return len(code), err 151 } 152 153 //triedb检索任何中间trie节点缓存层。 154 func (db *cachingDB) TrieDB() *trie.Database { 155 return db.db 156 } 157 158 //cachedtrie在提交时将其trie插入cachingdb。 159 type cachedTrie struct { 160 *trie.SecureTrie 161 db *cachingDB 162 } 163 164 func (m cachedTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) { 165 root, err := m.SecureTrie.Commit(onleaf) 166 if err == nil { 167 m.db.pushTrie(m.SecureTrie) 168 } 169 return root, err 170 } 171 172 func (m cachedTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { 173 return m.SecureTrie.Prove(key, fromLevel, proofDb) 174 } 175