github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/light/trie.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:39</date> 10 //</624450096733360128> 11 12 13 package light 14 15 import ( 16 "context" 17 "errors" 18 "fmt" 19 20 "github.com/ethereum/go-ethereum/common" 21 "github.com/ethereum/go-ethereum/core/state" 22 "github.com/ethereum/go-ethereum/core/types" 23 "github.com/ethereum/go-ethereum/crypto" 24 "github.com/ethereum/go-ethereum/ethdb" 25 "github.com/ethereum/go-ethereum/trie" 26 ) 27 28 func NewState(ctx context.Context, head *types.Header, odr OdrBackend) *state.StateDB { 29 state, _ := state.New(head.Root, NewStateDatabase(ctx, head, odr)) 30 return state 31 } 32 33 func NewStateDatabase(ctx context.Context, head *types.Header, odr OdrBackend) state.Database { 34 return &odrDatabase{ctx, StateTrieID(head), odr} 35 } 36 37 type odrDatabase struct { 38 ctx context.Context 39 id *TrieID 40 backend OdrBackend 41 } 42 43 func (db *odrDatabase) OpenTrie(root common.Hash) (state.Trie, error) { 44 return &odrTrie{db: db, id: db.id}, nil 45 } 46 47 func (db *odrDatabase) OpenStorageTrie(addrHash, root common.Hash) (state.Trie, error) { 48 return &odrTrie{db: db, id: StorageTrieID(db.id, addrHash, root)}, nil 49 } 50 51 func (db *odrDatabase) CopyTrie(t state.Trie) state.Trie { 52 switch t := t.(type) { 53 case *odrTrie: 54 cpy := &odrTrie{db: t.db, id: t.id} 55 if t.trie != nil { 56 cpytrie := *t.trie 57 cpy.trie = &cpytrie 58 } 59 return cpy 60 default: 61 panic(fmt.Errorf("unknown trie type %T", t)) 62 } 63 } 64 65 func (db *odrDatabase) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) { 66 if codeHash == sha3_nil { 67 return nil, nil 68 } 69 if code, err := db.backend.Database().Get(codeHash[:]); err == nil { 70 return code, nil 71 } 72 id := *db.id 73 id.AccKey = addrHash[:] 74 req := &CodeRequest{Id: &id, Hash: codeHash} 75 err := db.backend.Retrieve(db.ctx, req) 76 return req.Data, err 77 } 78 79 func (db *odrDatabase) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) { 80 code, err := db.ContractCode(addrHash, codeHash) 81 return len(code), err 82 } 83 84 func (db *odrDatabase) TrieDB() *trie.Database { 85 return nil 86 } 87 88 type odrTrie struct { 89 db *odrDatabase 90 id *TrieID 91 trie *trie.Trie 92 } 93 94 func (t *odrTrie) TryGet(key []byte) ([]byte, error) { 95 key = crypto.Keccak256(key) 96 var res []byte 97 err := t.do(key, func() (err error) { 98 res, err = t.trie.TryGet(key) 99 return err 100 }) 101 return res, err 102 } 103 104 func (t *odrTrie) TryUpdate(key, value []byte) error { 105 key = crypto.Keccak256(key) 106 return t.do(key, func() error { 107 return t.trie.TryUpdate(key, value) 108 }) 109 } 110 111 func (t *odrTrie) TryDelete(key []byte) error { 112 key = crypto.Keccak256(key) 113 return t.do(key, func() error { 114 return t.trie.TryDelete(key) 115 }) 116 } 117 118 func (t *odrTrie) Commit(onleaf trie.LeafCallback) (common.Hash, error) { 119 if t.trie == nil { 120 return t.id.Root, nil 121 } 122 return t.trie.Commit(onleaf) 123 } 124 125 func (t *odrTrie) Hash() common.Hash { 126 if t.trie == nil { 127 return t.id.Root 128 } 129 return t.trie.Hash() 130 } 131 132 func (t *odrTrie) NodeIterator(startkey []byte) trie.NodeIterator { 133 return newNodeIterator(t, startkey) 134 } 135 136 func (t *odrTrie) GetKey(sha []byte) []byte { 137 return nil 138 } 139 140 func (t *odrTrie) Prove(key []byte, fromLevel uint, proofDb ethdb.Putter) error { 141 return errors.New("not implemented, needs client/server interface split") 142 } 143 144 //尝试并重试执行一个函数,直到它返回时没有错误或 145 //MissingNodeError以外的错误类型 146 func (t *odrTrie) do(key []byte, fn func() error) error { 147 for { 148 var err error 149 if t.trie == nil { 150 t.trie, err = trie.New(t.id.Root, trie.NewDatabase(t.db.backend.Database())) 151 } 152 if err == nil { 153 err = fn() 154 } 155 if _, ok := err.(*trie.MissingNodeError); !ok { 156 return err 157 } 158 r := &TrieRequest{Id: t.id, Key: key} 159 if err := t.db.backend.Retrieve(t.db.ctx, r); err != nil { 160 return err 161 } 162 } 163 } 164 165 type nodeIterator struct { 166 trie.NodeIterator 167 t *odrTrie 168 err error 169 } 170 171 func newNodeIterator(t *odrTrie, startkey []byte) trie.NodeIterator { 172 it := &nodeIterator{t: t} 173 //如果还没有打开实际的非odr trie。 174 if t.trie == nil { 175 it.do(func() error { 176 t, err := trie.New(t.id.Root, trie.NewDatabase(t.db.backend.Database())) 177 if err == nil { 178 it.t.trie = t 179 } 180 return err 181 }) 182 } 183 it.do(func() error { 184 it.NodeIterator = it.t.trie.NodeIterator(startkey) 185 return it.NodeIterator.Error() 186 }) 187 return it 188 } 189 190 func (it *nodeIterator) Next(descend bool) bool { 191 var ok bool 192 it.do(func() error { 193 ok = it.NodeIterator.Next(descend) 194 return it.NodeIterator.Error() 195 }) 196 return ok 197 } 198 199 //do运行fn并尝试通过检索来填充丢失的节点。 200 func (it *nodeIterator) do(fn func() error) { 201 var lasthash common.Hash 202 for { 203 it.err = fn() 204 missing, ok := it.err.(*trie.MissingNodeError) 205 if !ok { 206 return 207 } 208 if missing.NodeHash == lasthash { 209 it.err = fmt.Errorf("retrieve loop for trie node %x", missing.NodeHash) 210 return 211 } 212 lasthash = missing.NodeHash 213 r := &TrieRequest{Id: it.t.id, Key: nibblesToKey(missing.Path)} 214 if it.err = it.t.db.backend.Retrieve(it.t.db.ctx, r); it.err != nil { 215 return 216 } 217 } 218 } 219 220 func (it *nodeIterator) Error() error { 221 if it.err != nil { 222 return it.err 223 } 224 return it.NodeIterator.Error() 225 } 226 227 func nibblesToKey(nib []byte) []byte { 228 if len(nib) > 0 && nib[len(nib)-1] == 0x10 { 229 nib = nib[:len(nib)-1] //液滴终止器 230 } 231 if len(nib)&1 == 1 { 232 nib = append(nib, 0) //使均匀 233 } 234 key := make([]byte, len(nib)/2) 235 for bi, ni := 0, 0; ni < len(nib); bi, ni = bi+1, ni+2 { 236 key[bi] = nib[ni]<<4 | nib[ni+1] 237 } 238 return key 239 } 240