perf: add contract info cache for spam token/nft transactions (#994)

This commit is contained in:
kevin 2023-12-08 01:22:41 -07:00 committed by GitHub
parent 0c95abe025
commit 8c2a59aa0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -36,6 +36,9 @@ type Worker struct {
metrics *common.Metrics metrics *common.Metrics
} }
// contractInfoCache is a temporary cache of contract information for ethereum token transfers
type contractInfoCache = map[string]*bchain.ContractInfo
// NewWorker creates new api worker // NewWorker creates new api worker
func NewWorker(db *db.RocksDB, chain bchain.BlockChain, mempool bchain.Mempool, txCache *db.TxCache, metrics *common.Metrics, is *common.InternalState, fiatRates *fiat.FiatRates) (*Worker, error) { func NewWorker(db *db.RocksDB, chain bchain.BlockChain, mempool bchain.Mempool, txCache *db.TxCache, metrics *common.Metrics, is *common.InternalState, fiatRates *fiat.FiatRates) (*Worker, error) {
w := &Worker{ w := &Worker{
@ -666,39 +669,49 @@ func (w *Worker) getContractDescriptorInfo(cd bchain.AddressDescriptor, typeFrom
} }
func (w *Worker) getEthereumTokensTransfers(transfers bchain.TokenTransfers, addresses map[string]struct{}) []TokenTransfer { func (w *Worker) getEthereumTokensTransfers(transfers bchain.TokenTransfers, addresses map[string]struct{}) []TokenTransfer {
sort.Sort(transfers)
tokens := make([]TokenTransfer, len(transfers)) tokens := make([]TokenTransfer, len(transfers))
for i := range transfers { if len(transfers) > 0 {
t := transfers[i] sort.Sort(transfers)
typeName := bchain.EthereumTokenTypeMap[t.Type] contractCache := make(contractInfoCache)
contractInfo, _, err := w.getContractInfo(t.Contract, typeName) for i := range transfers {
if err != nil { t := transfers[i]
glog.Errorf("getContractInfo error %v, contract %v", err, t.Contract) typeName := bchain.EthereumTokenTypeMap[t.Type]
continue var contractInfo *bchain.ContractInfo
} if info, ok := contractCache[t.Contract]; ok {
var value *Amount contractInfo = info
var values []MultiTokenValue } else {
if t.Type == bchain.MultiToken { info, _, err := w.getContractInfo(t.Contract, typeName)
values = make([]MultiTokenValue, len(t.MultiTokenValues)) if err != nil {
for j := range values { glog.Errorf("getContractInfo error %v, contract %v", err, t.Contract)
values[j].Id = (*Amount)(&t.MultiTokenValues[j].Id) continue
values[j].Value = (*Amount)(&t.MultiTokenValues[j].Value) }
contractInfo = info
contractCache[t.Contract] = info
}
var value *Amount
var values []MultiTokenValue
if t.Type == bchain.MultiToken {
values = make([]MultiTokenValue, len(t.MultiTokenValues))
for j := range values {
values[j].Id = (*Amount)(&t.MultiTokenValues[j].Id)
values[j].Value = (*Amount)(&t.MultiTokenValues[j].Value)
}
} else {
value = (*Amount)(&t.Value)
}
aggregateAddress(addresses, t.From)
aggregateAddress(addresses, t.To)
tokens[i] = TokenTransfer{
Type: typeName,
Contract: t.Contract,
From: t.From,
To: t.To,
Value: value,
MultiTokenValues: values,
Decimals: contractInfo.Decimals,
Name: contractInfo.Name,
Symbol: contractInfo.Symbol,
} }
} else {
value = (*Amount)(&t.Value)
}
aggregateAddress(addresses, t.From)
aggregateAddress(addresses, t.To)
tokens[i] = TokenTransfer{
Type: typeName,
Contract: t.Contract,
From: t.From,
To: t.To,
Value: value,
MultiTokenValues: values,
Decimals: contractInfo.Decimals,
Name: contractInfo.Name,
Symbol: contractInfo.Symbol,
} }
} }
return tokens return tokens