[wallet] Detect non archival RPC node
This commit is contained in:
parent
2427b3c0a5
commit
d8bccaff18
|
@ -56,7 +56,15 @@ func (api *API) GetTransfersByAddress(ctx context.Context, address common.Addres
|
|||
|
||||
from, err := findFirstRange(ctx, address, block, api.s.client)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
if nonArchivalNodeError(err) {
|
||||
api.s.feed.Send(Event{
|
||||
Type: EventNonArchivalNodeDetected,
|
||||
})
|
||||
from = big.NewInt(0).Sub(block, big.NewInt(100))
|
||||
} else {
|
||||
log.Error("first range error", "error", err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
fromByAddress := map[common.Address]*big.Int{address: from}
|
||||
toByAddress := map[common.Address]*big.Int{address: block}
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"math/big"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
|
@ -24,6 +25,7 @@ type ethHistoricalCommand struct {
|
|||
balanceCache *balanceCache
|
||||
feed *event.Feed
|
||||
foundHeaders []*DBHeader
|
||||
error error
|
||||
noLimit bool
|
||||
|
||||
from, to, resultingFrom *big.Int
|
||||
|
@ -43,7 +45,8 @@ func (c *ethHistoricalCommand) Run(ctx context.Context) (err error) {
|
|||
from, headers, err := findBlocksWithEthTransfers(ctx, c.client, c.balanceCache, c.eth, c.address, c.from, c.to, c.noLimit)
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
c.error = err
|
||||
return nil
|
||||
}
|
||||
|
||||
c.foundHeaders = headers
|
||||
|
@ -442,16 +445,17 @@ func (c *newBlocksTransfersCommand) getTransfers(parent context.Context, header
|
|||
// - runs fast indexing for each account separately
|
||||
// - starts listening to new blocks and watches for reorgs
|
||||
type controlCommand struct {
|
||||
accounts []common.Address
|
||||
db *Database
|
||||
eth *ETHTransferDownloader
|
||||
erc20 *ERC20TransfersDownloader
|
||||
chain *big.Int
|
||||
client *ethclient.Client
|
||||
feed *event.Feed
|
||||
safetyDepth *big.Int
|
||||
watchNewBlocks bool
|
||||
errorsCount int
|
||||
accounts []common.Address
|
||||
db *Database
|
||||
eth *ETHTransferDownloader
|
||||
erc20 *ERC20TransfersDownloader
|
||||
chain *big.Int
|
||||
client *ethclient.Client
|
||||
feed *event.Feed
|
||||
safetyDepth *big.Int
|
||||
watchNewBlocks bool
|
||||
errorsCount int
|
||||
nonArchivalRPCNode bool
|
||||
}
|
||||
|
||||
// run fast indexing for every accont up to canonical chain head minus safety depth.
|
||||
|
@ -488,6 +492,9 @@ func (c *findAndCheckBlockRangeCommand) fastIndex(ctx context.Context, bCache *b
|
|||
resultingFromByAddress := map[common.Address]*big.Int{}
|
||||
headers := map[common.Address][]*DBHeader{}
|
||||
for _, command := range commands {
|
||||
if command.error != nil {
|
||||
return nil, nil, command.error
|
||||
}
|
||||
resultingFromByAddress[command.address] = command.resultingFrom
|
||||
headers[command.address] = command.foundHeaders
|
||||
}
|
||||
|
@ -730,12 +737,16 @@ func (c *controlCommand) Run(parent context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
fromMap, err := findFirstRanges(parent, accountsWithoutHistory, head.Number, c.client)
|
||||
if err != nil {
|
||||
if c.NewError(err) {
|
||||
return nil
|
||||
fromMap := map[common.Address]*big.Int{}
|
||||
|
||||
if !c.nonArchivalRPCNode {
|
||||
fromMap, err = findFirstRanges(parent, accountsWithoutHistory, head.Number, c.client)
|
||||
if err != nil {
|
||||
if c.NewError(err) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
target := new(big.Int).Sub(head.Number, c.safetyDepth)
|
||||
|
@ -751,6 +762,9 @@ func (c *controlCommand) Run(parent context.Context) error {
|
|||
if !ok {
|
||||
from = fromMap[address]
|
||||
}
|
||||
if c.nonArchivalRPCNode {
|
||||
from = big.NewInt(0).Sub(target, big.NewInt(100))
|
||||
}
|
||||
|
||||
fromByAddress[address] = from
|
||||
toByAddress[address] = target
|
||||
|
@ -776,6 +790,13 @@ func (c *controlCommand) Run(parent context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
if cmnd.error != nil {
|
||||
if c.NewError(cmnd.error) {
|
||||
return nil
|
||||
}
|
||||
return cmnd.error
|
||||
}
|
||||
|
||||
downloader := ÐTransferDownloader{
|
||||
client: c.client,
|
||||
accounts: c.accounts,
|
||||
|
@ -852,9 +873,21 @@ func (c *controlCommand) Run(parent context.Context) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func nonArchivalNodeError(err error) bool {
|
||||
return strings.Contains(err.Error(), "missing trie node") ||
|
||||
strings.Contains(err.Error(), "project ID does not have access to archive state")
|
||||
}
|
||||
|
||||
func (c *controlCommand) NewError(err error) bool {
|
||||
c.errorsCount++
|
||||
log.Error("controlCommand error", "error", err, "counter", c.errorsCount)
|
||||
if nonArchivalNodeError(err) {
|
||||
log.Info("Non archival node detected")
|
||||
c.nonArchivalRPCNode = true
|
||||
c.feed.Send(Event{
|
||||
Type: EventNonArchivalNodeDetected,
|
||||
})
|
||||
}
|
||||
if c.errorsCount >= 3 {
|
||||
c.feed.Send(Event{
|
||||
Type: EventFetchingHistoryError,
|
||||
|
@ -994,6 +1027,7 @@ type findAndCheckBlockRangeCommand struct {
|
|||
toByAddress map[common.Address]*big.Int
|
||||
foundHeaders map[common.Address][]*DBHeader
|
||||
noLimit bool
|
||||
error error
|
||||
}
|
||||
|
||||
func (c *findAndCheckBlockRangeCommand) Command() Command {
|
||||
|
@ -1007,7 +1041,8 @@ func (c *findAndCheckBlockRangeCommand) Run(parent context.Context) (err error)
|
|||
log.Debug("start findAndCHeckBlockRangeCommand")
|
||||
newFromByAddress, ethHeadersByAddress, err := c.fastIndex(parent, c.balanceCache, c.fromByAddress, c.toByAddress)
|
||||
if err != nil {
|
||||
return err
|
||||
c.error = err
|
||||
return nil
|
||||
}
|
||||
if c.noLimit {
|
||||
newFromByAddress = map[common.Address]*big.Int{}
|
||||
|
|
|
@ -23,6 +23,8 @@ const (
|
|||
EventRecentHistoryReady EventType = "recent-history-ready"
|
||||
// EventRecentHistoryError emitted when fetching of tx history failed
|
||||
EventFetchingHistoryError EventType = "fetching-history-error"
|
||||
// EventNonArchivalNodeDetected emitted when a connection to a non archival node is detected
|
||||
EventNonArchivalNodeDetected EventType = "non-archival-node-detected"
|
||||
)
|
||||
|
||||
// Event is a type for wallet events.
|
||||
|
|
Loading…
Reference in New Issue