/
cached_object.go
105 lines (87 loc) · 2.43 KB
/
cached_object.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
// Copyright (c) 2018 The VeChainThor developers
// Distributed under the GNU Lesser General Public License v3.0 software license, see the accompanying
// file LICENSE or <https://www.gnu.org/licenses/lgpl-3.0.html>
package state
import (
"github.com/ethereum/go-ethereum/rlp"
lru "github.com/hashicorp/golang-lru"
"github.com/miniBamboo/workshare/muxdb"
"github.com/miniBamboo/workshare/workshare"
)
var codeCache, _ = lru.NewARC(512)
// cachedObject to cache code and storage of an account.
type cachedObject struct {
db *muxdb.MuxDB
addr workshare.Address
data Account
meta AccountMetadata
cache struct {
code []byte
storageTrie *muxdb.Trie
storage map[workshare.Bytes32]rlp.RawValue
}
}
func newCachedObject(db *muxdb.MuxDB, addr workshare.Address, data *Account, meta *AccountMetadata) *cachedObject {
return &cachedObject{db: db, addr: addr, data: *data, meta: *meta}
}
func (co *cachedObject) getOrCreateStorageTrie() *muxdb.Trie {
if co.cache.storageTrie != nil {
return co.cache.storageTrie
}
if len(co.data.StorageRoot) == 0 {
return nil
}
trie := co.db.NewTrie(
StorageTrieName(co.meta.StorageID),
workshare.BytesToBytes32(co.data.StorageRoot),
co.meta.StorageCommitNum,
co.meta.StorageDistinctNum)
co.cache.storageTrie = trie
return trie
}
// GetStorage returns storage value for given key.
func (co *cachedObject) GetStorage(key workshare.Bytes32, steadyBlockNum uint32) (rlp.RawValue, error) {
cache := &co.cache
// retrive from storage cache
if cache.storage != nil {
if v, ok := cache.storage[key]; ok {
return v, nil
}
} else {
cache.storage = make(map[workshare.Bytes32]rlp.RawValue)
}
// not found in cache
trie := co.getOrCreateStorageTrie()
if trie == nil {
return nil, nil
}
// load from trie
v, err := loadStorage(trie, key, steadyBlockNum)
if err != nil {
return nil, err
}
// put into cache
cache.storage[key] = v
return v, nil
}
// GetCode returns the code of the account.
func (co *cachedObject) GetCode() ([]byte, error) {
cache := &co.cache
if len(cache.code) > 0 {
return cache.code, nil
}
if len(co.data.CodeHash) > 0 {
// do have code
if code, has := codeCache.Get(string(co.data.CodeHash)); has {
return code.([]byte), nil
}
code, err := co.db.NewStore(codeStoreName).Get(co.data.CodeHash)
if err != nil {
return nil, err
}
codeCache.Add(string(co.data.CodeHash), code)
cache.code = code
return code, nil
}
return nil, nil
}