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
}
// contractInfoCache is a temporary cache of contract information for ethereum token transfers
type contractInfoCache = map[string]*bchain.ContractInfo
// 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) {
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 {
sort.Sort(transfers)
tokens := make([]TokenTransfer, len(transfers))
for i := range transfers {
t := transfers[i]
typeName := bchain.EthereumTokenTypeMap[t.Type]
contractInfo, _, err := w.getContractInfo(t.Contract, typeName)
if err != nil {
glog.Errorf("getContractInfo error %v, contract %v", err, t.Contract)
continue
}
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)
if len(transfers) > 0 {
sort.Sort(transfers)
contractCache := make(contractInfoCache)
for i := range transfers {
t := transfers[i]
typeName := bchain.EthereumTokenTypeMap[t.Type]
var contractInfo *bchain.ContractInfo
if info, ok := contractCache[t.Contract]; ok {
contractInfo = info
} else {
info, _, err := w.getContractInfo(t.Contract, typeName)
if err != nil {
glog.Errorf("getContractInfo error %v, contract %v", err, t.Contract)
continue
}
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