Skip to content

Commit

Permalink
address comments
Browse files Browse the repository at this point in the history
  • Loading branch information
Andrew7234 committed Nov 28, 2023
1 parent eaed488 commit 45fad28
Show file tree
Hide file tree
Showing 2 changed files with 108 additions and 52 deletions.
74 changes: 62 additions & 12 deletions analyzer/evmabibackfill/evm_abi_backfill.go
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,15 @@ func (p *processor) ProcessItem(ctx context.Context, batch *storage.QueryBatch,
if item.Event != nil {

Check failure on line 138 in analyzer/evmabibackfill/evm_abi_backfill.go

View workflow job for this annotation

GitHub Actions / lint-go

`if item.Event != nil` has complex nested blocks (complexity: 9) (nestif)
abiEvent, abiEventArgs, err := abiparse.ParseEvent(item.Event.EventBody.Topics, item.Event.EventBody.Data, &contractAbi)
if err != nil {
return fmt.Errorf("error processing event using abi for contract %s: %w", item.ContractAddr, err)
queueIncompatibleEventUpdate(batch, p.runtime, item.Event.Round, item.Event.TxIndex)
p.logger.Warn("error processing event using abi", "contract address", item.ContractAddr, "err", err)
return nil
}
eventArgs, err := marshalArgs(abiEvent.Inputs, abiEventArgs)
if err != nil {
return fmt.Errorf("error processing event args for contract %s: %w", item.ContractAddr, err)
queueIncompatibleEventUpdate(batch, p.runtime, item.Event.Round, item.Event.TxIndex)
p.logger.Warn("error processing event args using abi", "contract address", item.ContractAddr, "err", err)
return nil
}

batch.Queue(
Expand All @@ -157,15 +161,26 @@ func (p *processor) ProcessItem(ctx context.Context, batch *storage.QueryBatch,
} else if item.Tx != nil {
method, args, err := abiparse.ParseData(item.Tx.TxData, &contractAbi)
if err != nil {
return fmt.Errorf("error processing tx using abi for contract %s: %w", item.ContractAddr, err)
queueIncompatibleTxUpdate(batch, p.runtime, item.Tx.TxHash)
p.logger.Warn("error processing tx using abi", "contract address", item.ContractAddr, "err", err)
return nil
}
abiErr, abiErrArgs, err := abiparse.ParseError(*item.Tx.TxRevertReason, &contractAbi)
if err != nil {
return fmt.Errorf("error processing tx error for contract %s: %w", item.ContractAddr, err)
}
errArgs, err := marshalArgs(abiErr.Inputs, abiErrArgs)
if err != nil {
return fmt.Errorf("error processing tx error args for contract %s: %w", item.ContractAddr, err)
var abiErr *abi.Error
var abiErrArgs []interface{}
var errArgs []byte
if item.Tx.TxRevertReason != nil {
abiErr, abiErrArgs, err = abiparse.ParseError(*item.Tx.TxRevertReason, &contractAbi)
if err != nil || abiErr == nil {
queueIncompatibleTxUpdate(batch, p.runtime, item.Tx.TxHash)
p.logger.Warn("error processing tx error using abi", "contract address", item.ContractAddr, "err", err)
return nil
}
errArgs, err = marshalArgs(abiErr.Inputs, abiErrArgs)
if err != nil {
queueIncompatibleTxUpdate(batch, p.runtime, item.Tx.TxHash)
p.logger.Warn("error processing tx error args", "contract address", item.ContractAddr, "err", err)
return nil
}
}
batch.Queue(
queries.RuntimeTransactionUpdate,
Expand All @@ -181,6 +196,40 @@ func (p *processor) ProcessItem(ctx context.Context, batch *storage.QueryBatch,
return nil
}

// If abi processing of an event fails, it is likely due to incompatible
// data+abi, which is the event's fault. We thus mark the incompatible
// event as processed and continue.
//
// Note that if the abi is ever updated, we may need to revisit these events.
func queueIncompatibleEventUpdate(batch *storage.QueryBatch, runtime common.Runtime, round uint64, txIndex *int) {
batch.Queue(
queries.RuntimeEventUpdate,
runtime,
round,
txIndex,
nil, // event name
nil, // event args
nil, // event signature
)
}

// If abi processing of an transaction fails, it is likely due to incompatible
// data+abi, which is the transaction's fault. We thus mark the incompatible
// transaction as processed and continue.
//
// Note that if the abi is ever updated, we may need to revisit these txs.
func queueIncompatibleTxUpdate(batch *storage.QueryBatch, runtime common.Runtime, txHash string) {
batch.Queue(
queries.RuntimeTransactionUpdate,
runtime,
txHash,
nil, // method name
nil, // method args
nil, // error name
nil, // error args
)
}

func marshalArgs(abiArgs abi.Arguments, argVals []interface{}) ([]byte, error) {
if len(abiArgs) != len(argVals) {
return nil, fmt.Errorf("number of args does not match abi specification")
Expand All @@ -203,11 +252,12 @@ func marshalArgs(abiArgs abi.Arguments, argVals []interface{}) ([]byte, error) {

func (p *processor) QueueLength(ctx context.Context) (int, error) {
var txQueueLength int
if err := p.target.QueryRow(ctx, queries.RuntimeEvmVerifiedContractTxsCount).Scan(&txQueueLength); err != nil {
if err := p.target.QueryRow(ctx, queries.RuntimeEvmVerifiedContractTxsCount, p.runtime).Scan(&txQueueLength); err != nil {
return 0, fmt.Errorf("querying number of verified abi txs: %w", err)
}
var evQueueLength int
if err := p.target.QueryRow(ctx, queries.RuntimeEvmVerifiedContractEventsCount).Scan(&evQueueLength); err != nil {
// We limit the event count for performance reasons since the query requires a join of the transactions and events tables.
if err := p.target.QueryRow(ctx, queries.RuntimeEvmVerifiedContractEventsCount, p.runtime, 1000).Scan(&evQueueLength); err != nil {
return 0, fmt.Errorf("querying number of verified abi events: %w", err)
}
return txQueueLength + evQueueLength, nil
Expand Down
86 changes: 46 additions & 40 deletions analyzer/queries/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -885,22 +885,23 @@ var (
abi
FROM chain.evm_contracts
WHERE
runtime = $1 AND verification_info_downloaded_at IS NOT NULL
runtime = $1 AND abi IS NOT NULL
)
SELECT
abi_contracts.addr,
abi_contracts.abi,
txs.tx_hash,
txs.body->'data',
txs.error_message_raw,
txs.error_message_raw
FROM abi_contracts
JOIN chain.runtime_transactions as txs ON
txs.runtime = abi_contracts.runtime AND
txs.to = abi_contracts.addr AND
txs.method = 'evm.Call' -- note: does not include evm.Create txs
txs.method = 'evm.Call' -- note: does not include evm.Create txs; their payload is never encrypted.
WHERE
runtime = $1 AND
processed_at IS NULL
body IS NOT NULL AND
error_message_raw != '' AND
abi_parsed_at IS NULL
ORDER BY addr
LIMIT $2`

Expand All @@ -911,69 +912,74 @@ var (
contract_address AS addr
FROM chain.evm_contracts
WHERE
runtime = $1 AND verification_info_downloaded_at IS NOT NULL
runtime = $1 AND abi IS NOT NULL
)
SELECT COUNT(*)
FROM abi_contracts
JOIN chain.runtime_transactions as txs ON
txs.runtime = abi_contracts.runtime AND
txs.to = abi_contracts.addr AND
txs.method = 'evm.Call' -- note: does not include evm.Create txs
txs.method = 'evm.Call' -- note: does not include evm.Create txs; their payload is never encrypted.
WHERE
runtime = $1 AND -- todo: redundant; confirm that it does not improve performance and remove
processed_at IS NULL`
body IS NOT NULL AND
error_message_raw != '' AND
abi_parsed_at IS NULL`

RuntimeEvmVerifiedContractEvents = `
WITH contracts AS (
WITH abi_contracts AS (
SELECT
runtime,
contract_address AS addr,
abi
FROM chain.evm_contracts
WHERE
runtime = $1 AND
verification_info_downloaded_at IS NOT NULL
abi IS NOT NULL
)
SELECT
contracts.addr,
contracts.abi,
abi_contracts.addr,
abi_contracts.abi,
txs.round,
txs.tx_index,
evs.body,
FROM contracts
evs.body
FROM abi_contracts
JOIN chain.runtime_transactions as txs ON
txs.runtime = contracts.runtime AND
txs.to = contracts.addr AND
txs.runtime = abi_contracts.runtime AND
txs.to = abi_contracts.addr AND
txs.method = 'evm.Call'
JOIN chain.runtime_events as evs ON
evs.runtime = contracts.runtime AND
evs.round = txs.round AND
evs.tx_index = txs.tx_index
evs.runtime = abi_contracts.runtime AND
evs.tx_hash = txs.tx_hash
WHERE
evs.processed_at IS NULL
evs.abi_parsed_at IS NULL
ORDER BY addr
LIMIT $2`

RuntimeEvmVerifiedContractEventsCount = `
WITH contracts AS (
SELECT
runtime,
contract_address AS addr
FROM chain.evm_contracts
WITH abi_contracts AS (
SELECT
runtime,
contract_address AS addr
FROM chain.evm_contracts
WHERE
runtime = $1 AND
abi IS NOT NULL
),
abi_events AS (
SELECT txs.tx_hash
FROM abi_contracts
JOIN chain.runtime_transactions as txs ON
txs.runtime = abi_contracts.runtime AND
txs.to = abi_contracts.addr AND
txs.method = 'evm.Call'
JOIN chain.runtime_events as evs ON
evs.runtime = abi_contracts.runtime AND
evs.tx_hash = txs.tx_hash
WHERE
runtime = $1 AND
verification_info_downloaded_at IS NOT NULL
evs.abi_parsed_at IS NULL
LIMIT $2 -- limit count for performance reasons
)
SELECT COUNT(*)
FROM contracts
JOIN chain.runtime_transactions as txs ON
txs.runtime = contracts.runtime AND
txs.to = contracts.addr AND
txs.method = 'evm.Call'
JOIN chain.runtime_events as evs ON
evs.runtime = contracts.runtime AND
evs.round = txs.round AND
evs.tx_index = txs.tx_index
WHERE
evs.processed_at IS NULL`
SELECT
COUNT(*)
FROM abi_events;`
)

0 comments on commit 45fad28

Please sign in to comment.