Skip to content

Commit 41ab497

Browse files
committed
feat: setup versa db
1 parent 83a9b13 commit 41ab497

File tree

6 files changed

+443
-35
lines changed

6 files changed

+443
-35
lines changed

core/rawdb/accessors_trie.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ const HashScheme = "hash"
4646
// on extra state diffs to survive deep reorg.
4747
const PathScheme = "path"
4848

49+
const VersionScheme = "version"
50+
4951
// hasher is used to compute the sha256 hash of the provided data.
5052
type hasher struct{ sha crypto.KeccakState }
5153

core/state/caching_versa_db.go

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
package state
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"sync/atomic"
7+
8+
versa "github.com/bnb-chain/versioned-state-database"
9+
"github.com/ethereum/go-ethereum/common"
10+
"github.com/ethereum/go-ethereum/common/lru"
11+
"github.com/ethereum/go-ethereum/core/rawdb"
12+
"github.com/ethereum/go-ethereum/core/types"
13+
"github.com/ethereum/go-ethereum/crypto"
14+
"github.com/ethereum/go-ethereum/ethdb"
15+
"github.com/ethereum/go-ethereum/log"
16+
"github.com/ethereum/go-ethereum/rlp"
17+
"github.com/ethereum/go-ethereum/trie"
18+
"github.com/ethereum/go-ethereum/trie/trienode"
19+
"github.com/ethereum/go-ethereum/triedb"
20+
)
21+
22+
type cachingVersaDB struct {
23+
triedb *triedb.Database
24+
versionDB versa.Database
25+
codeDB ethdb.KeyValueStore
26+
codeSizeCache *lru.Cache[common.Hash, int]
27+
codeCache *lru.SizeConstrainedCache[common.Hash, []byte]
28+
29+
accTree *VersaTree
30+
state versa.StateHandler
31+
root common.Hash
32+
mode versa.StateMode
33+
hasState atomic.Bool
34+
}
35+
36+
// NewVersaDatabase should be call by NewDatabaseWithNodeDB
37+
// TODO:: NewDatabaseWithNodeDB should add mode param.
38+
func NewVersaDatabase(db ethdb.Database, triedb *triedb.Database, mode versa.StateMode) Database {
39+
return &cachingVersaDB{
40+
triedb: triedb,
41+
versionDB: triedb.VersaDB(),
42+
codeDB: db,
43+
codeSizeCache: lru.NewCache[common.Hash, int](codeSizeCacheSize),
44+
codeCache: lru.NewSizeConstrainedCache[common.Hash, []byte](codeCacheSize),
45+
}
46+
}
47+
48+
func (cv *cachingVersaDB) OpenTrie(root common.Hash) (Trie, error) {
49+
if cv.hasState.Load() {
50+
//TODO:: will change to log.Error after stabilization
51+
panic("account tree has open")
52+
}
53+
54+
// TODO:: if root tree, versa db shouldb ignore check version
55+
state, err := cv.versionDB.OpenState(0, root, cv.mode)
56+
if err != nil {
57+
return nil, err
58+
}
59+
60+
handler, err := cv.versionDB.OpenTree(state, 0, common.Hash{}, root)
61+
if err != nil {
62+
return nil, err
63+
}
64+
65+
tree := &VersaTree{
66+
db: cv.versionDB,
67+
handler: handler,
68+
accountTree: true,
69+
root: root,
70+
}
71+
72+
cv.state = state
73+
cv.hasState.Store(true) // if set, can't change
74+
cv.accTree = tree
75+
cv.root = root
76+
77+
return tree, nil
78+
}
79+
80+
func (cv *cachingVersaDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash, _ Trie) (Trie, error) {
81+
if !cv.hasState.Load() {
82+
//TODO:: will change to log.Error after stabilization
83+
panic("open account tree, before open storage tree")
84+
}
85+
if cv.root.Cmp(root) != 0 {
86+
panic("account root mismatch, on open storage tree")
87+
}
88+
89+
version, account, err := cv.accTree.getAccountWithVersion(address)
90+
if err != nil {
91+
return nil, err
92+
}
93+
if account.Root.Cmp(stateRoot) != 0 {
94+
return nil, fmt.Errorf("state root mismatch")
95+
}
96+
97+
handler, err := cv.versionDB.OpenTree(cv.state, version, crypto.Keccak256Hash(address.Bytes()), stateRoot)
98+
if err != nil {
99+
return nil, err
100+
}
101+
102+
tree := &VersaTree{
103+
db: cv.versionDB,
104+
handler: handler,
105+
version: version,
106+
root: root,
107+
stateRoot: stateRoot,
108+
address: address,
109+
}
110+
return tree, nil
111+
}
112+
113+
// Flush unique to versa
114+
func (cv *cachingVersaDB) Flush() error {
115+
return cv.versionDB.Flush(cv.state)
116+
}
117+
118+
// Release unique to versa
119+
func (cv *cachingVersaDB) Release() error {
120+
if err := cv.versionDB.CloseState(cv.state); err != nil {
121+
return nil
122+
}
123+
cv.release()
124+
return nil
125+
}
126+
127+
func (cv *cachingVersaDB) release() {
128+
cv.hasState.Store(false)
129+
cv.accTree = nil
130+
}
131+
132+
func (cv *cachingVersaDB) CopyTrie(Trie) Trie {
133+
//TODO:: support in the future
134+
return nil
135+
}
136+
137+
func (cv *cachingVersaDB) ContractCode(addr common.Address, codeHash common.Hash) ([]byte, error) {
138+
code, _ := cv.codeCache.Get(codeHash)
139+
if len(code) > 0 {
140+
return code, nil
141+
}
142+
code = rawdb.ReadCodeWithPrefix(cv.codeDB, codeHash)
143+
if len(code) > 0 {
144+
cv.codeCache.Add(codeHash, code)
145+
cv.codeSizeCache.Add(codeHash, len(code))
146+
return code, nil
147+
}
148+
return nil, errors.New("not found")
149+
}
150+
151+
func (cv *cachingVersaDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
152+
if cached, ok := cv.codeSizeCache.Get(codeHash); ok {
153+
return cached, nil
154+
}
155+
code, err := cv.ContractCode(addr, codeHash)
156+
return len(code), err
157+
}
158+
159+
func (cv *cachingVersaDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) {
160+
code, _ := cv.codeCache.Get(codeHash)
161+
if len(code) > 0 {
162+
return code, nil
163+
}
164+
code = rawdb.ReadCodeWithPrefix(cv.codeDB, codeHash)
165+
if len(code) > 0 {
166+
cv.codeCache.Add(codeHash, code)
167+
cv.codeSizeCache.Add(codeHash, len(code))
168+
return code, nil
169+
}
170+
return nil, errors.New("not found")
171+
}
172+
173+
func (cv *cachingVersaDB) DiskDB() ethdb.KeyValueStore {
174+
return cv.codeDB
175+
}
176+
177+
func (cv *cachingVersaDB) TrieDB() *triedb.Database {
178+
return cv.triedb
179+
}
180+
181+
func (cv *cachingVersaDB) NoTries() bool {
182+
// TODO:: not support fastnode
183+
return false
184+
}
185+
186+
type VersaTree struct {
187+
db versa.Database
188+
handler versa.TreeHandler
189+
version int64
190+
accountTree bool
191+
192+
// TODO:: debugging, used for logging
193+
root common.Hash
194+
stateRoot common.Hash
195+
address common.Address
196+
}
197+
198+
func (vt *VersaTree) GetKey(key []byte) []byte {
199+
_, val, err := vt.db.Get(vt.handler, key)
200+
if err != nil {
201+
log.Warn("failed to get key from version db")
202+
}
203+
return val
204+
}
205+
206+
func (vt *VersaTree) GetAccount(address common.Address) (*types.StateAccount, error) {
207+
_, res, err := vt.getAccountWithVersion(address)
208+
return res, err
209+
}
210+
211+
func (vt *VersaTree) getAccountWithVersion(address common.Address) (int64, *types.StateAccount, error) {
212+
vt.CheckAccountTree()
213+
ver, res, err := vt.db.Get(vt.handler, address.Bytes())
214+
if res == nil || err != nil {
215+
return ver, nil, err
216+
}
217+
ret := new(types.StateAccount)
218+
err = rlp.DecodeBytes(res, ret)
219+
return ver, ret, err
220+
}
221+
222+
func (vt *VersaTree) GetStorage(_ common.Address, key []byte) ([]byte, error) {
223+
vt.CheckStorageTree()
224+
_, res, err := vt.db.Get(vt.handler, key)
225+
if res == nil || err != nil {
226+
return nil, err
227+
}
228+
return res, err
229+
}
230+
231+
func (vt *VersaTree) UpdateAccount(address common.Address, account *types.StateAccount) error {
232+
vt.CheckAccountTree()
233+
data, err := rlp.EncodeToBytes(account)
234+
if err != nil {
235+
return err
236+
}
237+
return vt.db.Put(vt.handler, address.Bytes(), data)
238+
}
239+
240+
func (vt *VersaTree) UpdateStorage(_ common.Address, key, value []byte) error {
241+
vt.CheckStorageTree()
242+
return vt.db.Put(vt.handler, key, value)
243+
}
244+
245+
func (vt *VersaTree) DeleteAccount(address common.Address) error {
246+
vt.CheckAccountTree()
247+
return vt.db.Delete(vt.handler, address.Bytes())
248+
}
249+
250+
func (vt *VersaTree) DeleteStorage(_ common.Address, key []byte) error {
251+
vt.CheckStorageTree()
252+
return vt.db.Delete(vt.handler, key)
253+
}
254+
255+
func (vt *VersaTree) UpdateContractCode(address common.Address, codeHash common.Hash, code []byte) error {
256+
return nil
257+
}
258+
259+
func (vt *VersaTree) Hash() common.Hash {
260+
hash, err := vt.db.CalcRootHash(vt.handler)
261+
if err != nil {
262+
log.Warn("failed to cacl versa tree hash", "error", err)
263+
}
264+
return hash
265+
}
266+
267+
func (vt *VersaTree) Commit(_ bool) (common.Hash, *trienode.NodeSet, error) {
268+
hash, err := vt.db.Commit(vt.handler)
269+
if err != nil {
270+
log.Warn("failed to commit versa tree", "error", err)
271+
}
272+
return hash, nil, nil
273+
}
274+
275+
func (vt *VersaTree) NodeIterator(startKey []byte) (trie.NodeIterator, error) {
276+
panic("versa tree not support iterate")
277+
return nil, nil
278+
}
279+
280+
func (vt *VersaTree) Prove(key []byte, proofDb ethdb.KeyValueWriter) error {
281+
panic("versa tree not support prove")
282+
return nil
283+
}
284+
285+
// TODO:: test code, will be deleted after stabilization
286+
func (vt *VersaTree) CheckAccountTree() {
287+
if !vt.accountTree {
288+
panic("sub tree can't operate account")
289+
}
290+
}
291+
292+
// TODO:: test code, will be deleted after stabilization
293+
func (vt *VersaTree) CheckStorageTree() {
294+
if vt.accountTree {
295+
panic("root tree can't operate storage")
296+
}
297+
}

go.mod

Lines changed: 14 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ require (
1212
github.com/aws/aws-sdk-go-v2/service/route53 v1.30.2
1313
github.com/bnb-chain/fastssz v0.1.2
1414
github.com/bnb-chain/ics23 v0.1.0
15+
github.com/bnb-chain/versioned-state-database v0.0.0-20240809035848-76ffc0e09a92
1516
github.com/btcsuite/btcd/btcec/v2 v2.3.2
1617
github.com/cespare/cp v1.1.1
1718
github.com/cloudflare/cloudflare-go v0.79.0
@@ -44,7 +45,7 @@ require (
4445
github.com/hashicorp/golang-lru v0.5.5-0.20210104140557-80c98217689d
4546
github.com/holiman/billy v0.0.0-20240216141850-2abb0c79d3c4
4647
github.com/holiman/bloomfilter/v2 v2.0.3
47-
github.com/holiman/uint256 v1.2.4
48+
github.com/holiman/uint256 v1.3.0
4849
github.com/huin/goupnp v1.3.0
4950
github.com/influxdata/influxdb-client-go/v2 v2.4.0
5051
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
@@ -67,7 +68,7 @@ require (
6768
github.com/rs/cors v1.8.2
6869
github.com/shirou/gopsutil v3.21.11+incompatible
6970
github.com/status-im/keycard-go v0.2.0
70-
github.com/stretchr/testify v1.8.4
71+
github.com/stretchr/testify v1.9.0
7172
github.com/supranational/blst v0.3.11
7273
github.com/syndtr/goleveldb v1.0.1
7374
github.com/tendermint/go-amino v0.14.1
@@ -79,13 +80,13 @@ require (
7980
github.com/wealdtech/go-eth2-wallet-encryptor-keystorev4 v1.1.3
8081
github.com/willf/bitset v1.1.3
8182
go.uber.org/automaxprocs v1.5.2
82-
golang.org/x/crypto v0.21.0
83+
golang.org/x/crypto v0.25.0
8384
golang.org/x/exp v0.0.0-20240213143201-ec583247a57a
84-
golang.org/x/sync v0.6.0
85-
golang.org/x/sys v0.20.0
86-
golang.org/x/text v0.14.0
85+
golang.org/x/sync v0.7.0
86+
golang.org/x/sys v0.22.0
87+
golang.org/x/text v0.16.0
8788
golang.org/x/time v0.5.0
88-
golang.org/x/tools v0.18.0
89+
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d
8990
gopkg.in/natefinch/lumberjack.v2 v2.0.0
9091
gopkg.in/yaml.v3 v3.0.1
9192
)
@@ -111,7 +112,7 @@ require (
111112
github.com/beorn7/perks v1.0.1 // indirect
112113
github.com/bits-and-blooms/bitset v1.11.0 // indirect
113114
github.com/cespare/xxhash v1.1.0 // indirect
114-
github.com/cespare/xxhash/v2 v2.2.0 // indirect
115+
github.com/cespare/xxhash/v2 v2.3.0 // indirect
115116
github.com/chzyer/readline v1.5.1 // indirect
116117
github.com/cockroachdb/errors v1.11.1 // indirect
117118
github.com/cockroachdb/logtags v0.0.0-20230118201751-21c54148d20b // indirect
@@ -251,6 +252,7 @@ require (
251252
github.com/spf13/afero v1.10.0 // indirect
252253
github.com/tecbot/gorocksdb v0.0.0-20191217155057-f0fad39f321c // indirect
253254
github.com/thomaso-mirodin/intmath v0.0.0-20160323211736-5dc6d854e46e // indirect
255+
github.com/tidwall/btree v1.7.0 // indirect
254256
github.com/tidwall/gjson v1.10.2 // indirect
255257
github.com/tidwall/match v1.1.1 // indirect
256258
github.com/tidwall/pretty v1.2.0 // indirect
@@ -271,10 +273,10 @@ require (
271273
go.uber.org/mock v0.4.0 // indirect
272274
go.uber.org/multierr v1.11.0 // indirect
273275
go.uber.org/zap v1.27.0 // indirect
274-
golang.org/x/mod v0.15.0 // indirect
275-
golang.org/x/net v0.23.0 // indirect
276+
golang.org/x/mod v0.17.0 // indirect
277+
golang.org/x/net v0.25.0 // indirect
276278
golang.org/x/oauth2 v0.16.0 // indirect
277-
golang.org/x/term v0.18.0 // indirect
279+
golang.org/x/term v0.22.0 // indirect
278280
google.golang.org/api v0.44.0 // indirect
279281
google.golang.org/appengine v1.6.7 // indirect
280282
google.golang.org/genproto v0.0.0-20231016165738-49dd2c1f3d0b // indirect
@@ -295,6 +297,7 @@ require (
295297
)
296298

297299
replace (
300+
github.com/bnb-chain/versioned-state-database => ../versioned-state-database
298301
github.com/cometbft/cometbft => github.com/bnb-chain/greenfield-cometbft v1.3.1
299302
github.com/grpc-ecosystem/grpc-gateway/v2 => github.com/prysmaticlabs/grpc-gateway/v2 v2.3.1-0.20210702154020-550e1cd83ec1
300303
github.com/syndtr/goleveldb v1.0.1 => github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7

0 commit comments

Comments
 (0)