aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPéter Szilágyi <peterke@gmail.com>2019-03-18 19:19:40 +0800
committerPéter Szilágyi <peterke@gmail.com>2019-03-18 19:19:40 +0800
commit211ec46284fecf4a4eeb8dd322a8edf9f430be95 (patch)
treee77eb74be6e1fb3335de1742835468cb8f1199c4
parent54cd3e89a4aa51f4c9e3ce73a8393f7774d52e13 (diff)
downloadgo-tangerine-211ec46284fecf4a4eeb8dd322a8edf9f430be95.tar
go-tangerine-211ec46284fecf4a4eeb8dd322a8edf9f430be95.tar.gz
go-tangerine-211ec46284fecf4a4eeb8dd322a8edf9f430be95.tar.bz2
go-tangerine-211ec46284fecf4a4eeb8dd322a8edf9f430be95.tar.lz
go-tangerine-211ec46284fecf4a4eeb8dd322a8edf9f430be95.tar.xz
go-tangerine-211ec46284fecf4a4eeb8dd322a8edf9f430be95.tar.zst
go-tangerine-211ec46284fecf4a4eeb8dd322a8edf9f430be95.zip
les, light: verbose errors on state retrieval issues
-rw-r--r--les/handler.go181
-rw-r--r--light/lightchain.go5
2 files changed, 114 insertions, 72 deletions
diff --git a/les/handler.go b/les/handler.go
index 9efe7d9e1..50c32fb95 100644
--- a/les/handler.go
+++ b/les/handler.go
@@ -72,7 +72,7 @@ type BlockChain interface {
GetHeaderByHash(hash common.Hash) *types.Header
CurrentHeader() *types.Header
GetTd(hash common.Hash, number uint64) *big.Int
- State() (*state.StateDB, error)
+ StateCache() state.Database
InsertHeaderChain(chain []*types.Header, checkFreq int) (int, error)
Rollback(chain []common.Hash)
GetHeaderByNumber(number uint64) *types.Header
@@ -642,24 +642,33 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
if i != 0 && !task.waitOrStop() {
return
}
- // Retrieve the requested state entry, stopping if enough was found
- if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil {
- if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil {
- statedb, err := pm.blockchain.State()
- if err != nil {
- continue
- }
- account, err := pm.getAccount(statedb, header.Root, common.BytesToHash(req.AccKey))
- if err != nil {
- continue
- }
- code, _ := statedb.Database().TrieDB().Node(common.BytesToHash(account.CodeHash))
+ // Look up the root hash belonging to the request
+ number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash)
+ if number == nil {
+ p.Log().Warn("Failed to retrieve block num for code", "hash", req.BHash)
+ continue
+ }
+ header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number)
+ if header == nil {
+ p.Log().Warn("Failed to retrieve header for code", "block", *number, "hash", req.BHash)
+ continue
+ }
+ triedb := pm.blockchain.StateCache().TrieDB()
- data = append(data, code)
- if bytes += len(code); bytes >= softResponseLimit {
- break
- }
- }
+ account, err := pm.getAccount(triedb, header.Root, common.BytesToHash(req.AccKey))
+ if err != nil {
+ p.Log().Warn("Failed to retrieve account for code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(req.AccKey), "err", err)
+ continue
+ }
+ code, err := triedb.Node(common.BytesToHash(account.CodeHash))
+ if err != nil {
+ p.Log().Warn("Failed to retrieve account code", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(req.AccKey), "codehash", common.BytesToHash(account.CodeHash), "err", err)
+ continue
+ }
+ // Accumulate the code and abort if enough data was retrieved
+ data = append(data, code)
+ if bytes += len(code); bytes >= softResponseLimit {
+ break
}
}
sendResponse(req.ReqID, uint64(reqCnt), p.ReplyCode(req.ReqID, data), task.done())
@@ -779,34 +788,52 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
if i != 0 && !task.waitOrStop() {
return
}
- // Retrieve the requested state entry, stopping if enough was found
- if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil {
- if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil {
- statedb, err := pm.blockchain.State()
- if err != nil {
- continue
- }
- var trie state.Trie
- if len(req.AccKey) > 0 {
- account, err := pm.getAccount(statedb, header.Root, common.BytesToHash(req.AccKey))
- if err != nil {
- continue
- }
- trie, _ = statedb.Database().OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root)
- } else {
- trie, _ = statedb.Database().OpenTrie(header.Root)
- }
- if trie != nil {
- var proof light.NodeList
- trie.Prove(req.Key, 0, &proof)
+ // Look up the root hash belonging to the request
+ number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash)
+ if number == nil {
+ p.Log().Warn("Failed to retrieve block num for proof", "hash", req.BHash)
+ continue
+ }
+ header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number)
+ if header == nil {
+ p.Log().Warn("Failed to retrieve header for proof", "block", *number, "hash", req.BHash)
+ continue
+ }
+ // Open the account or storage trie for the request
+ statedb := pm.blockchain.StateCache()
- proofs = append(proofs, proof)
- if bytes += proof.DataSize(); bytes >= softResponseLimit {
- break
- }
- }
+ var trie state.Trie
+ switch len(req.AccKey) {
+ case 0:
+ // No account key specified, open an account trie
+ trie, err = statedb.OpenTrie(header.Root)
+ if trie == nil || err != nil {
+ p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "root", header.Root, "err", err)
+ continue
+ }
+ default:
+ // Account key specified, open a storage trie
+ account, err := pm.getAccount(statedb.TrieDB(), header.Root, common.BytesToHash(req.AccKey))
+ if err != nil {
+ p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(req.AccKey), "err", err)
+ continue
+ }
+ trie, err = statedb.OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root)
+ if trie == nil || err != nil {
+ p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(req.AccKey), "root", account.Root, "err", err)
+ continue
}
}
+ // Prove the user's request from the account or stroage trie
+ var proof light.NodeList
+ if err := trie.Prove(req.Key, 0, &proof); err != nil {
+ p.Log().Warn("Failed to prove state request", "block", header.Number, "hash", header.Hash(), "err", err)
+ continue
+ }
+ proofs = append(proofs, proof)
+ if bytes += proof.DataSize(); bytes >= softResponseLimit {
+ break
+ }
}
sendResponse(req.ReqID, uint64(reqCnt), p.ReplyProofs(req.ReqID, proofs), task.done())
}()
@@ -824,7 +851,6 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
// Gather state data until the fetch or network limits is reached
var (
lastBHash common.Hash
- statedb *state.StateDB
root common.Hash
)
reqCnt := len(req.Reqs)
@@ -832,43 +858,60 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
return errResp(ErrRequestRejected, "")
}
go func() {
-
nodes := light.NewNodeSet()
for i, req := range req.Reqs {
if i != 0 && !task.waitOrStop() {
return
}
- // Look up the state belonging to the request
- if statedb == nil || req.BHash != lastBHash {
- statedb, root, lastBHash = nil, common.Hash{}, req.BHash
-
- if number := rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number != nil {
- if header := rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header != nil {
- statedb, _ = pm.blockchain.State()
- root = header.Root
- }
+ // Look up the root hash belonging to the request
+ var (
+ number *uint64
+ header *types.Header
+ trie state.Trie
+ )
+ if req.BHash != lastBHash {
+ root, lastBHash = common.Hash{}, req.BHash
+
+ if number = rawdb.ReadHeaderNumber(pm.chainDb, req.BHash); number == nil {
+ p.Log().Warn("Failed to retrieve block num for proof", "hash", req.BHash)
+ continue
}
+ if header = rawdb.ReadHeader(pm.chainDb, req.BHash, *number); header == nil {
+ p.Log().Warn("Failed to retrieve header for proof", "block", *number, "hash", req.BHash)
+ continue
+ }
+ root = header.Root
}
- if statedb == nil {
- continue
- }
- // Pull the account or storage trie of the request
- var trie state.Trie
- if len(req.AccKey) > 0 {
- account, err := pm.getAccount(statedb, root, common.BytesToHash(req.AccKey))
+ // Open the account or storage trie for the request
+ statedb := pm.blockchain.StateCache()
+
+ switch len(req.AccKey) {
+ case 0:
+ // No account key specified, open an account trie
+ trie, err = statedb.OpenTrie(root)
+ if trie == nil || err != nil {
+ p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "root", root, "err", err)
+ continue
+ }
+ default:
+ // Account key specified, open a storage trie
+ account, err := pm.getAccount(statedb.TrieDB(), root, common.BytesToHash(req.AccKey))
if err != nil {
+ p.Log().Warn("Failed to retrieve account for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(req.AccKey), "err", err)
+ continue
+ }
+ trie, err = statedb.OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root)
+ if trie == nil || err != nil {
+ p.Log().Warn("Failed to open storage trie for proof", "block", header.Number, "hash", header.Hash(), "account", common.BytesToHash(req.AccKey), "root", account.Root, "err", err)
continue
}
- trie, _ = statedb.Database().OpenStorageTrie(common.BytesToHash(req.AccKey), account.Root)
- } else {
- trie, _ = statedb.Database().OpenTrie(root)
}
- if trie == nil {
+ // Prove the user's request from the account or stroage trie
+ if err := trie.Prove(req.Key, req.FromLevel, nodes); err != nil {
+ p.Log().Warn("Failed to prove state request", "block", header.Number, "hash", header.Hash(), "err", err)
continue
}
- // Prove the user's request from the account or stroage trie
- trie.Prove(req.Key, req.FromLevel, nodes)
if nodes.DataSize() >= softResponseLimit {
break
}
@@ -1190,8 +1233,8 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
}
// getAccount retrieves an account from the state based at root.
-func (pm *ProtocolManager) getAccount(statedb *state.StateDB, root, hash common.Hash) (state.Account, error) {
- trie, err := trie.New(root, statedb.Database().TrieDB())
+func (pm *ProtocolManager) getAccount(triedb *trie.Database, root, hash common.Hash) (state.Account, error) {
+ trie, err := trie.New(root, triedb)
if err != nil {
return state.Account{}, err
}
diff --git a/light/lightchain.go b/light/lightchain.go
index fb5f8ead2..38f1f6341 100644
--- a/light/lightchain.go
+++ b/light/lightchain.go
@@ -211,9 +211,8 @@ func (lc *LightChain) Genesis() *types.Block {
return lc.genesisBlock
}
-// State returns a new mutable state based on the current HEAD block.
-func (lc *LightChain) State() (*state.StateDB, error) {
- return nil, errors.New("not implemented, needs client/server interface split")
+func (lc *LightChain) StateCache() state.Database {
+ panic("not implemented")
}
// GetBody retrieves a block body (transactions and uncles) from the database