Fix node resolution; use Cid struct as key
was erroneously storing the cid in the fullNode's flag.cache
This commit is contained in:
parent
3f0e36c0a3
commit
88e7a394d0
@ -1,4 +1,4 @@
|
||||
package util
|
||||
package internal
|
||||
|
||||
import (
|
||||
"github.com/ipfs/go-cid"
|
||||
|
@ -10,6 +10,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
|
||||
lru "github.com/hashicorp/golang-lru"
|
||||
|
||||
"github.com/cerc-io/ipld-eth-statedb/internal"
|
||||
"github.com/cerc-io/ipld-eth-statedb/trie_by_cid/trie"
|
||||
)
|
||||
|
||||
@ -97,11 +98,10 @@ func (db *cachingDB) ContractCode(codeHash common.Hash) ([]byte, error) {
|
||||
if code := db.codeCache.Get(nil, codeHash.Bytes()); len(code) > 0 {
|
||||
return code, nil
|
||||
}
|
||||
// TODO - use non panicking
|
||||
codeCID := ipld.Keccak256ToCid(ipld.RawBinary, codeHash.Bytes())
|
||||
// if err != nil {
|
||||
// return nil, err
|
||||
// }
|
||||
codeCID, err := internal.Keccak256ToCid(ipld.RawBinary, codeHash.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
code, err := db.db.DiskDB().Get(codeCID.Bytes())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -22,12 +22,13 @@ import (
|
||||
"github.com/VictoriaMetrics/fastcache"
|
||||
"github.com/ethereum/go-ethereum/ethdb"
|
||||
"github.com/ethereum/go-ethereum/trie"
|
||||
"github.com/ipfs/go-cid"
|
||||
)
|
||||
|
||||
type CidBytes = []byte
|
||||
type CidKey = cid.Cid
|
||||
|
||||
func isEmpty(key CidBytes) bool {
|
||||
return len(key) == 0
|
||||
func isEmpty(key CidKey) bool {
|
||||
return len(key.KeyString()) == 0
|
||||
}
|
||||
|
||||
// Database is an intermediate read-only layer between the trie data structures and
|
||||
@ -73,57 +74,30 @@ func (db *Database) DiskDB() ethdb.KeyValueStore {
|
||||
return db.diskdb
|
||||
}
|
||||
|
||||
// node retrieves a cached trie node from memory, or returns nil if none can be
|
||||
// found in the memory cache.
|
||||
func (db *Database) node(key CidBytes) (node, error) {
|
||||
// Retrieve the node from the clean cache if available
|
||||
if db.cleans != nil {
|
||||
if enc := db.cleans.Get(nil, key); enc != nil {
|
||||
// The returned value from cache is in its own copy,
|
||||
// safe to use mustDecodeNodeUnsafe for decoding.
|
||||
return decodeNodeUnsafe(key, enc)
|
||||
}
|
||||
}
|
||||
|
||||
// Content unavailable in memory, attempt to retrieve from disk
|
||||
enc, err := db.diskdb.Get(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if enc == nil {
|
||||
return nil, nil
|
||||
}
|
||||
if db.cleans != nil {
|
||||
db.cleans.Set(key, enc)
|
||||
}
|
||||
// The returned value from database is in its own copy,
|
||||
// safe to use mustDecodeNodeUnsafe for decoding.
|
||||
return decodeNodeUnsafe(key, enc)
|
||||
}
|
||||
|
||||
// Node retrieves an encoded cached trie node from memory. If it cannot be found
|
||||
// cached, the method queries the persistent database for the content.
|
||||
func (db *Database) Node(key CidBytes) ([]byte, error) {
|
||||
// Node retrieves an encoded trie node by CID. If it cannot be found
|
||||
// cached in memory, it queries the persistent database.
|
||||
func (db *Database) Node(key CidKey) ([]byte, error) {
|
||||
// It doesn't make sense to retrieve the metaroot
|
||||
if isEmpty(key) {
|
||||
return nil, errors.New("not found")
|
||||
}
|
||||
cidbytes := key.Bytes()
|
||||
// Retrieve the node from the clean cache if available
|
||||
if db.cleans != nil {
|
||||
if enc := db.cleans.Get(nil, key); enc != nil {
|
||||
if enc := db.cleans.Get(nil, cidbytes); enc != nil {
|
||||
return enc, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Content unavailable in memory, attempt to retrieve from disk
|
||||
enc, err := db.diskdb.Get(key)
|
||||
enc, err := db.diskdb.Get(cidbytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(enc) != 0 {
|
||||
if db.cleans != nil {
|
||||
db.cleans.Set(key[:], enc)
|
||||
db.cleans.Set(cidbytes, enc)
|
||||
}
|
||||
return enc, nil
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ import (
|
||||
// to retrieve the meta root.
|
||||
func TestDatabaseMetarootFetch(t *testing.T) {
|
||||
db := trie.NewDatabase(memorydb.New())
|
||||
if _, err := db.Node(trie.CidBytes(nil)); err == nil {
|
||||
if _, err := db.Node(trie.CidKey{}); err == nil {
|
||||
t.Fatalf("metaroot retrieval succeeded")
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
util "github.com/cerc-io/ipld-eth-statedb/internal"
|
||||
"github.com/ethereum/go-ethereum/statediff/indexer/ipld"
|
||||
)
|
||||
|
||||
@ -161,7 +162,11 @@ func (t *Trie) tryGetNode(origNode node, path []byte, pos int) (item []byte, new
|
||||
if hash == nil {
|
||||
return nil, origNode, 0, errors.New("non-consensus node")
|
||||
}
|
||||
blob, err := t.db.Node(hash)
|
||||
cid, err := util.Keccak256ToCid(t.codec, hash)
|
||||
if err != nil {
|
||||
return nil, origNode, 0, err
|
||||
}
|
||||
blob, err := t.db.Node(cid)
|
||||
return blob, origNode, 1, err
|
||||
}
|
||||
// Path still needs to be traversed, descend into children
|
||||
@ -206,8 +211,15 @@ func (t *Trie) tryGetNode(origNode node, path []byte, pos int) (item []byte, new
|
||||
// resolveHash loads node from the underlying database with the provided
|
||||
// node hash and path prefix.
|
||||
func (t *Trie) resolveHash(n hashNode, prefix []byte) (node, error) {
|
||||
cid := ipld.Keccak256ToCid(t.codec, n)
|
||||
node, err := t.db.node(cid.Bytes())
|
||||
cid, err := util.Keccak256ToCid(t.codec, n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
enc, err := t.db.Node(cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
node, err := decodeNodeUnsafe(n, enc)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@ -220,8 +232,14 @@ func (t *Trie) resolveHash(n hashNode, prefix []byte) (node, error) {
|
||||
// resolveHash loads rlp-encoded node blob from the underlying database
|
||||
// with the provided node hash and path prefix.
|
||||
func (t *Trie) resolveBlob(n hashNode, prefix []byte) ([]byte, error) {
|
||||
cid := ipld.Keccak256ToCid(t.codec, n)
|
||||
blob, _ := t.db.Node(cid.Bytes())
|
||||
cid, err := util.Keccak256ToCid(t.codec, n)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blob, err := t.db.Node(cid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(blob) != 0 {
|
||||
return blob, nil
|
||||
}
|
||||
@ -231,20 +249,20 @@ func (t *Trie) resolveBlob(n hashNode, prefix []byte) ([]byte, error) {
|
||||
// Hash returns the root hash of the trie. It does not write to the
|
||||
// database and can be used even if the trie doesn't have one.
|
||||
func (t *Trie) Hash() common.Hash {
|
||||
hash, cached, _ := t.hashRoot()
|
||||
hash, cached := t.hashRoot()
|
||||
t.root = cached
|
||||
return common.BytesToHash(hash.(hashNode))
|
||||
}
|
||||
|
||||
// hashRoot calculates the root hash of the given trie
|
||||
func (t *Trie) hashRoot() (node, node, error) {
|
||||
func (t *Trie) hashRoot() (node, node) {
|
||||
if t.root == nil {
|
||||
return hashNode(emptyRoot.Bytes()), nil, nil
|
||||
return hashNode(emptyRoot.Bytes()), nil
|
||||
}
|
||||
// If the number of changes is below 100, we let one thread handle it
|
||||
h := newHasher(t.unhashed >= 100)
|
||||
defer returnHasherToPool(h)
|
||||
hashed, cached := h.hash(t.root, true)
|
||||
t.unhashed = 0
|
||||
return hashed, cached, nil
|
||||
return hashed, cached
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user