Skip to content

Commit

Permalink
calculate multiple times the creation block of a contract and select …
Browse files Browse the repository at this point in the history
…the lower one, use provider manager on API layer
  • Loading branch information
lucasmenendez committed Jun 20, 2024
1 parent 2030094 commit 10b2350
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 1 deletion.
2 changes: 1 addition & 1 deletion api/tokens.go
Original file line number Diff line number Diff line change
Expand Up @@ -640,7 +640,7 @@ func (capi *census3API) tokenStartBlock(msg *api.APIdata, ctx *httprouter.HTTPCo
}
log.Infow("start block calculated", "startBlock", startBlock, "tokenID", req.ID, "chainID", req.ChainID)
}()
return ctx.Send([]byte("ok"), api.HTTPstatusOK)
return ctx.Send([]byte("check the logs"), api.HTTPstatusOK)
}

func (capi *census3API) getTokenHolder(msg *api.APIdata, ctx *httprouter.HTTPContext) error {
Expand Down
15 changes: 15 additions & 0 deletions helpers/web3/web3_iter.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ type Web3Endpoint struct {
Name string `json:"name"`
ShortName string `json:"shortName"`
URI string
IsArchive bool
client *ethclient.Client
}

Expand All @@ -39,6 +40,20 @@ func NewWeb3Iterator(endpoints ...*Web3Endpoint) *Web3Iterator {
}
}

// Available returns the number of available endpoints.
func (w3pp *Web3Iterator) Available() int {
w3pp.mtx.Lock()
defer w3pp.mtx.Unlock()
return len(w3pp.available)
}

// Disabled returns the number of disabled endpoints.
func (w3pp *Web3Iterator) Disabled() int {
w3pp.mtx.Lock()
defer w3pp.mtx.Unlock()
return len(w3pp.disabled)
}

// Add adds a new endpoint to the pool, making it available for the next
// requests.
func (w3pp *Web3Iterator) Add(endpoint ...*Web3Endpoint) {
Expand Down
51 changes: 51 additions & 0 deletions helpers/web3/web3_pool.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,26 @@ import (
"context"
"encoding/json"
"fmt"
"math/big"
"net/http"
"regexp"
"strings"
"time"

"github.com/ethereum/go-ethereum/ethclient"
"go.vocdoni.io/dvote/log"
)

const (
DefaultMaxWeb3ClientRetries = 5

shortNameSourceUri = "https://chainid.network/chains_mini.json"
checkWeb3EndpointsTimeout = time.Second * 10
foundTxErrMessage = "transaction type not supported"
)

var notFoundTxRgx = regexp.MustCompile(`not\s[be\s|]*found`)

// Web3Pool struct contains a map of chainID-[]*Web3Endpoint, where
// the key is the chainID and the value is a list of Web3Endpoint. It also
// contains a list of all the Web3Endpoint metadata. It provides methods to
Expand Down Expand Up @@ -90,13 +97,19 @@ func (nm *Web3Pool) AddEndpoint(uri string) error {
if name == "" || shortName == "" {
return fmt.Errorf("no chain metadata found for chainID %d", chainID)
}
// check if the endpoint is an archive node or not
isArchive, err := isArchiveNode(ctx, client)
if err != nil {
log.Warnw("error checking if the web3 provider is an archive node", "chainID", chainID, "error", err)
}
// add the endpoint to the pool
endpoint := &Web3Endpoint{
ChainID: chainID,
Name: name,
ShortName: shortName,
URI: uri,
client: client,
IsArchive: isArchive,
}
if _, ok := nm.endpoints[chainID]; !ok {
nm.endpoints[chainID] = NewWeb3Iterator(endpoint)
Expand Down Expand Up @@ -133,6 +146,19 @@ func (nm *Web3Pool) DisableEndpoint(chainID uint64, uri string) {
}
}

// NumberOfEndpoints method returns the total number (or just the available ones)
// of endpoints for the chainID provided.
func (nm *Web3Pool) NumberOfEndpoints(chainID uint64, onlyAvailable bool) int {
if endpoints, ok := nm.endpoints[chainID]; ok {
n := endpoints.Available()
if !onlyAvailable {
n += endpoints.Disabled()
}
return n
}
return 0
}

// Client method returns a new *Client instance for the chainID provided.
// It returns an error if the endpoint is not found.
func (nm *Web3Pool) Client(chainID uint64) (*Client, error) {
Expand Down Expand Up @@ -221,3 +247,28 @@ func connect(ctx context.Context, uri string) (client *ethclient.Client, err err
}
return nil, fmt.Errorf("error dialing web3 provider uri '%s': %w", uri, err)
}

// isArchiveNode method returns true if the web3 client is an archive node. To
// determine if the client is an archive node, checks the transactions of the
// block 1 of the chain. If client finds transactions, it is an archive node. If
// it does not find transactions, it is not an archive node. If an error occurs,
// it returns false and the error.
func isArchiveNode(ctx context.Context, client *ethclient.Client) (bool, error) {
block, err := client.BlockByNumber(ctx, big.NewInt(1))
if err != nil {
if strings.Contains(err.Error(), foundTxErrMessage) {
return true, nil
}
return false, fmt.Errorf("error getting block 1: %w", err)
}
if _, err := client.TransactionInBlock(ctx, block.Hash(), 0); err != nil {
if notFoundTxRgx.MatchString(err.Error()) {
return false, nil
}
if strings.Contains(err.Error(), foundTxErrMessage) {
return true, nil
}
return false, fmt.Errorf("error getting transaction in block 1: %w", err)
}
return true, nil
}
3 changes: 3 additions & 0 deletions scanner/providers/web3/web3_provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ func creationBlock(client *web3.Client, ctx context.Context, addr common.Address
time.Sleep(RetryWeb3Cooldown)
continue
}
if creationBlock == 0 {
continue
}
if minCreationBlock == 0 || creationBlock < minCreationBlock {
minCreationBlock = creationBlock
}
Expand Down

0 comments on commit 10b2350

Please sign in to comment.