Skip to content

Commit

Permalink
(BIDS-2584) add table columns, show failed transactions (#2784)
Browse files Browse the repository at this point in the history
* (BIDS-2584) add table columns, show failed transactions

* (BIDS-2584) (BIDS-2636) use data from EL node

* (BIDS-2584) filter txn overview

* (BIDS-2584) added advanced filter to internal transactions
  • Loading branch information
remoterami authored Feb 2, 2024
1 parent 7162bbf commit ae296a7
Show file tree
Hide file tree
Showing 5 changed files with 129 additions and 93 deletions.
138 changes: 68 additions & 70 deletions db/bigtable_eth1.go
Original file line number Diff line number Diff line change
Expand Up @@ -2450,6 +2450,11 @@ func (bigtable *Bigtable) GetAddressInternalTableData(address []byte, pageToken
fromName := names[string(t.From)]
toName := names[string(t.To)]

if t.Type == "suicide" {
// erigon's "suicide" might be misleading for users
t.Type = "selfdestruct"
}

tableData[i] = []interface{}{
utils.FormatTransactionHash(t.ParentHash, true),
utils.FormatBlockNumber(t.BlockNumber),
Expand All @@ -2470,86 +2475,79 @@ func (bigtable *Bigtable) GetAddressInternalTableData(address []byte, pageToken
return data, nil
}

func (bigtable *Bigtable) GetInternalTransfersForTransaction(transaction []byte, from []byte) ([]types.Transfer, error) {

tmr := time.AfterFunc(REPORT_TIMEOUT, func() {
logger.WithFields(logrus.Fields{
"transaction": transaction,
"from": from,
}).Warnf("%s call took longer than %v", utils.GetCurrentFuncName(), REPORT_TIMEOUT)
})
defer tmr.Stop()

ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Second*30))
defer cancel()

transfers := map[int]*types.Eth1InternalTransactionIndexed{}
mux := sync.Mutex{}

prefix := fmt.Sprintf("%s:ITX:%x:", bigtable.chainId, transaction)
rowRange := gcp_bigtable.NewRange(prefix+"\x00", prefixSuccessor(prefix, 3))

err := bigtable.tableData.ReadRows(ctx, rowRange, func(row gcp_bigtable.Row) bool {
b := &types.Eth1InternalTransactionIndexed{}
row_ := row[DEFAULT_FAMILY][0]
err := proto.Unmarshal(row_.Value, b)
if err != nil {
logrus.Fatalf("error parsing Eth1InternalTransactionIndexed data: %v", err)
return false
}
// geth traces include the initial transfer & zero-value staticalls
if bytes.Equal(b.From, from) || bytes.Equal(b.Value, []byte{}) {
return true
}
rowN, err := strconv.Atoi(strings.Split(row_.Row, ":")[3])
if err != nil {
logrus.Fatalf("error parsing Eth1InternalTransactionIndexed row number: %v", err)
return false
}
rowN = 100000 - rowN
mux.Lock()
transfers[rowN] = b
mux.Unlock()
return true
}, gcp_bigtable.LimitRows(256))

if err != nil {
return nil, err
func (bigtable *Bigtable) GetInternalTransfersForTransaction(transaction []byte, from []byte, parityTrace []*rpc.ParityTraceResult) ([]types.ITransaction, error) {
getTraceInfo := func(trace *rpc.ParityTraceResult) ([]byte, []byte, []byte, string) {
var from, to, value []byte
tx_type := trace.Type

switch trace.Type {
case "create":
from = common.FromHex(trace.Action.From)
to = common.FromHex(trace.Result.Address)
value = common.FromHex(trace.Action.Value)
case "suicide":
from = common.FromHex(trace.Action.Address)
to = common.FromHex(trace.Action.RefundAddress)
value = common.FromHex(trace.Action.Balance)
case "call":
from = common.FromHex(trace.Action.From)
to = common.FromHex(trace.Action.To)
value = common.FromHex(trace.Action.Value)
tx_type = trace.Action.CallType
default:
utils.LogError(nil, "unknown trace type", 0)
}
return from, to, value, tx_type
}

names := make(map[string]string)
for _, t := range transfers {
names[string(t.From)] = ""
names[string(t.To)] = ""
for _, trace := range parityTrace {
from, to, _, _ := getTraceInfo(trace)
names[string(from)] = ""
names[string(to)] = ""
}

err = bigtable.GetAddressNames(names)
err := bigtable.GetAddressNames(names)
if err != nil {
return nil, err
}

data := make([]types.Transfer, len(transfers))

// sort by event id
keys := make([]int, 0, len(transfers))
for k := range transfers {
keys = append(keys, k)
}
sort.Ints(keys)

for i, k := range keys {
t := transfers[k]

fromName := names[string(t.From)]
toName := names[string(t.To)]
from := utils.FormatAddress(t.From, nil, fromName, false, false, true)
to := utils.FormatAddress(t.To, nil, toName, false, false, true)
data := make([]types.ITransaction, 0, len(parityTrace)-1)
for i := 1; i < len(parityTrace); i++ {
from, to, value, tx_type := getTraceInfo(parityTrace[i])
if string(value) == "\x00" {
continue
}
if tx_type == "suicide" {
// erigon's "suicide" might be misleading for users
tx_type = "selfdestruct"
}
fromName := names[parityTrace[i].Action.From]
toName := names[parityTrace[i].Action.To]
input := make([]byte, 0)
if len(parityTrace[i].Action.Input) > 2 {
input, err = hex.DecodeString(parityTrace[i].Action.Input[2:])
if err != nil {
utils.LogError(err, "can't convert hex string", 0)
}
}
itx := types.ITransaction{
From: utils.FormatAddress(from, nil, fromName, false, false, true),
To: utils.FormatAddress(to, nil, toName, false, false, true),
Amount: utils.FormatBytesAmount(value, utils.Config.Frontend.ElCurrency, 8),
TracePath: utils.FormatTracePath(tx_type, parityTrace[i].TraceAddress, parityTrace[i].Error == "", bigtable.GetMethodLabel(input, true)),
Advanced: tx_type == "delegatecall" || string(value) == "\x00",
}

data[i] = types.Transfer{
From: from,
To: to,
Amount: utils.FormatBytesAmount(t.Value, utils.Config.Frontend.ElCurrency, 8),
gaslimit, err := strconv.ParseUint(parityTrace[i].Action.Gas, 0, 0)
if err == nil {
itx.Gas.Limit = gaslimit
}

data = append(data, itx)
// gasusage, err := strconv.ParseUint(parityTrace[i].Result.GasUsed, 0, 0)
// if err == nil {
// itx.Gas.Usage = gasusage
// }
}
return data, nil
}
Expand Down
16 changes: 8 additions & 8 deletions eth1data/eth1data.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,11 +134,11 @@ func GetEth1Transaction(hash common.Hash) (*types.Eth1TxData, error) {
}
}

data, err := rpc.CurrentErigonClient.TraceParityTx(tx.Hash().Hex())
if err != nil {
return nil, fmt.Errorf("failed to get parity trace for revert reason: %w", err)
}
if receipt.Status != 1 {
data, err := rpc.CurrentErigonClient.TraceParityTx(tx.Hash().Hex())
if err != nil {
return nil, fmt.Errorf("failed to get parity trace for revert reason: %w", err)
}
errorMsg, err := abi.UnpackRevert(utils.MustParseHex(data[0].Result.Output))
if err == nil {
txPageData.ErrorMsg = errorMsg
Expand All @@ -149,10 +149,10 @@ func GetEth1Transaction(hash common.Hash) (*types.Eth1TxData, error) {
if err != nil {
return nil, fmt.Errorf("error loading token transfers from tx: %w", err)
}
txPageData.InternalTxns, err = db.BigtableClient.GetInternalTransfersForTransaction(tx.Hash().Bytes(), msg.From.Bytes())
if err != nil {
return nil, fmt.Errorf("error loading internal transfers from tx: %w", err)
}
}
txPageData.InternalTxns, err = db.BigtableClient.GetInternalTransfersForTransaction(tx.Hash().Bytes(), msg.From.Bytes(), data)
if err != nil {
return nil, fmt.Errorf("error loading internal transfers from tx: %w", err)
}
txPageData.FromName, err = db.BigtableClient.GetAddressName(msg.From.Bytes())
if err != nil {
Expand Down
36 changes: 22 additions & 14 deletions templates/eth1tx.html
Original file line number Diff line number Diff line change
Expand Up @@ -166,15 +166,17 @@ <h1 class="h4 mb-1 mb-md-0">
{{ if gt (len .InternalTxns) 0 }}
<ul class="fa-ul mb-0 mt-2">
{{ range $i, $row := .InternalTxns }}
<li class="mb-1">
<i class="fa-li fas fa-long-arrow-alt-right"></i>
<span>Transfer</span>
<span>{{ .Amount }}</span>
<span>From</span>
<span>{{ .From }}</span>
<span>To</span>
<span>{{ .To }}</span>
</li>
{{ if not .Advanced }}
<li class="mb-1">
<i class="fa-li fas fa-long-arrow-alt-right"></i>
<span>Transfer</span>
<span>{{ .Amount }}</span>
<span>From</span>
<span>{{ .From }}</span>
<span>To</span>
<span>{{ .To }}</span>
</li>
{{ end }}
{{ end }}
</ul>
{{ end }}
Expand Down Expand Up @@ -399,17 +401,23 @@ <h1 class="h4 mb-1 mb-md-0">
<div class="table-responsive">
<table class="table table-borderless text-monospace">
<thead>
<th>Type Trace Address</th>
<th>From</th>
<th>To</th>
<th>Value</th>
<th>Gas Limit</th>
</thead>
<tbody>
{{ range $index, $tx := .InternalTxns }}
<tr>
<td>{{ .From }}</td>
<td>{{ .To }}</td>
<td>{{ .Amount }}</td>
</tr>
{{ if not .Advanced }}
<tr>
<td>{{ .TracePath }}</td>
<td>{{ .From }}</td>
<td>{{ .To }}</td>
<td>{{ .Amount }}</td>
<td>{{ .Gas.Limit }}</td>
</tr>
{{ end }}
{{ end }}
</tbody>
</table>
Expand Down
15 changes: 14 additions & 1 deletion types/templates.go
Original file line number Diff line number Diff line change
Expand Up @@ -1670,6 +1670,19 @@ type Eth1TokenPageData struct {
HoldersTable *DataTableResponse
}

type ITransaction struct {
From template.HTML
To template.HTML
Amount template.HTML
TracePath template.HTML
Advanced bool
Gas struct {
Limit uint64
// Usage uint64
// UsedPerc float64
}
}

type Transfer struct {
From template.HTML
To template.HTML
Expand All @@ -1691,7 +1704,7 @@ type EpochInfo struct {
type Eth1TxData struct {
From common.Address
To *common.Address
InternalTxns []Transfer
InternalTxns []ITransaction
FromName string
ToName string
Gas struct {
Expand Down
17 changes: 17 additions & 0 deletions utils/eth1.go
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,23 @@ func formatAmount(amount *big.Int, unit string, digits int, maxPreCommaDigitsBef
return template.HTML(fmt.Sprintf("<span%s>%s%s</span>", tooltip, trimmedAmount, displayUnit))
}

func FormatTracePath(callType string, tracePath []int64, success bool, method string) template.HTML {
for _, trace := range tracePath {
callType = fmt.Sprintf("%s_%d", callType, trace)
}

tooltip := ""
if method != "" {
tooltip = fmt.Sprintf(` data-toggle="tooltip" data-placement="top" title="%s"`, method)
}

failedStr := ""
if !success {
failedStr = `<span data-toggle="tooltip" title="Transaction failed">❗</span>`
}
return template.HTML(fmt.Sprintf(`<span%s class="text-monospace">%s</span>%s`, tooltip, callType, failedStr))
}

func trimAmount(amount *big.Int, unitDigits int, maxPreCommaDigitsBeforeTrim int, digits int, addPositiveSign bool) (trimmedAmount, fullAmount string) {
// Initialize trimmedAmount and postComma variables to "0"
trimmedAmount = "0"
Expand Down

0 comments on commit ae296a7

Please sign in to comment.