mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-18 02:40:45 +00:00
This commit is contained in:
parent
07d3c421f3
commit
398d9b693d
19 changed files with 132 additions and 110 deletions
|
|
@ -16,7 +16,7 @@ func TestXDCxTrieTest(t *testing.T) {
|
||||||
t.SkipNow()
|
t.SkipNow()
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
stateCache := NewDatabase(db)
|
stateCache := NewDatabase(db)
|
||||||
trie, _ := stateCache.OpenStorageTrie(EmptyHash, types.EmptyRootHash)
|
trie, _ := stateCache.OpenStorageTrie(EmptyHash, common.Address{}, types.EmptyRootHash)
|
||||||
max := 1000000
|
max := 1000000
|
||||||
for i := 1; i < max; i++ {
|
for i := 1; i < max; i++ {
|
||||||
k := common.BigToHash(big.NewInt(int64(i))).Bytes()
|
k := common.BigToHash(big.NewInt(int64(i))).Bytes()
|
||||||
|
|
|
||||||
|
|
@ -33,16 +33,16 @@ type Database interface {
|
||||||
OpenTrie(root common.Hash) (Trie, error)
|
OpenTrie(root common.Hash) (Trie, error)
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
OpenStorageTrie(addrHash, root common.Hash) (Trie, error)
|
OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error)
|
||||||
|
|
||||||
// CopyTrie returns an independent copy of the given trie.
|
// CopyTrie returns an independent copy of the given trie.
|
||||||
CopyTrie(Trie) Trie
|
CopyTrie(Trie) Trie
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
ContractCode(addrHash, codeHash common.Hash) ([]byte, error)
|
ContractCode(address common.Address, codeHash common.Hash) ([]byte, error)
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
|
ContractCodeSize(address common.Address, codeHash common.Hash) (int, error)
|
||||||
|
|
||||||
// TrieDB retrieves the low level trie database used for data storage.
|
// TrieDB retrieves the low level trie database used for data storage.
|
||||||
TrieDB() *trie.Database
|
TrieDB() *trie.Database
|
||||||
|
|
@ -83,7 +83,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
|
func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error) {
|
||||||
return NewXDCXTrie(root, db.db)
|
return NewXDCXTrie(root, db.db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,12 +98,12 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) {
|
func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) {
|
func (db *cachingDB) ContractCodeSize(address common.Address, codeHash common.Hash) (int, error) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -79,9 +79,9 @@ func (s *stateLendingBook) setError(err error) {
|
||||||
func (s *stateLendingBook) getTrie(db Database) Trie {
|
func (s *stateLendingBook) getTrie(db Database) Trie {
|
||||||
if s.trie == nil {
|
if s.trie == nil {
|
||||||
var err error
|
var err error
|
||||||
s.trie, err = db.OpenStorageTrie(s.lendingBook, s.data.Root)
|
s.trie, err = db.OpenStorageTrie(s.lendingBook, common.Address{}, s.data.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.trie, _ = db.OpenStorageTrie(s.price, types.EmptyRootHash)
|
s.trie, _ = db.OpenStorageTrie(s.price, common.Address{}, types.EmptyRootHash)
|
||||||
s.setError(fmt.Errorf("can't create storage trie: %v", err))
|
s.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -102,9 +102,9 @@ func (s *liquidationPriceState) createLendingBook(db Database, lendingBook commo
|
||||||
func (s *liquidationPriceState) getTrie(db Database) Trie {
|
func (s *liquidationPriceState) getTrie(db Database) Trie {
|
||||||
if s.trie == nil {
|
if s.trie == nil {
|
||||||
var err error
|
var err error
|
||||||
s.trie, err = db.OpenStorageTrie(s.liquidationPrice, s.data.Root)
|
s.trie, err = db.OpenStorageTrie(s.liquidationPrice, common.Address{}, s.data.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.trie, _ = db.OpenStorageTrie(s.liquidationPrice, types.EmptyRootHash)
|
s.trie, _ = db.OpenStorageTrie(s.liquidationPrice, common.Address{}, types.EmptyRootHash)
|
||||||
s.setError(fmt.Errorf("can't create storage trie: %v", err))
|
s.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -90,9 +90,9 @@ func (s *stateOrderList) setError(err error) {
|
||||||
func (s *stateOrderList) getTrie(db Database) Trie {
|
func (s *stateOrderList) getTrie(db Database) Trie {
|
||||||
if s.trie == nil {
|
if s.trie == nil {
|
||||||
var err error
|
var err error
|
||||||
s.trie, err = db.OpenStorageTrie(s.price, s.data.Root)
|
s.trie, err = db.OpenStorageTrie(s.price, common.Address{}, s.data.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.trie, _ = db.OpenStorageTrie(s.price, types.EmptyRootHash)
|
s.trie, _ = db.OpenStorageTrie(s.price, common.Address{}, types.EmptyRootHash)
|
||||||
s.setError(fmt.Errorf("can't create storage trie: %v", err))
|
s.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -134,9 +134,9 @@ func (te *tradingExchanges) setError(err error) {
|
||||||
func (te *tradingExchanges) getAsksTrie(db Database) Trie {
|
func (te *tradingExchanges) getAsksTrie(db Database) Trie {
|
||||||
if te.asksTrie == nil {
|
if te.asksTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
te.asksTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.AskRoot)
|
te.asksTrie, err = db.OpenStorageTrie(te.orderBookHash, common.Address{}, te.data.AskRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
te.asksTrie, _ = db.OpenStorageTrie(te.orderBookHash, types.EmptyRootHash)
|
te.asksTrie, _ = db.OpenStorageTrie(te.orderBookHash, common.Address{}, types.EmptyRootHash)
|
||||||
te.setError(fmt.Errorf("can't create asks trie: %v", err))
|
te.setError(fmt.Errorf("can't create asks trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -146,9 +146,9 @@ func (te *tradingExchanges) getAsksTrie(db Database) Trie {
|
||||||
func (te *tradingExchanges) getOrdersTrie(db Database) Trie {
|
func (te *tradingExchanges) getOrdersTrie(db Database) Trie {
|
||||||
if te.ordersTrie == nil {
|
if te.ordersTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
te.ordersTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.OrderRoot)
|
te.ordersTrie, err = db.OpenStorageTrie(te.orderBookHash, common.Address{}, te.data.OrderRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
te.ordersTrie, _ = db.OpenStorageTrie(te.orderBookHash, types.EmptyRootHash)
|
te.ordersTrie, _ = db.OpenStorageTrie(te.orderBookHash, common.Address{}, types.EmptyRootHash)
|
||||||
te.setError(fmt.Errorf("can't create asks trie: %v", err))
|
te.setError(fmt.Errorf("can't create asks trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -264,9 +264,9 @@ func (te *tradingExchanges) CommitAsksTrie(db Database) error {
|
||||||
func (te *tradingExchanges) getBidsTrie(db Database) Trie {
|
func (te *tradingExchanges) getBidsTrie(db Database) Trie {
|
||||||
if te.bidsTrie == nil {
|
if te.bidsTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
te.bidsTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.BidRoot)
|
te.bidsTrie, err = db.OpenStorageTrie(te.orderBookHash, common.Address{}, te.data.BidRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
te.bidsTrie, _ = db.OpenStorageTrie(te.orderBookHash, types.EmptyRootHash)
|
te.bidsTrie, _ = db.OpenStorageTrie(te.orderBookHash, common.Address{}, types.EmptyRootHash)
|
||||||
te.setError(fmt.Errorf("can't create bids trie: %v", err))
|
te.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -635,9 +635,9 @@ func (te *tradingExchanges) createStateLiquidationPrice(db Database, liquidation
|
||||||
func (te *tradingExchanges) getLiquidationPriceTrie(db Database) Trie {
|
func (te *tradingExchanges) getLiquidationPriceTrie(db Database) Trie {
|
||||||
if te.liquidationPriceTrie == nil {
|
if te.liquidationPriceTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
te.liquidationPriceTrie, err = db.OpenStorageTrie(te.orderBookHash, te.data.LiquidationPriceRoot)
|
te.liquidationPriceTrie, err = db.OpenStorageTrie(te.orderBookHash, common.Address{}, te.data.LiquidationPriceRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
te.liquidationPriceTrie, _ = db.OpenStorageTrie(te.orderBookHash, types.EmptyRootHash)
|
te.liquidationPriceTrie, _ = db.OpenStorageTrie(te.orderBookHash, common.Address{}, types.EmptyRootHash)
|
||||||
te.setError(fmt.Errorf("can't create liquidation liquidationPrice trie: %v", err))
|
te.setError(fmt.Errorf("can't create liquidation liquidationPrice trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,16 +33,16 @@ type Database interface {
|
||||||
OpenTrie(root common.Hash) (Trie, error)
|
OpenTrie(root common.Hash) (Trie, error)
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
OpenStorageTrie(addrHash, root common.Hash) (Trie, error)
|
OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error)
|
||||||
|
|
||||||
// CopyTrie returns an independent copy of the given trie.
|
// CopyTrie returns an independent copy of the given trie.
|
||||||
CopyTrie(Trie) Trie
|
CopyTrie(Trie) Trie
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
ContractCode(addrHash, codeHash common.Hash) ([]byte, error)
|
ContractCode(address common.Address, codeHash common.Hash) ([]byte, error)
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
|
ContractCodeSize(address common.Address, codeHash common.Hash) (int, error)
|
||||||
|
|
||||||
// TrieDB retrieves the low level trie database used for data storage.
|
// TrieDB retrieves the low level trie database used for data storage.
|
||||||
TrieDB() *trie.Database
|
TrieDB() *trie.Database
|
||||||
|
|
@ -83,7 +83,7 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
func (db *cachingDB) OpenStorageTrie(addrHash, root common.Hash) (Trie, error) {
|
func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error) {
|
||||||
return NewXDCXTrie(root, db.db)
|
return NewXDCXTrie(root, db.db)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -98,12 +98,12 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) {
|
func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) {
|
func (db *cachingDB) ContractCodeSize(address common.Address, codeHash common.Hash) (int, error) {
|
||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -78,9 +78,9 @@ func (il *itemListState) setError(err error) {
|
||||||
func (il *itemListState) getTrie(db Database) Trie {
|
func (il *itemListState) getTrie(db Database) Trie {
|
||||||
if il.trie == nil {
|
if il.trie == nil {
|
||||||
var err error
|
var err error
|
||||||
il.trie, err = db.OpenStorageTrie(il.key, il.data.Root)
|
il.trie, err = db.OpenStorageTrie(il.key, common.Address{}, il.data.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
il.trie, _ = db.OpenStorageTrie(il.key, types.EmptyRootHash)
|
il.trie, _ = db.OpenStorageTrie(il.key, common.Address{}, types.EmptyRootHash)
|
||||||
il.setError(fmt.Errorf("can't create storage trie: %v", err))
|
il.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -127,9 +127,9 @@ func (s *lendingExchangeState) setError(err error) {
|
||||||
func (s *lendingExchangeState) getLendingItemTrie(db Database) Trie {
|
func (s *lendingExchangeState) getLendingItemTrie(db Database) Trie {
|
||||||
if s.lendingItemTrie == nil {
|
if s.lendingItemTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
s.lendingItemTrie, err = db.OpenStorageTrie(s.lendingBook, s.data.LendingItemRoot)
|
s.lendingItemTrie, err = db.OpenStorageTrie(s.lendingBook, common.Address{}, s.data.LendingItemRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.lendingItemTrie, _ = db.OpenStorageTrie(s.lendingBook, types.EmptyRootHash)
|
s.lendingItemTrie, _ = db.OpenStorageTrie(s.lendingBook, common.Address{}, types.EmptyRootHash)
|
||||||
s.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
s.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -139,9 +139,9 @@ func (s *lendingExchangeState) getLendingItemTrie(db Database) Trie {
|
||||||
func (s *lendingExchangeState) getLendingTradeTrie(db Database) Trie {
|
func (s *lendingExchangeState) getLendingTradeTrie(db Database) Trie {
|
||||||
if s.lendingTradeTrie == nil {
|
if s.lendingTradeTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
s.lendingTradeTrie, err = db.OpenStorageTrie(s.lendingBook, s.data.LendingTradeRoot)
|
s.lendingTradeTrie, err = db.OpenStorageTrie(s.lendingBook, common.Address{}, s.data.LendingTradeRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.lendingTradeTrie, _ = db.OpenStorageTrie(s.lendingBook, types.EmptyRootHash)
|
s.lendingTradeTrie, _ = db.OpenStorageTrie(s.lendingBook, common.Address{}, types.EmptyRootHash)
|
||||||
s.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
s.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,9 +151,9 @@ func (s *lendingExchangeState) getLendingTradeTrie(db Database) Trie {
|
||||||
func (s *lendingExchangeState) getInvestingTrie(db Database) Trie {
|
func (s *lendingExchangeState) getInvestingTrie(db Database) Trie {
|
||||||
if s.investingTrie == nil {
|
if s.investingTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
s.investingTrie, err = db.OpenStorageTrie(s.lendingBook, s.data.InvestingRoot)
|
s.investingTrie, err = db.OpenStorageTrie(s.lendingBook, common.Address{}, s.data.InvestingRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.investingTrie, _ = db.OpenStorageTrie(s.lendingBook, types.EmptyRootHash)
|
s.investingTrie, _ = db.OpenStorageTrie(s.lendingBook, common.Address{}, types.EmptyRootHash)
|
||||||
s.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
s.setError(fmt.Errorf("can't create Lendings trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -163,9 +163,9 @@ func (s *lendingExchangeState) getInvestingTrie(db Database) Trie {
|
||||||
func (s *lendingExchangeState) getBorrowingTrie(db Database) Trie {
|
func (s *lendingExchangeState) getBorrowingTrie(db Database) Trie {
|
||||||
if s.borrowingTrie == nil {
|
if s.borrowingTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
s.borrowingTrie, err = db.OpenStorageTrie(s.lendingBook, s.data.BorrowingRoot)
|
s.borrowingTrie, err = db.OpenStorageTrie(s.lendingBook, common.Address{}, s.data.BorrowingRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.borrowingTrie, _ = db.OpenStorageTrie(s.lendingBook, types.EmptyRootHash)
|
s.borrowingTrie, _ = db.OpenStorageTrie(s.lendingBook, common.Address{}, types.EmptyRootHash)
|
||||||
s.setError(fmt.Errorf("can't create bids trie: %v", err))
|
s.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -175,9 +175,9 @@ func (s *lendingExchangeState) getBorrowingTrie(db Database) Trie {
|
||||||
func (s *lendingExchangeState) getLiquidationTimeTrie(db Database) Trie {
|
func (s *lendingExchangeState) getLiquidationTimeTrie(db Database) Trie {
|
||||||
if s.liquidationTimeTrie == nil {
|
if s.liquidationTimeTrie == nil {
|
||||||
var err error
|
var err error
|
||||||
s.liquidationTimeTrie, err = db.OpenStorageTrie(s.lendingBook, s.data.LiquidationTimeRoot)
|
s.liquidationTimeTrie, err = db.OpenStorageTrie(s.lendingBook, common.Address{}, s.data.LiquidationTimeRoot)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.liquidationTimeTrie, _ = db.OpenStorageTrie(s.lendingBook, types.EmptyRootHash)
|
s.liquidationTimeTrie, _ = db.OpenStorageTrie(s.lendingBook, common.Address{}, types.EmptyRootHash)
|
||||||
s.setError(fmt.Errorf("can't create bids trie: %v", err))
|
s.setError(fmt.Errorf("can't create bids trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -77,9 +77,9 @@ func (lt *liquidationTimeState) setError(err error) {
|
||||||
func (lt *liquidationTimeState) getTrie(db Database) Trie {
|
func (lt *liquidationTimeState) getTrie(db Database) Trie {
|
||||||
if lt.trie == nil {
|
if lt.trie == nil {
|
||||||
var err error
|
var err error
|
||||||
lt.trie, err = db.OpenStorageTrie(lt.lendingBook, lt.data.Root)
|
lt.trie, err = db.OpenStorageTrie(lt.lendingBook, common.Address{}, lt.data.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lt.trie, _ = db.OpenStorageTrie(lt.time, types.EmptyRootHash)
|
lt.trie, _ = db.OpenStorageTrie(lt.lendingBook, common.Address{}, types.EmptyRootHash)
|
||||||
lt.setError(fmt.Errorf("can't create storage trie: %v", err))
|
lt.setError(fmt.Errorf("can't create storage trie: %v", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -265,7 +265,7 @@ func (bc *BlockChain) TrieNode(hash common.Hash) ([]byte, error) {
|
||||||
// ContractCode retrieves a blob of data associated with a contract hash
|
// ContractCode retrieves a blob of data associated with a contract hash
|
||||||
// either from ephemeral in-memory cache, or from persistent storage.
|
// either from ephemeral in-memory cache, or from persistent storage.
|
||||||
func (bc *BlockChain) ContractCode(hash common.Hash) ([]byte, error) {
|
func (bc *BlockChain) ContractCode(hash common.Hash) ([]byte, error) {
|
||||||
return bc.stateCache.ContractCode(common.Hash{}, hash)
|
return bc.stateCache.ContractCode(common.Address{}, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCodeWithPrefix retrieves a blob of data associated with a contract
|
// ContractCodeWithPrefix retrieves a blob of data associated with a contract
|
||||||
|
|
@ -275,9 +275,11 @@ func (bc *BlockChain) ContractCode(hash common.Hash) ([]byte, error) {
|
||||||
// new code scheme.
|
// new code scheme.
|
||||||
func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
|
func (bc *BlockChain) ContractCodeWithPrefix(hash common.Hash) ([]byte, error) {
|
||||||
type codeReader interface {
|
type codeReader interface {
|
||||||
ContractCodeWithPrefix(addrHash, codeHash common.Hash) ([]byte, error)
|
ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error)
|
||||||
}
|
}
|
||||||
return bc.stateCache.(codeReader).ContractCodeWithPrefix(common.Hash{}, hash)
|
// TODO(rjl493456442) The associated account address is also required
|
||||||
|
// in Verkle scheme. Fix it once snap-sync is supported for Verkle.
|
||||||
|
return bc.stateCache.(codeReader).ContractCodeWithPrefix(common.Address{}, hash)
|
||||||
}
|
}
|
||||||
|
|
||||||
// State returns a new mutable state based on the current HEAD block.
|
// State returns a new mutable state based on the current HEAD block.
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ func InspectDatabase(db ethdb.Database, keyPrefix, keyStart []byte) error {
|
||||||
receiptSize += size
|
receiptSize += size
|
||||||
case bytes.HasPrefix(key, txLookupPrefix) && len(key) == (len(txLookupPrefix)+common.HashLength):
|
case bytes.HasPrefix(key, txLookupPrefix) && len(key) == (len(txLookupPrefix)+common.HashLength):
|
||||||
txlookupSize += size
|
txlookupSize += size
|
||||||
case bytes.HasPrefix(key, preimagePrefix) && len(key) == (len(preimagePrefix)+common.HashLength):
|
case bytes.HasPrefix(key, PreimagePrefix) && len(key) == (len(PreimagePrefix)+common.HashLength):
|
||||||
preimageSize += size
|
preimageSize += size
|
||||||
case bytes.HasPrefix(key, bloomBitsPrefix) && len(key) == (len(bloomBitsPrefix)+10+common.HashLength):
|
case bytes.HasPrefix(key, bloomBitsPrefix) && len(key) == (len(bloomBitsPrefix)+10+common.HashLength):
|
||||||
bloomBitsSize += size
|
bloomBitsSize += size
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ var (
|
||||||
trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node
|
trieNodeAccountPrefix = []byte("A") // trieNodeAccountPrefix + hexPath -> trie node
|
||||||
trieNodeStoragePrefix = []byte("O") // trieNodeStoragePrefix + accountHash + hexPath -> trie node
|
trieNodeStoragePrefix = []byte("O") // trieNodeStoragePrefix + accountHash + hexPath -> trie node
|
||||||
|
|
||||||
preimagePrefix = []byte("secure-key-") // preimagePrefix + hash -> preimage
|
PreimagePrefix = []byte("secure-key-") // PreimagePrefix + hash -> preimage
|
||||||
configPrefix = []byte("ethereum-config-") // config prefix for the db
|
configPrefix = []byte("ethereum-config-") // config prefix for the db
|
||||||
genesisPrefix = []byte("ethereum-genesis-") // genesis state prefix for the db
|
genesisPrefix = []byte("ethereum-genesis-") // genesis state prefix for the db
|
||||||
|
|
||||||
|
|
@ -173,9 +173,9 @@ func bloomBitsKey(bit uint, section uint64, hash common.Hash) []byte {
|
||||||
return key
|
return key
|
||||||
}
|
}
|
||||||
|
|
||||||
// preimageKey = preimagePrefix + hash
|
// preimageKey = PreimagePrefix + hash
|
||||||
func preimageKey(hash common.Hash) []byte {
|
func preimageKey(hash common.Hash) []byte {
|
||||||
return append(preimagePrefix, hash.Bytes()...)
|
return append(PreimagePrefix, hash.Bytes()...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// codeKey = codePrefix + hash
|
// codeKey = codePrefix + hash
|
||||||
|
|
|
||||||
|
|
@ -24,6 +24,7 @@ import (
|
||||||
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
"github.com/XinFinOrg/XDPoSChain/common/lru"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
"github.com/XinFinOrg/XDPoSChain/core/rawdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/core/types"
|
"github.com/XinFinOrg/XDPoSChain/core/types"
|
||||||
|
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||||
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
"github.com/XinFinOrg/XDPoSChain/ethdb"
|
||||||
"github.com/XinFinOrg/XDPoSChain/trie"
|
"github.com/XinFinOrg/XDPoSChain/trie"
|
||||||
"github.com/XinFinOrg/XDPoSChain/trie/trienode"
|
"github.com/XinFinOrg/XDPoSChain/trie/trienode"
|
||||||
|
|
@ -43,16 +44,16 @@ type Database interface {
|
||||||
OpenTrie(root common.Hash) (Trie, error)
|
OpenTrie(root common.Hash) (Trie, error)
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (Trie, error)
|
OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error)
|
||||||
|
|
||||||
// CopyTrie returns an independent copy of the given trie.
|
// CopyTrie returns an independent copy of the given trie.
|
||||||
CopyTrie(Trie) Trie
|
CopyTrie(Trie) Trie
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
ContractCode(addrHash, codeHash common.Hash) ([]byte, error)
|
ContractCode(address common.Address, codeHash common.Hash) ([]byte, error)
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
ContractCodeSize(addrHash, codeHash common.Hash) (int, error)
|
ContractCodeSize(address common.Address, codeHash common.Hash) (int, error)
|
||||||
|
|
||||||
// DiskDB returns the underlying key-value disk database.
|
// DiskDB returns the underlying key-value disk database.
|
||||||
DiskDB() ethdb.KeyValueStore
|
DiskDB() ethdb.KeyValueStore
|
||||||
|
|
@ -183,8 +184,8 @@ func (db *cachingDB) OpenTrie(root common.Hash) (Trie, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// OpenStorageTrie opens the storage trie of an account.
|
// OpenStorageTrie opens the storage trie of an account.
|
||||||
func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, addrHash, root common.Hash) (Trie, error) {
|
func (db *cachingDB) OpenStorageTrie(stateRoot common.Hash, address common.Address, root common.Hash) (Trie, error) {
|
||||||
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, addrHash, root), db.triedb)
|
tr, err := trie.NewStateTrie(trie.StorageTrieID(stateRoot, crypto.Keccak256Hash(address.Bytes()), root), db.triedb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -202,11 +203,12 @@ func (db *cachingDB) CopyTrie(t Trie) Trie {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCode retrieves a particular contract's code.
|
// ContractCode retrieves a particular contract's code.
|
||||||
func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error) {
|
func (db *cachingDB) ContractCode(address common.Address, codeHash common.Hash) ([]byte, error) {
|
||||||
if code, _ := db.codeCache.Get(codeHash); len(code) > 0 {
|
code, _ := db.codeCache.Get(codeHash)
|
||||||
|
if len(code) > 0 {
|
||||||
return code, nil
|
return code, nil
|
||||||
}
|
}
|
||||||
code := rawdb.ReadCode(db.disk, codeHash)
|
code = rawdb.ReadCode(db.disk, codeHash)
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
db.codeCache.Add(codeHash, code)
|
db.codeCache.Add(codeHash, code)
|
||||||
db.codeSizeCache.Add(codeHash, len(code))
|
db.codeSizeCache.Add(codeHash, len(code))
|
||||||
|
|
@ -218,11 +220,12 @@ func (db *cachingDB) ContractCode(addrHash, codeHash common.Hash) ([]byte, error
|
||||||
// ContractCodeWithPrefix retrieves a particular contract's code. If the
|
// ContractCodeWithPrefix retrieves a particular contract's code. If the
|
||||||
// code can't be found in the cache, then check the existence with **new**
|
// code can't be found in the cache, then check the existence with **new**
|
||||||
// db scheme.
|
// db scheme.
|
||||||
func (db *cachingDB) ContractCodeWithPrefix(addrHash, codeHash common.Hash) ([]byte, error) {
|
func (db *cachingDB) ContractCodeWithPrefix(address common.Address, codeHash common.Hash) ([]byte, error) {
|
||||||
if code, _ := db.codeCache.Get(codeHash); len(code) > 0 {
|
code, _ := db.codeCache.Get(codeHash)
|
||||||
|
if len(code) > 0 {
|
||||||
return code, nil
|
return code, nil
|
||||||
}
|
}
|
||||||
code := rawdb.ReadCodeWithPrefix(db.disk, codeHash)
|
code = rawdb.ReadCodeWithPrefix(db.disk, codeHash)
|
||||||
if len(code) > 0 {
|
if len(code) > 0 {
|
||||||
db.codeCache.Add(codeHash, code)
|
db.codeCache.Add(codeHash, code)
|
||||||
db.codeSizeCache.Add(codeHash, len(code))
|
db.codeSizeCache.Add(codeHash, len(code))
|
||||||
|
|
@ -232,11 +235,11 @@ func (db *cachingDB) ContractCodeWithPrefix(addrHash, codeHash common.Hash) ([]b
|
||||||
}
|
}
|
||||||
|
|
||||||
// ContractCodeSize retrieves a particular contracts code's size.
|
// ContractCodeSize retrieves a particular contracts code's size.
|
||||||
func (db *cachingDB) ContractCodeSize(addrHash, codeHash common.Hash) (int, error) {
|
func (db *cachingDB) ContractCodeSize(addr common.Address, codeHash common.Hash) (int, error) {
|
||||||
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
|
if cached, ok := db.codeSizeCache.Get(codeHash); ok {
|
||||||
return cached, nil
|
return cached, nil
|
||||||
}
|
}
|
||||||
code, err := db.ContractCode(addrHash, codeHash)
|
code, err := db.ContractCode(addr, codeHash)
|
||||||
return len(code), err
|
return len(code), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ package state
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/XinFinOrg/XDPoSChain/common"
|
"github.com/XinFinOrg/XDPoSChain/common"
|
||||||
|
|
@ -27,7 +28,8 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// nodeIterator is an iterator to traverse the entire state trie post-order,
|
// nodeIterator is an iterator to traverse the entire state trie post-order,
|
||||||
// including all of the contract code and contract state tries.
|
// including all of the contract code and contract state tries. Preimage is
|
||||||
|
// required in order to resolve the contract address.
|
||||||
type nodeIterator struct {
|
type nodeIterator struct {
|
||||||
state *StateDB // State being iterated
|
state *StateDB // State being iterated
|
||||||
|
|
||||||
|
|
@ -113,7 +115,15 @@ func (it *nodeIterator) step() error {
|
||||||
if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil {
|
if err := rlp.Decode(bytes.NewReader(it.stateIt.LeafBlob()), &account); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, common.BytesToHash(it.stateIt.LeafKey()), account.Root)
|
// Lookup the preimage of account hash
|
||||||
|
preimage := it.state.trie.GetKey(it.stateIt.LeafKey())
|
||||||
|
if preimage == nil {
|
||||||
|
return errors.New("account address is not available")
|
||||||
|
}
|
||||||
|
address := common.BytesToAddress(preimage)
|
||||||
|
|
||||||
|
// Traverse the storage slots belong to the account
|
||||||
|
dataTrie, err := it.state.db.OpenStorageTrie(it.state.originalRoot, address, account.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -126,8 +136,7 @@ func (it *nodeIterator) step() error {
|
||||||
}
|
}
|
||||||
if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
|
if !bytes.Equal(account.CodeHash, types.EmptyCodeHash.Bytes()) {
|
||||||
it.codeHash = common.BytesToHash(account.CodeHash)
|
it.codeHash = common.BytesToHash(account.CodeHash)
|
||||||
addrHash := common.BytesToHash(it.stateIt.LeafKey())
|
it.code, err = it.state.db.ContractCode(address, common.BytesToHash(account.CodeHash))
|
||||||
it.code, err = it.state.db.ContractCode(addrHash, common.BytesToHash(account.CodeHash))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("code %x: %v", account.CodeHash, err)
|
return fmt.Errorf("code %x: %v", account.CodeHash, err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -140,7 +140,7 @@ func (s *stateObject) touch() {
|
||||||
// be loaded.
|
// be loaded.
|
||||||
func (s *stateObject) getTrie() (Trie, error) {
|
func (s *stateObject) getTrie() (Trie, error) {
|
||||||
if s.trie == nil {
|
if s.trie == nil {
|
||||||
tr, err := s.db.db.OpenStorageTrie(s.db.originalRoot, s.addrHash, s.data.Root)
|
tr, err := s.db.db.OpenStorageTrie(s.db.originalRoot, s.address, s.data.Root)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
@ -376,7 +376,7 @@ func (s *stateObject) Code() []byte {
|
||||||
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
|
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
code, err := s.db.db.ContractCode(s.addrHash, common.BytesToHash(s.CodeHash()))
|
code, err := s.db.db.ContractCode(s.address, common.BytesToHash(s.CodeHash()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err))
|
s.db.setError(fmt.Errorf("can't load code hash %x: %v", s.CodeHash(), err))
|
||||||
}
|
}
|
||||||
|
|
@ -394,7 +394,7 @@ func (s *stateObject) CodeSize() int {
|
||||||
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
|
if bytes.Equal(s.CodeHash(), types.EmptyCodeHash.Bytes()) {
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
size, err := s.db.db.ContractCodeSize(s.addrHash, common.BytesToHash(s.CodeHash()))
|
size, err := s.db.db.ContractCodeSize(s.address, common.BytesToHash(s.CodeHash()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err))
|
s.db.setError(fmt.Errorf("can't load code size %x: %v", s.CodeHash(), err))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -323,7 +323,7 @@ func (s *StateDB) GetAccountInfo(addr common.Address) *AccountInfo {
|
||||||
if stateObject.code != nil {
|
if stateObject.code != nil {
|
||||||
result.CodeSize = len(stateObject.code)
|
result.CodeSize = len(stateObject.code)
|
||||||
} else {
|
} else {
|
||||||
size, err := s.db.ContractCodeSize(stateObject.addrHash, common.BytesToHash(stateObject.CodeHash()))
|
size, err := s.db.ContractCodeSize(stateObject.address, common.BytesToHash(stateObject.CodeHash()))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
s.setError(err)
|
s.setError(err)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -42,7 +42,7 @@ type testAccount struct {
|
||||||
func makeTestState() (ethdb.Database, Database, common.Hash, []*testAccount) {
|
func makeTestState() (ethdb.Database, Database, common.Hash, []*testAccount) {
|
||||||
// Create an empty state
|
// Create an empty state
|
||||||
db := rawdb.NewMemoryDatabase()
|
db := rawdb.NewMemoryDatabase()
|
||||||
sdb := NewDatabase(db)
|
sdb := NewDatabaseWithConfig(db, &trie.Config{Preimages: true})
|
||||||
state, _ := New(types.EmptyRootHash, sdb)
|
state, _ := New(types.EmptyRootHash, sdb)
|
||||||
|
|
||||||
// Fill it with some arbitrary data
|
// Fill it with some arbitrary data
|
||||||
|
|
@ -100,28 +100,9 @@ func checkStateAccounts(t *testing.T, db ethdb.Database, root common.Hash, accou
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkTrieConsistency checks that all nodes in a (sub-)trie are indeed present.
|
|
||||||
func checkTrieConsistency(db ethdb.Database, root common.Hash) error {
|
|
||||||
if v, _ := db.Get(root[:]); v == nil {
|
|
||||||
return nil // Consider a non existent state consistent.
|
|
||||||
}
|
|
||||||
trie, err := trie.New(trie.StateTrieID(root), trie.NewDatabase(db))
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
it := trie.MustNodeIterator(nil)
|
|
||||||
for it.Next(true) {
|
|
||||||
}
|
|
||||||
return it.Error()
|
|
||||||
}
|
|
||||||
|
|
||||||
// checkStateConsistency checks that all data of a state root is present.
|
// checkStateConsistency checks that all data of a state root is present.
|
||||||
func checkStateConsistency(db ethdb.Database, root common.Hash) error {
|
func checkStateConsistency(db ethdb.Database, root common.Hash) error {
|
||||||
// Create and iterate a state trie rooted in a sub-node
|
state, err := New(root, NewDatabaseWithConfig(db, &trie.Config{Preimages: true}))
|
||||||
if _, err := db.Get(root.Bytes()); err != nil {
|
|
||||||
return nil // Consider a non existent state consistent.
|
|
||||||
}
|
|
||||||
state, err := New(root, NewDatabase(db))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
@ -172,7 +153,7 @@ type stateElement struct {
|
||||||
|
|
||||||
func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool) {
|
func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool) {
|
||||||
// Create a random state to copy
|
// Create a random state to copy
|
||||||
_, srcDb, srcRoot, srcAccounts := makeTestState()
|
srcDisk, srcDb, srcRoot, srcAccounts := makeTestState()
|
||||||
if commit {
|
if commit {
|
||||||
srcDb.TrieDB().Commit(srcRoot, false)
|
srcDb.TrieDB().Commit(srcRoot, false)
|
||||||
}
|
}
|
||||||
|
|
@ -205,7 +186,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool) {
|
||||||
codeResults = make([]trie.CodeSyncResult, len(codeElements))
|
codeResults = make([]trie.CodeSyncResult, len(codeElements))
|
||||||
)
|
)
|
||||||
for i, element := range codeElements {
|
for i, element := range codeElements {
|
||||||
data, err := srcDb.ContractCode(common.Hash{}, element.code)
|
data, err := srcDb.ContractCode(common.Address{}, element.code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve contract bytecode for hash %x", element.code)
|
t.Fatalf("failed to retrieve contract bytecode for hash %x", element.code)
|
||||||
}
|
}
|
||||||
|
|
@ -275,6 +256,10 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Copy the preimages from source db in order to traverse the state.
|
||||||
|
srcDb.TrieDB().WritePreimages()
|
||||||
|
copyPreimages(srcDisk, dstDb)
|
||||||
|
|
||||||
// Cross check that the two states are in sync
|
// Cross check that the two states are in sync
|
||||||
checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
|
checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
|
||||||
}
|
}
|
||||||
|
|
@ -283,7 +268,7 @@ func testIterativeStateSync(t *testing.T, count int, commit bool, bypath bool) {
|
||||||
// partial results are returned, and the others sent only later.
|
// partial results are returned, and the others sent only later.
|
||||||
func TestIterativeDelayedStateSync(t *testing.T) {
|
func TestIterativeDelayedStateSync(t *testing.T) {
|
||||||
// Create a random state to copy
|
// Create a random state to copy
|
||||||
_, srcDb, srcRoot, srcAccounts := makeTestState()
|
srcDisk, srcDb, srcRoot, srcAccounts := makeTestState()
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
dstDb := rawdb.NewMemoryDatabase()
|
||||||
|
|
@ -313,7 +298,7 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||||
if len(codeElements) > 0 {
|
if len(codeElements) > 0 {
|
||||||
codeResults := make([]trie.CodeSyncResult, len(codeElements)/2+1)
|
codeResults := make([]trie.CodeSyncResult, len(codeElements)/2+1)
|
||||||
for i, element := range codeElements[:len(codeResults)] {
|
for i, element := range codeElements[:len(codeResults)] {
|
||||||
data, err := srcDb.ContractCode(common.Hash{}, element.code)
|
data, err := srcDb.ContractCode(common.Address{}, element.code)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve contract bytecode for %x", element.code)
|
t.Fatalf("failed to retrieve contract bytecode for %x", element.code)
|
||||||
}
|
}
|
||||||
|
|
@ -364,6 +349,10 @@ func TestIterativeDelayedStateSync(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Copy the preimages from source db in order to traverse the state.
|
||||||
|
srcDb.TrieDB().WritePreimages()
|
||||||
|
copyPreimages(srcDisk, dstDb)
|
||||||
|
|
||||||
// Cross check that the two states are in sync
|
// Cross check that the two states are in sync
|
||||||
checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
|
checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
|
||||||
}
|
}
|
||||||
|
|
@ -376,7 +365,7 @@ func TestIterativeRandomStateSyncBatched(t *testing.T) { testIterativeRandomS
|
||||||
|
|
||||||
func testIterativeRandomStateSync(t *testing.T, count int) {
|
func testIterativeRandomStateSync(t *testing.T, count int) {
|
||||||
// Create a random state to copy
|
// Create a random state to copy
|
||||||
_, srcDb, srcRoot, srcAccounts := makeTestState()
|
srcDisk, srcDb, srcRoot, srcAccounts := makeTestState()
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
dstDb := rawdb.NewMemoryDatabase()
|
||||||
|
|
@ -400,7 +389,7 @@ func testIterativeRandomStateSync(t *testing.T, count int) {
|
||||||
if len(codeQueue) > 0 {
|
if len(codeQueue) > 0 {
|
||||||
results := make([]trie.CodeSyncResult, 0, len(codeQueue))
|
results := make([]trie.CodeSyncResult, 0, len(codeQueue))
|
||||||
for hash := range codeQueue {
|
for hash := range codeQueue {
|
||||||
data, err := srcDb.ContractCode(common.Hash{}, hash)
|
data, err := srcDb.ContractCode(common.Address{}, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve node data for %x", hash)
|
t.Fatalf("failed to retrieve node data for %x", hash)
|
||||||
}
|
}
|
||||||
|
|
@ -448,6 +437,10 @@ func testIterativeRandomStateSync(t *testing.T, count int) {
|
||||||
codeQueue[hash] = struct{}{}
|
codeQueue[hash] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Copy the preimages from source db in order to traverse the state.
|
||||||
|
srcDb.TrieDB().WritePreimages()
|
||||||
|
copyPreimages(srcDisk, dstDb)
|
||||||
|
|
||||||
// Cross check that the two states are in sync
|
// Cross check that the two states are in sync
|
||||||
checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
|
checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
|
||||||
}
|
}
|
||||||
|
|
@ -456,7 +449,7 @@ func testIterativeRandomStateSync(t *testing.T, count int) {
|
||||||
// partial results are returned (Even those randomly), others sent only later.
|
// partial results are returned (Even those randomly), others sent only later.
|
||||||
func TestIterativeRandomDelayedStateSync(t *testing.T) {
|
func TestIterativeRandomDelayedStateSync(t *testing.T) {
|
||||||
// Create a random state to copy
|
// Create a random state to copy
|
||||||
_, srcDb, srcRoot, srcAccounts := makeTestState()
|
srcDisk, srcDb, srcRoot, srcAccounts := makeTestState()
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
dstDb := rawdb.NewMemoryDatabase()
|
||||||
|
|
@ -482,7 +475,7 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
|
||||||
for hash := range codeQueue {
|
for hash := range codeQueue {
|
||||||
delete(codeQueue, hash)
|
delete(codeQueue, hash)
|
||||||
|
|
||||||
data, err := srcDb.ContractCode(common.Hash{}, hash)
|
data, err := srcDb.ContractCode(common.Address{}, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve node data for %x", hash)
|
t.Fatalf("failed to retrieve node data for %x", hash)
|
||||||
}
|
}
|
||||||
|
|
@ -538,6 +531,10 @@ func TestIterativeRandomDelayedStateSync(t *testing.T) {
|
||||||
codeQueue[hash] = struct{}{}
|
codeQueue[hash] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Copy the preimages from source db in order to traverse the state.
|
||||||
|
srcDb.TrieDB().WritePreimages()
|
||||||
|
copyPreimages(srcDisk, dstDb)
|
||||||
|
|
||||||
// Cross check that the two states are in sync
|
// Cross check that the two states are in sync
|
||||||
checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
|
checkStateAccounts(t, dstDb, srcRoot, srcAccounts)
|
||||||
}
|
}
|
||||||
|
|
@ -556,7 +553,6 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
isCode[types.EmptyCodeHash] = struct{}{}
|
isCode[types.EmptyCodeHash] = struct{}{}
|
||||||
checkTrieConsistency(db, srcRoot)
|
|
||||||
|
|
||||||
// Create a destination state and sync with the scheduler
|
// Create a destination state and sync with the scheduler
|
||||||
dstDb := rawdb.NewMemoryDatabase()
|
dstDb := rawdb.NewMemoryDatabase()
|
||||||
|
|
@ -589,7 +585,7 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
if len(codeQueue) > 0 {
|
if len(codeQueue) > 0 {
|
||||||
results := make([]trie.CodeSyncResult, 0, len(codeQueue))
|
results := make([]trie.CodeSyncResult, 0, len(codeQueue))
|
||||||
for hash := range codeQueue {
|
for hash := range codeQueue {
|
||||||
data, err := srcDb.ContractCode(common.Hash{}, hash)
|
data, err := srcDb.ContractCode(common.Address{}, hash)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("failed to retrieve node data for %x", hash)
|
t.Fatalf("failed to retrieve node data for %x", hash)
|
||||||
}
|
}
|
||||||
|
|
@ -603,7 +599,6 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var nodehashes []common.Hash
|
|
||||||
if len(nodeQueue) > 0 {
|
if len(nodeQueue) > 0 {
|
||||||
results := make([]trie.NodeSyncResult, 0, len(nodeQueue))
|
results := make([]trie.NodeSyncResult, 0, len(nodeQueue))
|
||||||
for path, element := range nodeQueue {
|
for path, element := range nodeQueue {
|
||||||
|
|
@ -618,7 +613,6 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
addedPaths = append(addedPaths, element.path)
|
addedPaths = append(addedPaths, element.path)
|
||||||
addedHashes = append(addedHashes, element.hash)
|
addedHashes = append(addedHashes, element.hash)
|
||||||
}
|
}
|
||||||
nodehashes = append(nodehashes, element.hash)
|
|
||||||
}
|
}
|
||||||
// Process each of the state nodes
|
// Process each of the state nodes
|
||||||
for _, result := range results {
|
for _, result := range results {
|
||||||
|
|
@ -633,13 +627,6 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
}
|
}
|
||||||
batch.Write()
|
batch.Write()
|
||||||
|
|
||||||
for _, root := range nodehashes {
|
|
||||||
// Can't use checkStateConsistency here because subtrie keys may have odd
|
|
||||||
// length and crash in LeafKey.
|
|
||||||
if err := checkTrieConsistency(dstDb, root); err != nil {
|
|
||||||
t.Fatalf("state inconsistent: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Fetch the next batch to retrieve
|
// Fetch the next batch to retrieve
|
||||||
nodeQueue = make(map[string]stateElement)
|
nodeQueue = make(map[string]stateElement)
|
||||||
codeQueue = make(map[common.Hash]struct{})
|
codeQueue = make(map[common.Hash]struct{})
|
||||||
|
|
@ -655,6 +642,10 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
codeQueue[hash] = struct{}{}
|
codeQueue[hash] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Copy the preimages from source db in order to traverse the state.
|
||||||
|
srcDb.TrieDB().WritePreimages()
|
||||||
|
copyPreimages(db, dstDb)
|
||||||
|
|
||||||
// Sanity check that removing any node from the database is detected
|
// Sanity check that removing any node from the database is detected
|
||||||
for _, node := range addedCodes {
|
for _, node := range addedCodes {
|
||||||
val := rawdb.ReadCode(dstDb, node)
|
val := rawdb.ReadCode(dstDb, node)
|
||||||
|
|
@ -679,3 +670,15 @@ func TestIncompleteStateSync(t *testing.T) {
|
||||||
rawdb.WriteTrieNode(dstDb, owner, inner, hash, val, scheme)
|
rawdb.WriteTrieNode(dstDb, owner, inner, hash, val, scheme)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func copyPreimages(srcDb, dstDb ethdb.Database) {
|
||||||
|
it := srcDb.NewIterator(rawdb.PreimagePrefix, nil)
|
||||||
|
defer it.Release()
|
||||||
|
|
||||||
|
preimages := make(map[common.Hash][]byte)
|
||||||
|
for it.Next() {
|
||||||
|
hash := it.Key()[len(rawdb.PreimagePrefix):]
|
||||||
|
preimages[common.BytesToHash(hash)] = common.CopyBytes(it.Value())
|
||||||
|
}
|
||||||
|
rawdb.WritePreimages(dstDb, preimages)
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -182,10 +182,15 @@ func (db *Database) Scheme() string {
|
||||||
// It is meant to be called when closing the blockchain object, so that all
|
// It is meant to be called when closing the blockchain object, so that all
|
||||||
// resources held can be released correctly.
|
// resources held can be released correctly.
|
||||||
func (db *Database) Close() error {
|
func (db *Database) Close() error {
|
||||||
|
db.WritePreimages()
|
||||||
|
return db.backend.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// WritePreimages flushes all accumulated preimages to disk forcibly.
|
||||||
|
func (db *Database) WritePreimages() {
|
||||||
if db.preimages != nil {
|
if db.preimages != nil {
|
||||||
db.preimages.commit(true)
|
db.preimages.commit(true)
|
||||||
}
|
}
|
||||||
return db.backend.Close()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cap iteratively flushes old but still referenced trie nodes until the total
|
// Cap iteratively flushes old but still referenced trie nodes until the total
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue