Skip to content

Commit 112f3c4

Browse files
committed
add rate limiting when fetching headers, store failed event decoding information, various smaller fixes
1 parent b372e5d commit 112f3c4

File tree

6 files changed

+172
-49
lines changed

6 files changed

+172
-49
lines changed

seth/client.go

Lines changed: 56 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -532,8 +532,6 @@ func (m *Client) TransferETHFromKey(ctx context.Context, fromKeyNum int, to stri
532532
fromKeyNum, m.Addresses[fromKeyNum].Hex(), err)
533533
}
534534

535-
ctx, sendCancel := context.WithTimeout(ctx, m.Cfg.Network.TxnTimeout.Duration())
536-
defer sendCancel()
537535
err = m.Client.SendTransaction(ctx, signedTx)
538536
if err != nil {
539537
return fmt.Errorf("failed to send transaction to network: %w\n"+
@@ -1345,12 +1343,13 @@ func (t TransactionLog) GetData() []byte {
13451343
return t.Data
13461344
}
13471345

1348-
func (m *Client) decodeContractLogs(l zerolog.Logger, logs []types.Log, allABIs []*abi.ABI) ([]DecodedTransactionLog, error) {
1346+
func (m *Client) decodeContractLogs(l zerolog.Logger, logs []types.Log, allABIs []*abi.ABI) ([]DecodedTransactionLog, []EventDecodingError, error) {
13491347
l.Trace().
13501348
Msg("Decoding events")
13511349
sigMap := buildEventSignatureMap(allABIs)
13521350

13531351
var eventsParsed []DecodedTransactionLog
1352+
var decodeErrors []EventDecodingError
13541353
for _, lo := range logs {
13551354
if len(lo.Topics) == 0 {
13561355
l.Debug().
@@ -1384,6 +1383,7 @@ func (m *Client) decodeContractLogs(l zerolog.Logger, logs []types.Log, allABIs
13841383

13851384
// Iterate over possible events with the same signature
13861385
matched := false
1386+
var decodeAttempts []ABIDecodingError
13871387
for _, evWithABI := range possibleEvents {
13881388
evSpec := evWithABI.EventSpec
13891389
contractABI := evWithABI.ContractABI
@@ -1421,19 +1421,28 @@ func (m *Client) decodeContractLogs(l zerolog.Logger, logs []types.Log, allABIs
14211421
}
14221422

14231423
// Proceed to decode the event
1424+
// Find ABI name for this contract ABI
1425+
abiName := m.findABIName(contractABI)
14241426
d := TransactionLog{lo.Topics, lo.Data}
14251427
l.Trace().
14261428
Str("Name", evSpec.RawName).
14271429
Str("Signature", evSpec.Sig).
1430+
Str("ABI", abiName).
14281431
Msg("Unpacking event")
14291432

14301433
eventsMap, topicsMap, err := decodeEventFromLog(l, *contractABI, *evSpec, d)
14311434
if err != nil {
1432-
l.Error().
1435+
l.Debug().
14331436
Err(err).
14341437
Str("Event", evSpec.Name).
1435-
Msg("Failed to decode event; skipping")
1436-
continue // Skip this event instead of returning an error
1438+
Str("ABI", abiName).
1439+
Msg("Failed to decode event; trying next ABI")
1440+
decodeAttempts = append(decodeAttempts, ABIDecodingError{
1441+
ABIName: abiName,
1442+
EventName: evSpec.Name,
1443+
Error: err.Error(),
1444+
})
1445+
continue // Try next ABI instead of giving up
14371446
}
14381447

14391448
parsedEvent := decodedLogFromMaps(&DecodedTransactionLog{}, eventsMap, topicsMap)
@@ -1455,12 +1464,36 @@ func (m *Client) decodeContractLogs(l zerolog.Logger, logs []types.Log, allABIs
14551464
}
14561465

14571466
if !matched {
1467+
// Record the decode failure
1468+
topics := make([]string, len(lo.Topics))
1469+
for i, topic := range lo.Topics {
1470+
topics[i] = topic.Hex()
1471+
}
1472+
1473+
decodeError := EventDecodingError{
1474+
Signature: eventSig,
1475+
LogIndex: lo.Index,
1476+
Address: lo.Address.Hex(),
1477+
Topics: topics,
1478+
Errors: decodeAttempts,
1479+
}
1480+
decodeErrors = append(decodeErrors, decodeError)
1481+
1482+
abiNames := make([]string, len(decodeAttempts))
1483+
for i, attempt := range decodeAttempts {
1484+
abiNames[i] = attempt.ABIName
1485+
}
1486+
14581487
l.Warn().
14591488
Str("Signature", eventSig).
1460-
Msg("No matching event with valid indexed parameter count found for log")
1489+
Uint("LogIndex", lo.Index).
1490+
Str("Address", lo.Address.Hex()).
1491+
Strs("AttemptedABIs", abiNames).
1492+
Int("FailedAttempts", len(decodeAttempts)).
1493+
Msg("Failed to decode event log")
14611494
}
14621495
}
1463-
return eventsParsed, nil
1496+
return eventsParsed, decodeErrors, nil
14641497
}
14651498

14661499
type eventWithABI struct {
@@ -1484,6 +1517,21 @@ func buildEventSignatureMap(allABIs []*abi.ABI) map[string][]*eventWithABI {
14841517
return sigMap
14851518
}
14861519

1520+
// findABIName finds the name of the ABI in the ContractStore, returns "unknown" if not found
1521+
func (m *Client) findABIName(targetABI *abi.ABI) string {
1522+
if m.ContractStore == nil {
1523+
return "unknown"
1524+
}
1525+
1526+
for name, storedABI := range m.ContractStore.ABIs {
1527+
if reflect.DeepEqual(storedABI, *targetABI) {
1528+
return strings.TrimSuffix(name, ".abi")
1529+
}
1530+
}
1531+
1532+
return "unknown"
1533+
}
1534+
14871535
// WaitUntilNoPendingTxForRootKey waits until there's no pending transaction for root key. If after timeout there are still pending transactions, it returns error.
14881536
func (m *Client) WaitUntilNoPendingTxForRootKey(timeout time.Duration) error {
14891537
return m.WaitUntilNoPendingTx(m.MustGetRootKeyAddress(), timeout)

seth/client_builder.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func NewClientBuilder() *ClientBuilder {
3232
DialTimeout: MustMakeDuration(DefaultDialTimeout),
3333
TransferGasFee: DefaultTransferGasFee,
3434
GasPriceEstimationEnabled: true,
35-
GasPriceEstimationBlocks: 200,
35+
GasPriceEstimationBlocks: 20,
3636
GasPriceEstimationTxPriority: Priority_Standard,
3737
GasPrice: DefaultGasPrice,
3838
GasFeeCap: DefaultGasFeeCap,

seth/decode.go

Lines changed: 61 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,29 @@ const (
3636
// DecodedTransaction decoded transaction
3737
type DecodedTransaction struct {
3838
CommonData
39-
Index uint `json:"index"`
40-
Hash string `json:"hash,omitempty"`
41-
Protected bool `json:"protected,omitempty"`
42-
Transaction *types.Transaction `json:"transaction,omitempty"`
43-
Receipt *types.Receipt `json:"receipt,omitempty"`
44-
Events []DecodedTransactionLog `json:"events,omitempty"`
39+
Index uint `json:"index"`
40+
Hash string `json:"hash,omitempty"`
41+
Protected bool `json:"protected,omitempty"`
42+
Transaction *types.Transaction `json:"transaction,omitempty"`
43+
Receipt *types.Receipt `json:"receipt,omitempty"`
44+
Events []DecodedTransactionLog `json:"events,omitempty"`
45+
EventDecodingErrors []EventDecodingError `json:"event_decoding_errors,omitempty"`
46+
}
47+
48+
// EventDecodingError represents a failed event decode attempt
49+
type EventDecodingError struct {
50+
Signature string `json:"signature"`
51+
LogIndex uint `json:"log_index"`
52+
Address string `json:"address"`
53+
Topics []string `json:"topics,omitempty"`
54+
Errors []ABIDecodingError `json:"errors,omitempty"`
55+
}
56+
57+
// ABIDecodingError represents a single ABI decode attempt failure
58+
type ABIDecodingError struct {
59+
ABIName string `json:"abi_name"`
60+
EventName string `json:"event_name"`
61+
Error string `json:"error"`
4562
}
4663

4764
type CommonData struct {
@@ -448,6 +465,7 @@ func (m *Client) decodeTransaction(l zerolog.Logger, tx *types.Transaction, rece
448465
}
449466

450467
var txIndex uint
468+
var decodeErrors []EventDecodingError
451469

452470
if receipt != nil {
453471
l.Trace().Interface("Receipt", receipt).Msg("TX receipt")
@@ -463,7 +481,8 @@ func (m *Client) decodeTransaction(l zerolog.Logger, tx *types.Transaction, rece
463481
allABIs = m.ContractStore.GetAllABIs()
464482
}
465483

466-
txEvents, err = m.decodeContractLogs(l, logsValues, allABIs)
484+
var err error
485+
txEvents, decodeErrors, err = m.decodeContractLogs(l, logsValues, allABIs)
467486
if err != nil {
468487
return defaultTxn, err
469488
}
@@ -475,12 +494,13 @@ func (m *Client) decodeTransaction(l zerolog.Logger, tx *types.Transaction, rece
475494
Method: abiResult.Method.Sig,
476495
Input: txInput,
477496
},
478-
Index: txIndex,
479-
Receipt: receipt,
480-
Transaction: tx,
481-
Protected: tx.Protected(),
482-
Hash: tx.Hash().String(),
483-
Events: txEvents,
497+
Index: txIndex,
498+
Receipt: receipt,
499+
Transaction: tx,
500+
Protected: tx.Protected(),
501+
Hash: tx.Hash().String(),
502+
Events: txEvents,
503+
EventDecodingErrors: decodeErrors,
484504
}
485505

486506
return ptx, nil
@@ -499,7 +519,34 @@ func (m *Client) printDecodedTXData(l zerolog.Logger, ptx *DecodedTransaction) {
499519
for _, e := range ptx.Events {
500520
l.Debug().
501521
Str("Signature", e.Signature).
502-
Interface("Log", e.EventData).Send()
522+
Str("Address", e.Address.Hex()).
523+
Interface("Topics", e.Topics).
524+
Interface("Data", e.EventData).
525+
Msg("Event emitted")
526+
}
527+
528+
// Print event decoding errors separately
529+
if len(ptx.EventDecodingErrors) > 0 {
530+
l.Warn().
531+
Int("Failed event decodes", len(ptx.EventDecodingErrors)).
532+
Msg("Some events could not be decoded")
533+
534+
for _, decodeErr := range ptx.EventDecodingErrors {
535+
abiNames := make([]string, len(decodeErr.Errors))
536+
errorMsgs := make([]string, len(decodeErr.Errors))
537+
for i, abiErr := range decodeErr.Errors {
538+
abiNames[i] = abiErr.ABIName
539+
errorMsgs[i] = fmt.Sprintf("%s.%s: %s", abiErr.ABIName, abiErr.EventName, abiErr.Error)
540+
}
541+
542+
l.Warn().
543+
Str("Signature", decodeErr.Signature).
544+
Uint("LogIndex", decodeErr.LogIndex).
545+
Str("Address", decodeErr.Address).
546+
Strs("AttemptedABIs", abiNames).
547+
Strs("Errors", errorMsgs).
548+
Msg("Failed to decode event log")
549+
}
503550
}
504551
}
505552

seth/gas_adjuster.go

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package seth
22

33
import (
44
"context"
5+
"errors"
56
"fmt"
67
"math"
78
"math/big"
@@ -12,6 +13,7 @@ import (
1213

1314
"github.com/avast/retry-go"
1415
"github.com/ethereum/go-ethereum/core/types"
16+
"go.uber.org/ratelimit"
1517
)
1618

1719
const (
@@ -56,7 +58,7 @@ func (m *Client) CalculateNetworkCongestionMetric(blocksNumber uint64, strategy
5658
return cachedHeader, nil
5759
}
5860

59-
timeout := blocksNumber / 100
61+
timeout := blocksNumber / 10
6062
if timeout < 3 {
6163
timeout = 3
6264
} else if timeout > 6 {
@@ -94,7 +96,9 @@ func (m *Client) CalculateNetworkCongestionMetric(blocksNumber uint64, strategy
9496
var wg sync.WaitGroup
9597
dataCh := make(chan *types.Header)
9698

99+
limit := ratelimit.New(4) // 4 concurrent requests
97100
go func() {
101+
limit.Take()
98102
for header := range dataCh {
99103
headers = append(headers, header)
100104
// placed here, because we want to wait for all headers to be received and added to slice before continuing
@@ -262,6 +266,7 @@ func (m *Client) GetSuggestedEIP1559Fees(ctx context.Context, priority string) (
262266
Float64("BaseFee", baseFee64).
263267
Int64("SuggestedTip", currentGasTip.Int64()).
264268
Msgf("Incorrect gas data received from node: base fee was 0. Skipping gas estimation")
269+
err = errors.New("incorrect gas data received from node: base fee was 0. Skipping gas estimation")
265270
return
266271
}
267272

@@ -734,16 +739,18 @@ func calculateGasUsedRatio(headers []*types.Header) float64 {
734739
return 0
735740
}
736741

737-
var totalRatio float64
742+
var totalGasUsedRatio float64
743+
validHeaders := 0
738744
for _, header := range headers {
739-
if header.GasLimit == 0 {
740-
continue
745+
if header.GasLimit > 0 {
746+
totalGasUsedRatio += float64(header.GasUsed) / float64(header.GasLimit)
747+
validHeaders++
741748
}
742-
ratio := float64(header.GasUsed) / float64(header.GasLimit)
743-
totalRatio += ratio
744749
}
745-
averageRatio := totalRatio / float64(len(headers))
746-
return averageRatio
750+
if validHeaders == 0 {
751+
return 0.0
752+
}
753+
return totalGasUsedRatio / float64(validHeaders)
747754
}
748755

749756
func calculateMagnitudeDifference(first, second *big.Float) (int, string) {

seth/nonce.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ func (m *NonceManager) UpdateNonces() error {
107107
for addr := range m.Nonces {
108108
nonce, err := m.Client.Client.NonceAt(context.Background(), addr, nil)
109109
if err != nil {
110-
return err
110+
return fmt.Errorf("failed to updated nonces for address '%s': %w", addr, err)
111111
}
112112
m.Nonces[addr] = mustSafeInt64(nonce)
113113
}

0 commit comments

Comments
 (0)