-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Alok
committed
Apr 25, 2024
1 parent
8dfb478
commit f799a76
Showing
3 changed files
with
646 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,129 @@ | ||
package txmonitor | ||
|
||
import ( | ||
"context" | ||
|
||
"github.com/ethereum/go-ethereum/common" | ||
"github.com/ethereum/go-ethereum/core/types" | ||
"github.com/ethereum/go-ethereum/rpc" | ||
) | ||
|
||
// StructLog represents a single operation (op code) executed during | ||
// a transaction. It is part of the execution trace and provides detailed | ||
// information about each step of the transaction execution. | ||
type StructLog struct { | ||
// Pc indicates the program counter at the point of execution. | ||
Pc uint64 `json:"pc,omitempty"` | ||
// Op is the name of the opcode that was executed. | ||
Op string `json:"op,omitempty"` | ||
// Gas represents the gas available at this step of execution. | ||
Gas uint64 `json:"gas,omitempty"` | ||
// GasCost is the amount of gas used by this operation. | ||
GasCost uint64 `json:"gasCost,omitempty"` | ||
// Depth indicates the call depth of the current operation. | ||
Depth int `json:"depth,omitempty"` | ||
// Error reports any exceptions or errors encountered during the | ||
// execution of the corresponding operation (op code) in the EVM. | ||
Error string `json:"error,omitempty"` | ||
// Stack is the state of the EVM stack at this point of execution. | ||
Stack []string `json:"stack,omitempty"` | ||
// Memory represents the contents of the EVM memory at this point. | ||
Memory []string `json:"memory,omitempty"` | ||
// Storage is a map representing the contract storage state after this | ||
// operation. The keys are storage slots and the values are the data | ||
// stored at those slots. | ||
Storage map[string]string `json:"storage,omitempty"` | ||
} | ||
|
||
// TransactionTrace encapsulates the result of tracing an Ethereum transaction, | ||
// providing a high-level overview of the transaction's execution and its | ||
// effects on the EVM state. | ||
type TransactionTrace struct { | ||
// Failed indicates whether the transaction was successful. | ||
Failed bool `json:"failed,omitempty"` | ||
// Gas indicates the total gas used by the transaction. | ||
Gas uint64 `json:"gas,omitempty"` | ||
// ReturnValue is the data returned by the transaction if it was a call | ||
// to a contract. | ||
ReturnValue string `json:"returnValue,omitempty"` | ||
// StructLogs is a slice of StructLog entries, each representing a step | ||
// in the transaction's execution. These logs provide a detailed trace | ||
// of the EVM operations, allowing for deep inspection of transaction | ||
// behavior. | ||
StructLogs []StructLog `json:"structLogs,omitempty"` | ||
} | ||
|
||
// Debugger defines an interface for EVM debugging tools. | ||
type Debugger interface { | ||
// TraceTransaction takes a transaction hash and returns | ||
// a detailed trace of the transaction's execution. | ||
TraceTransaction(ctx context.Context, txHash common.Hash) (*TransactionTrace, error) | ||
} | ||
|
||
// Result represents the result of a transaction receipt retrieval operation. | ||
type Result struct { | ||
// Receipt is the transaction receipt. | ||
Receipt *types.Receipt | ||
// Err is the error encountered during the operation. | ||
Err error | ||
} | ||
|
||
// BatchReceiptGetter is an interface for retrieving multiple receipts | ||
type BatchReceiptGetter interface { | ||
// BatchReceipts retrieves multiple receipts for a list of transaction hashes. | ||
BatchReceipts(ctx context.Context, txHashes []common.Hash) ([]Result, error) | ||
} | ||
|
||
type evmHelper struct { | ||
client *rpc.Client | ||
} | ||
|
||
// NewEVMHelper creates a new EVMHelper instance. | ||
func NewEVMHelper(client *rpc.Client) *evmHelper { | ||
return &evmHelper{client} | ||
} | ||
|
||
// TraceTransaction implements Debugger.TraceTransaction interface. | ||
func (e *evmHelper) TraceTransaction(ctx context.Context, txHash common.Hash) (*TransactionTrace, error) { | ||
result := new(TransactionTrace) | ||
traceOptions := map[string]interface{}{} // Empty map for default options. | ||
if err := e.client.CallContext( | ||
ctx, | ||
result, | ||
"debug_traceTransaction", | ||
txHash, | ||
traceOptions, | ||
); err != nil { | ||
return nil, err | ||
} | ||
return result, nil | ||
} | ||
|
||
// BatchReceipts retrieves multiple receipts for a list of transaction hashes. | ||
func (e *evmHelper) BatchReceipts(ctx context.Context, txHashes []common.Hash) ([]Result, error) { | ||
batch := make([]rpc.BatchElem, len(txHashes)) | ||
|
||
for i, hash := range txHashes { | ||
batch[i] = rpc.BatchElem{ | ||
Method: "eth_getTransactionReceipt", | ||
Args: []interface{}{hash}, | ||
Result: new(types.Receipt), | ||
} | ||
} | ||
|
||
// Execute the batch request | ||
err := e.client.BatchCallContext(ctx, batch) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
receipts := make([]Result, len(batch)) | ||
for i, elem := range batch { | ||
receipts[i].Receipt = elem.Result.(*types.Receipt) | ||
if elem.Error != nil { | ||
receipts[i].Err = elem.Error | ||
} | ||
} | ||
|
||
return receipts, nil | ||
} |
Oops, something went wrong.