diff --git a/.hack/devnet/run.sh b/.hack/devnet/run.sh index 9ffab3fc..1f70b52c 100755 --- a/.hack/devnet/run.sh +++ b/.hack/devnet/run.sh @@ -48,6 +48,12 @@ EXECUTION_NODES=$(docker ps -aq -f "label=kurtosis_enclave_uuid=$ENCLAVE_UUID" \ -f "label=com.kurtosistech.app-id=kurtosis" \ -f "label=com.kurtosistech.custom.ethereum-package.client-type=execution" | tac) +TRACOOR_NODES=$(docker ps -aq -f "label=kurtosis_enclave_uuid=$ENCLAVE_UUID" \ + -f "label=com.kurtosistech.app-id=kurtosis" \ + -f "label=com.kurtosistech.id=tracoor" | tac) + +TRACOOR_PORT=$(docker inspect --format='{{ (index (index .NetworkSettings.Ports "7007/tcp") 0).HostPort }}' $TRACOOR_NODES) + cat < "${__dir}/generated-dora-config.yaml" logging: outputLevel: "info" @@ -82,6 +88,8 @@ frontend: disableDasGuardianCheck: false enableDasGuardianMassScan: true showValidatorSummary: true + tracoorUrl: "http://127.0.0.1:$TRACOOR_PORT" + tracoorNetwork: "kurtosis" api: enabled: true corsOrigins: diff --git a/clients/execution/chainstate.go b/clients/execution/chainstate.go index 1c5ac13e..72d65f66 100644 --- a/clients/execution/chainstate.go +++ b/clients/execution/chainstate.go @@ -16,6 +16,8 @@ import ( var DefaultSystemContractAddresses = map[string]common.Address{ rpc.ConsolidationRequestContract: common.HexToAddress("0x0000BBdDc7CE488642fb579F8B00f3a590007251"), rpc.WithdrawalRequestContract: common.HexToAddress("0x00000961Ef480Eb55e80D19ad83579A64c007002"), + rpc.BeaconRootsContract: common.HexToAddress("0x000F3df6D732807Ef1319fB7B8bB8522d0Beac02"), + rpc.HistoryStorageContract: common.HexToAddress("0x0000F90827F1C53a10cb7A02335B175320002935"), } type ChainState struct { diff --git a/clients/execution/rpc/ethconfig.go b/clients/execution/rpc/ethconfig.go index a8ca0ecf..c4540ae7 100644 --- a/clients/execution/rpc/ethconfig.go +++ b/clients/execution/rpc/ethconfig.go @@ -11,6 +11,8 @@ const ( DepositContract = "DEPOSIT_CONTRACT_ADDRESS" ConsolidationRequestContract = "CONSOLIDATION_REQUEST_PREDEPLOY_ADDRESS" WithdrawalRequestContract = "WITHDRAWAL_REQUEST_PREDEPLOY_ADDRESS" + BeaconRootsContract = "BEACON_ROOTS_ADDRESS" + HistoryStorageContract = "HISTORY_STORAGE_ADDRESS" ) type EthConfigFork struct { diff --git a/handlers/slot.go b/handlers/slot.go index dd745d4c..c9a67989 100644 --- a/handlers/slot.go +++ b/handlers/slot.go @@ -940,16 +940,15 @@ func getSlotPageBlockData(ctx context.Context, blockData *services.CombinedBlock getSlotPageTransactions(ctx, pageData, transactions, blockUid) } - // EIP-7928 Block Access List — Gloas stores the RLP-encoded list on - // the envelope's payload; other forks don't carry it. - if executionPayload.Version >= spec.DataVersionGloas && executionPayload.Gloas != nil { - if balBytes := []byte(executionPayload.Gloas.BlockAccessList); len(balBytes) > 0 { - accesses, err := utils.DecodeBlockAccessList(balBytes) - if err != nil { - logrus.Warnf("error decoding block access list for slot %v: %v", blockData.Header.Message.Slot, err) - } else { - pageData.ExecutionData.BlockAccessList = convertBALToModel(accesses) - } + // EIP-7928 Block Access List — the chainservice sources the bytes + // either from the envelope (fresh from the node) or from blockdb + // (preserved after the node pruned it). + if len(blockData.BlockAccessList) > 0 { + accesses, err := utils.DecodeBlockAccessList(blockData.BlockAccessList) + if err != nil { + logrus.Warnf("error decoding block access list for slot %v: %v", blockData.Header.Message.Slot, err) + } else { + pageData.ExecutionData.BlockAccessList = convertBALToModel(accesses) } } diff --git a/handlers/slot_download.go b/handlers/slot_download.go index a905732e..258d85b1 100644 --- a/handlers/slot_download.go +++ b/handlers/slot_download.go @@ -11,6 +11,7 @@ import ( bdbtypes "github.com/ethpandaops/dora/blockdb/types" "github.com/ethpandaops/dora/indexer/beacon" "github.com/ethpandaops/dora/services" + "github.com/ethpandaops/dora/utils" "github.com/ethpandaops/go-eth2-client/spec/bellatrix" "github.com/ethpandaops/go-eth2-client/spec/phase0" "github.com/golang/snappy" @@ -88,6 +89,56 @@ func handleSlotDownload(ctx context.Context, w http.ResponseWriter, blockSlot in case "block-body-json": return handleBlockBodyDownload(w, blockData) + case "payload-ssz": + if blockData.Payload == nil { + return fmt.Errorf("block has no execution payload envelope") + } + dynSsz := services.GlobalBeaconService.GetBeaconIndexer().GetDynSSZ() + ssz, err := dynSsz.MarshalSSZ(blockData.Payload) + if err != nil { + return fmt.Errorf("error serializing payload envelope: %v", err) + } + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=payload-%d-%x.ssz", blockData.Header.Message.Slot, blockData.Root[:])) + _, _ = w.Write(ssz) + return nil + + case "payload-json": + if blockData.Payload == nil { + return fmt.Errorf("block has no execution payload envelope") + } + jsonRes, err := blockData.Payload.MarshalJSON() + if err != nil { + return fmt.Errorf("error serializing payload envelope: %v", err) + } + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=payload-%d-%x.json", blockData.Header.Message.Slot, blockData.Root[:])) + _, _ = w.Write(jsonRes) + return nil + + case "bal-rlp": + if len(blockData.BlockAccessList) == 0 { + return fmt.Errorf("block has no block access list") + } + w.Header().Set("Content-Type", "application/octet-stream") + w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=bal-%d-%x.rlp", blockData.Header.Message.Slot, blockData.Root[:])) + _, _ = w.Write(blockData.BlockAccessList) + return nil + + case "bal-json": + if len(blockData.BlockAccessList) == 0 { + return fmt.Errorf("block has no block access list") + } + accesses, err := utils.DecodeBlockAccessList(blockData.BlockAccessList) + if err != nil { + return fmt.Errorf("error decoding block access list: %v", err) + } + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=bal-%d-%x.json", blockData.Header.Message.Slot, blockData.Root[:])) + encoder := json.NewEncoder(w) + encoder.SetIndent("", " ") + return encoder.Encode(balToJSON(accesses)) + default: return fmt.Errorf("unknown download type: %s", downloadType) } @@ -513,3 +564,107 @@ func buildSingleReceipt( return receipt, nil } + +// balAccountJSON is the download-friendly JSON shape for one EIP-7928 account +// entry. Uses hex strings for all byte fields so the dump is readable and +// stable across tooling. +type balAccountJSON struct { + Address string `json:"address"` + StorageWrites []balSlotWritesJSON `json:"storage_writes,omitempty"` + StorageReads []string `json:"storage_reads,omitempty"` + BalanceChanges []balBalanceChangeJSON `json:"balance_changes,omitempty"` + NonceChanges []balNonceChangeJSON `json:"nonce_changes,omitempty"` + CodeChanges []balCodeChangeJSON `json:"code_changes,omitempty"` +} + +type balSlotWritesJSON struct { + Slot string `json:"slot"` + Accesses []balStorageWriteJSON `json:"accesses"` +} + +type balStorageWriteJSON struct { + TxIndex uint16 `json:"tx_index"` + ValueAfter string `json:"value_after"` +} + +type balBalanceChangeJSON struct { + TxIndex uint16 `json:"tx_index"` + Balance string `json:"balance"` +} + +type balNonceChangeJSON struct { + TxIndex uint16 `json:"tx_index"` + Nonce uint64 `json:"nonce"` +} + +type balCodeChangeJSON struct { + TxIndex uint16 `json:"tx_index"` + Code string `json:"code"` +} + +// balToJSON converts the RLP-decoded BAL structure into the download JSON shape. +func balToJSON(accesses []utils.BALAccountAccess) []balAccountJSON { + result := make([]balAccountJSON, len(accesses)) + for i, entry := range accesses { + out := balAccountJSON{ + Address: fmt.Sprintf("0x%x", entry.Address[:]), + } + + if len(entry.StorageWrites) > 0 { + out.StorageWrites = make([]balSlotWritesJSON, len(entry.StorageWrites)) + for j, sw := range entry.StorageWrites { + writes := make([]balStorageWriteJSON, len(sw.Accesses)) + for k, w := range sw.Accesses { + writes[k] = balStorageWriteJSON{ + TxIndex: w.TxIdx, + ValueAfter: fmt.Sprintf("0x%x", w.ValueAfter), + } + } + out.StorageWrites[j] = balSlotWritesJSON{ + Slot: fmt.Sprintf("0x%x", sw.Slot), + Accesses: writes, + } + } + } + + if len(entry.StorageReads) > 0 { + out.StorageReads = make([]string, len(entry.StorageReads)) + for j, r := range entry.StorageReads { + out.StorageReads[j] = fmt.Sprintf("0x%x", r) + } + } + + if len(entry.BalanceChanges) > 0 { + out.BalanceChanges = make([]balBalanceChangeJSON, len(entry.BalanceChanges)) + for j, b := range entry.BalanceChanges { + out.BalanceChanges[j] = balBalanceChangeJSON{ + TxIndex: b.TxIdx, + Balance: fmt.Sprintf("0x%x", b.Balance), + } + } + } + + if len(entry.NonceChanges) > 0 { + out.NonceChanges = make([]balNonceChangeJSON, len(entry.NonceChanges)) + for j, n := range entry.NonceChanges { + out.NonceChanges[j] = balNonceChangeJSON{ + TxIndex: n.TxIdx, + Nonce: n.Nonce, + } + } + } + + if len(entry.CodeChanges) > 0 { + out.CodeChanges = make([]balCodeChangeJSON, len(entry.CodeChanges)) + for j, c := range entry.CodeChanges { + out.CodeChanges[j] = balCodeChangeJSON{ + TxIndex: c.TxIndex, + Code: fmt.Sprintf("0x%x", c.Code), + } + } + } + + result[i] = out + } + return result +} diff --git a/handlers/transaction.go b/handlers/transaction.go index b8c81ffe..53367be7 100644 --- a/handlers/transaction.go +++ b/handlers/transaction.go @@ -1080,7 +1080,7 @@ func buildInternalTxsFromBlockdb(ctx context.Context, pageData *models.Transacti isCreate := f.Type == 3 || f.Type == 4 precompileInfo := utils.GetPrecompileInfo(f.To[:]) sysName, isSysContract := sysContracts[f.To] - isNonDepositSys := isSysContract && sysName != "Deposit" + isNonDepositSys := isSysContract && sysName != "Deposit Contract" if isCreate { itx.MethodName = "deploy" @@ -1090,9 +1090,9 @@ func buildInternalTxsFromBlockdb(ctx context.Context, pageData *models.Transacti } else if isNonDepositSys { itx.MethodName = sysName switch sysName { - case "Withdrawal Request": + case "Withdrawal Request (EIP-7002)": itx.DecodedCalldata = utils.DecodeWithdrawalRequestInput(f.Input) - case "Consolidation Request": + case "Consolidation Request (EIP-7251)": itx.DecodedCalldata = utils.DecodeConsolidationRequestInput(f.Input) } } else { diff --git a/services/chainservice.go b/services/chainservice.go index 37aca1a0..5ae8412c 100644 --- a/services/chainservice.go +++ b/services/chainservice.go @@ -424,24 +424,30 @@ func (bs *ChainService) GetSystemContractAddress(systemContract string) common.A } // GetSystemContractAddresses returns a map of all known system contract -// addresses to their human-readable names. Includes deposit, withdrawal -// request, and consolidation request contracts. +// addresses to their human-readable labels (with EIP tags). Includes +// deposit, withdrawal request, consolidation request, beacon roots, and +// block hash history contracts. func (bs *ChainService) GetSystemContractAddresses() map[common.Address]string { - result := make(map[common.Address]string, 4) + result := make(map[common.Address]string, 5) + + labels := map[string]string{ + exerpc.WithdrawalRequestContract: "Withdrawal Request (EIP-7002)", + exerpc.ConsolidationRequestContract: "Consolidation Request (EIP-7251)", + exerpc.BeaconRootsContract: "Beacon Roots (EIP-4788)", + exerpc.HistoryStorageContract: "Block Hash History (EIP-2935)", + } execChainState := bs.GetExecutionChainState() if execChainState != nil { - withdrawalAddr := execChainState.GetSystemContractAddress(exerpc.WithdrawalRequestContract) - consolidationAddr := execChainState.GetSystemContractAddress(exerpc.ConsolidationRequestContract) - result[withdrawalAddr] = "Withdrawal Request" - result[consolidationAddr] = "Consolidation Request" + for name, label := range labels { + if addr := execChainState.GetSystemContractAddress(name); addr != (common.Address{}) { + result[addr] = label + } + } } else { for name, addr := range execution.DefaultSystemContractAddresses { - switch name { - case exerpc.WithdrawalRequestContract: - result[addr] = "Withdrawal Request" - case exerpc.ConsolidationRequestContract: - result[addr] = "Consolidation Request" + if label, ok := labels[name]; ok { + result[addr] = label } } } @@ -453,7 +459,7 @@ func (bs *ChainService) GetSystemContractAddresses() map[common.Address]string { if specs != nil && len(specs.DepositContractAddress) == 20 { var depositAddr common.Address copy(depositAddr[:], specs.DepositContractAddress) - result[depositAddr] = "Deposit" + result[depositAddr] = "Deposit Contract" } } diff --git a/services/chainservice_blocks.go b/services/chainservice_blocks.go index 3a032c7f..bf2cb5b8 100644 --- a/services/chainservice_blocks.go +++ b/services/chainservice_blocks.go @@ -21,11 +21,12 @@ import ( ) type CombinedBlockResponse struct { - Root phase0.Root - Header *phase0.SignedBeaconBlockHeader - Block *spec.VersionedSignedBeaconBlock - Payload *gloas.SignedExecutionPayloadEnvelope - Orphaned bool + Root phase0.Root + Header *phase0.SignedBeaconBlockHeader + Block *spec.VersionedSignedBeaconBlock + Payload *gloas.SignedExecutionPayloadEnvelope + BlockAccessList []byte + Orphaned bool } // GetBlockBlob retrieves the blob data for a given block root and blob index. @@ -176,7 +177,7 @@ func (bs *ChainService) GetSlotDetailsByBlockroot(ctx context.Context, blockroot // try loading from block db if result == nil && header != nil && blockdb.GlobalBlockDb != nil { blockData, err := blockdb.GlobalBlockDb.GetBlock(ctx, uint64(header.Message.Slot), blockroot[:], - btypes.BlockDataFlagBody|btypes.BlockDataFlagPayload, + btypes.BlockDataFlagBody|btypes.BlockDataFlagPayload|btypes.BlockDataFlagBal, func(version uint64, block []byte) (any, error) { return beacon.UnmarshalVersionedSignedBeaconBlockSSZ(bs.beaconIndexer.GetDynSSZ(), version, block) }, func(version uint64, payload []byte) (any, error) { @@ -192,10 +193,17 @@ func (bs *ChainService) GetSlotDetailsByBlockroot(ctx context.Context, blockroot if blockData.Payload != nil { resp.Payload = blockData.Payload.(*gloas.SignedExecutionPayloadEnvelope) } + if blockData.BalVersion != 0 && len(blockData.BalData) > 0 { + if bal, err := beacon.UnmarshalBlockAccessList(blockData.BalVersion, blockData.BalData); err == nil { + resp.BlockAccessList = bal + } + } result = resp } } + bs.populateBlockAccessList(ctx, result) + return result, nil } @@ -321,7 +329,7 @@ func (bs *ChainService) GetSlotDetailsBySlot(ctx context.Context, slot phase0.Sl // try loading from block db if result == nil && header != nil && blockdb.GlobalBlockDb != nil { blockData, err := blockdb.GlobalBlockDb.GetBlock(ctx, uint64(slot), blockRoot[:], - btypes.BlockDataFlagHeader|btypes.BlockDataFlagBody|btypes.BlockDataFlagPayload, + btypes.BlockDataFlagHeader|btypes.BlockDataFlagBody|btypes.BlockDataFlagPayload|btypes.BlockDataFlagBal, func(version uint64, block []byte) (any, error) { return beacon.UnmarshalVersionedSignedBeaconBlockSSZ(bs.beaconIndexer.GetDynSSZ(), version, block) }, func(version uint64, payload []byte) (any, error) { @@ -343,13 +351,57 @@ func (bs *ChainService) GetSlotDetailsBySlot(ctx context.Context, slot phase0.Sl if blockData.Payload != nil { resp.Payload = blockData.Payload.(*gloas.SignedExecutionPayloadEnvelope) } + if blockData.BalVersion != 0 && len(blockData.BalData) > 0 { + if bal, err := beacon.UnmarshalBlockAccessList(blockData.BalVersion, blockData.BalData); err == nil { + resp.BlockAccessList = bal + } + } result = resp } } + bs.populateBlockAccessList(ctx, result) + return result, nil } +// populateBlockAccessList fills result.BlockAccessList for Gloas+ blocks. +// Prefers the envelope's in-payload BAL, falling back to the BAL preserved +// in blockdb when the node has pruned it (BAL is ephemeral on nodes but +// stored forever in blockdb — see indexer/beacon/block.go writeToBlockDb). +func (bs *ChainService) populateBlockAccessList(ctx context.Context, result *CombinedBlockResponse) { + if result == nil || result.Block == nil || result.Block.Version < spec.DataVersionGloas { + return + } + if len(result.BlockAccessList) > 0 { + return + } + + if result.Payload != nil && result.Payload.Message != nil && result.Payload.Message.Payload != nil { + if bal := []byte(result.Payload.Message.Payload.BlockAccessList); len(bal) > 0 { + result.BlockAccessList = bal + return + } + } + + if blockdb.GlobalBlockDb == nil || result.Header == nil { + return + } + + blockData, err := blockdb.GlobalBlockDb.GetBlock(ctx, uint64(result.Header.Message.Slot), result.Root[:], + btypes.BlockDataFlagBal, nil, nil) + if err != nil || blockData == nil || blockData.BalVersion == 0 || len(blockData.BalData) == 0 { + return + } + + bal, err := beacon.UnmarshalBlockAccessList(blockData.BalVersion, blockData.BalData) + if err != nil { + logrus.WithError(err).Warnf("failed to decode BAL from blockdb for block 0x%x", result.Root[:]) + return + } + result.BlockAccessList = bal +} + // GetBlobSidecarsByBlockRoot retrieves the blob sidecars for a given block root. // It first tries to find a client that has the block root in its cache, and if not found, // it falls back to a random ready client. It then retrieves the blob sidecars for the block root diff --git a/templates/slot/slot.html b/templates/slot/slot.html index 401e3294..af65201f 100644 --- a/templates/slot/slot.html +++ b/templates/slot/slot.html @@ -347,94 +347,90 @@

Proofs

-

Download Block Data

- -
-
-
-
-

Signed Beacon Block Header

-
- +
Consensus Layer
+
+
+
+
Signed Beacon Block Header
+ Slot, proposer, roots, signature +
+
+ SSZ + JSON
- -
-
-
-

Signed Beacon Block

+
+
+
Signed Beacon Block
+ Full block with body, attestations, and operations +
+
+ SSZ + JSON +
+
+ {{ if and .Block.PayloadHeader (ne .Block.PayloadHeader.PayloadStatus 0) }} +
+
+
Signed Execution Payload Envelope
+ Gloas builder envelope (EIP-7732)
- -
+ {{ end }}
{{ if .Block.ExecutionData }} -
-

Execution Data

-
-
-
-
-

Execution Block

+
Execution Layer
+
+
+
+
Execution Block
+ eth_getBlockByHash format with full transactions
- -
- {{ if .Block.ExecutionData.HasExecData }} -
-
-
-

Block Receipts

+ {{ if .Block.ExecutionData.HasExecData }} +
+
+
Block Receipts
+ All transaction receipts with logs +
+
+ JSON +
-
-
- - Download as JSON - + {{ end }} + {{ if .Block.ExecutionData.BlockAccessList }} +
+
+
Block Access List (EIP-7928)
+ Per-account storage / balance / nonce / code accesses +
+
+ RLP + JSON
-
+ {{ end }}
- {{ end }} -
{{ end }} {{ if .TracoorUrl }} -
-

Tracoor Traces

-
-
-
- Loading... +
Tracoor Traces
+
+
+
+ Loading... +
+ Loading Tracoor traces…
-

Loading Tracoor traces...

-
{{ end }}
@@ -501,58 +497,28 @@

Tracoor Traces

} function renderTracoorData(data) { - var html = '
'; - - // Beacon Block Traces - html += '
'; - html += '
Beacon Block Traces'; - if (data.beacon_blocks && data.beacon_blocks.length > 0) { - html += ' ' + data.beacon_blocks.length + ''; - } - html += '
'; - if (data.beacon_blocks_error) { - html += '
' + escapeHtml(data.beacon_blocks_error) + '
'; - } else if (data.beacon_blocks && data.beacon_blocks.length > 0) { - html += renderTracoorTable(data.beacon_blocks, 'beacon_block', data.tracoor_url); - } else { - html += '

No beacon block traces available.

'; - } - html += '
'; - - // Beacon State Traces - html += '
'; - html += '
Beacon State Traces'; - if (data.beacon_states && data.beacon_states.length > 0) { - html += ' ' + data.beacon_states.length + ''; - } - html += '
'; - if (data.beacon_states_error) { - html += '
' + escapeHtml(data.beacon_states_error) + '
'; - } else if (data.beacon_states && data.beacon_states.length > 0) { - html += renderTracoorTable(data.beacon_states, 'beacon_state', data.tracoor_url); - } else { - html += '

No beacon state traces available.

'; - } - html += '
'; + var html = ''; + html += renderTracoorSection('fa-cube', 'Beacon Block Traces', data.beacon_blocks, data.beacon_blocks_error, 'beacon_block', data.tracoor_url); + html += renderTracoorSection('fa-database', 'Beacon State Traces', data.beacon_states, data.beacon_states_error, 'beacon_state', data.tracoor_url); + html += renderTracoorSection('fa-microchip', 'Execution Block Traces', data.execution_block_traces, data.execution_block_trace_error, 'execution_block_trace', data.tracoor_url); + $('#tracoor-content').html(html); + } - // Execution Block Traces - html += '
'; - html += '
Execution Block Traces'; - if (data.execution_block_traces && data.execution_block_traces.length > 0) { - html += ' ' + data.execution_block_traces.length + ''; + function renderTracoorSection(icon, title, items, err, type, tracoorBaseUrl) { + var count = (items && items.length) ? items.length : 0; + var html = '
' + escapeHtml(title); + if (count > 0) { + html += ' ' + count + ''; } - html += '
'; - if (data.execution_block_trace_error) { - html += '
' + escapeHtml(data.execution_block_trace_error) + '
'; - } else if (data.execution_block_traces && data.execution_block_traces.length > 0) { - html += renderTracoorTable(data.execution_block_traces, 'execution_block_trace', data.tracoor_url); + html += ''; + if (err) { + html += '
' + escapeHtml(err) + '
'; + } else if (count > 0) { + html += renderTracoorTable(items, type, tracoorBaseUrl); } else { - html += '

No execution block traces available.

'; + html += '

None available.

'; } - html += '
'; - - html += '
'; - $('#tracoor-content').html(html); + return html; } function getClientBadgeClass(client) { @@ -577,14 +543,7 @@

Tracoor Traces

var isExecution = type === 'execution_block_trace'; var implField = isExecution ? 'execution_implementation' : 'beacon_implementation'; - var html = '
'; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; + var html = '
'; for (var i = 0; i < items.length; i++) { var item = items[i]; @@ -593,16 +552,19 @@

Tracoor Traces

var downloadUrl = tracoorBaseUrl + '/download/' + type + '/' + item.id; var badgeClass = getClientBadgeClass(impl); - html += '
'; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; - html += ''; + html += '
'; + html += '
'; + html += '
'; + html += '' + escapeHtml(impl) + ''; + html += '' + escapeHtml(item.node) + ''; + html += '
'; + html += '' + escapeHtml(item.node_version) + ' · ' + escapeHtml(fetchedAt) + ''; + html += '
'; + html += 'Download'; + html += '
'; } - html += '
NodeClientVersionFetched AtDownload
' + escapeHtml(item.node) + '' + escapeHtml(impl) + '' + escapeHtml(item.node_version) + '' + escapeHtml(fetchedAt) + '
'; + html += '
'; return html; } diff --git a/utils/calldata.go b/utils/calldata.go index fd5012e5..d1bc379c 100644 --- a/utils/calldata.go +++ b/utils/calldata.go @@ -77,15 +77,15 @@ func ResolveCallTargetAndMethod( if len(toAddr) == 20 { var addr common.Address copy(addr[:], toAddr) - if sysName, ok := sysContracts[addr]; ok && sysName != "Deposit" { + if sysName, ok := sysContracts[addr]; ok && sysName != "Deposit Contract" { res.CallType = "system" res.CallName = sysName res.MethodName = sysName if len(inputData) > 0 { switch sysName { - case "Withdrawal Request": + case "Withdrawal Request (EIP-7002)": res.DecodedCalldata = DecodeWithdrawalRequestInput(inputData) - case "Consolidation Request": + case "Consolidation Request (EIP-7251)": res.DecodedCalldata = DecodeConsolidationRequestInput(inputData) } } @@ -165,7 +165,7 @@ func ShouldSkipSignatureLookup(toAddr []byte, isCreate bool, sysContracts map[co var addr common.Address copy(addr[:], toAddr) - if sysName, ok := sysContracts[addr]; ok && sysName != "Deposit" { + if sysName, ok := sysContracts[addr]; ok && sysName != "Deposit Contract" { return true, sysName } }