diff --git a/tools/observer/explorer-indexer.mjs b/tools/observer/explorer-indexer.mjs index 69249965a..287c3354d 100644 --- a/tools/observer/explorer-indexer.mjs +++ b/tools/observer/explorer-indexer.mjs @@ -18,7 +18,7 @@ // EXPLORER_TICK_MS the idle tick, default 2000 // // Tables (created on start if missing; the prefix is written as T below): -// T live_txs one row per EVM transaction: hash, block_hash, block_number, tx_index, from_addr, to_addr, value_wei, +// T live_txs one row per EVM transaction: hash (0x), block_hash (the DAG block's hash, no 0x, as live_blocks), block_number, tx_index, from_addr, to_addr, value_wei, // nonce, gas, gas_price, gas_used, effective_gas_price, status, contract_address, input_bytes, selector, // logs_count, logs (jsonb), igneum (jsonb: the receipt's igneum section), tx_type, ts_ms, received_at // T live_accounts one row per address seen: balance_wei, nonce, code_bytes, is_contract, sent, received, first_seen_number, @@ -53,7 +53,7 @@ export const lower = a => (a ? String(a).toLowerCase() : null); export function txRow(tx, rc, block) { const input = String(tx.input || '0x'); return { - hash: lower(tx.hash), block_hash: lower(block.hash), block_number: hexInt(block.number), tx_index: hexInt(tx.transactionIndex) ?? 0, + hash: lower(tx.hash), block_hash: lower(block.hash).replace(/^0x/, ''), block_number: hexInt(block.number), tx_index: hexInt(tx.transactionIndex) ?? 0, from_addr: lower(tx.from), to_addr: lower(tx.to), value_wei: hexBig(tx.value) || '0', nonce: hexInt(tx.nonce), gas: hexInt(tx.gas), gas_price: hexBig(tx.gasPrice ?? tx.maxFeePerGas) , gas_used: rc ? hexInt(rc.gasUsed) : null, effective_gas_price: rc ? hexBig(rc.effectiveGasPrice) : null, status: rc && rc.status !== undefined && rc.status !== null ? hexInt(rc.status) : null, contract_address: rc ? lower(rc.contractAddress) : null, @@ -144,7 +144,7 @@ async function indexNumbers(sql, numbers) { const byHash = new Map((receipts[i] || []).map(r => [lower(r.transactionHash), r])); const txs = (b.transactions || []).map(t => txRow(t, byHash.get(lower(t.hash)) || null, b)); rows.push(...txs); - blockRows.push({ number: hexInt(b.number), hash: lower(b.hash), tx_count: txs.length, gas_used: hexInt(b.gasUsed), ts_ms: hexInt(b.timestamp) * 1000 }); + blockRows.push({ number: hexInt(b.number), hash: lower(b.hash).replace(/^0x/, ''), tx_count: txs.length, gas_used: hexInt(b.gasUsed), ts_ms: hexInt(b.timestamp) * 1000 }); for (const [a, kinds] of touched(txs, b)) { const q = accountQueue.get(a) || { kinds: new Set(), number: 0 }; for (const k of kinds) q.kinds.add(k); q.number = Math.max(q.number, hexInt(b.number)); accountQueue.set(a, q); } } // a number re-indexed after a reorg drops its old rows first @@ -233,7 +233,7 @@ async function main() { const lo = Math.max(0, indexed - 2); const stored = await sql(`SELECT number, hash FROM ${T}explorer_blocks WHERE number BETWEEN $1 AND $2`, [lo, indexed]); const live = await Promise.all(stored.map(s => rpc('eth_getBlockByNumber', [hex(Number(s.number)), false]).catch(() => null))); - const moved = stored.filter((s, i) => live[i] && lower(live[i].hash) !== s.hash).map(s => Number(s.number)); + const moved = stored.filter((s, i) => live[i] && lower(live[i].hash).replace(/^0x/, '') !== s.hash).map(s => Number(s.number)); if (moved.length) { const from = Math.min(...moved); log(`reorg: chain block ${from} moved, re-indexing from it`); indexed = from - 1; } } const behind = tip - indexed; diff --git a/tools/observer/explorer-indexer.test.mjs b/tools/observer/explorer-indexer.test.mjs index 53e5d3d97..0c8faa63c 100644 --- a/tools/observer/explorer-indexer.test.mjs +++ b/tools/observer/explorer-indexer.test.mjs @@ -15,7 +15,7 @@ test('hex helpers: null stays null, big values keep every digit', () => { test('txRow: lower-case addresses and hashes, numbers decoded, the receipt folded in, the selector and the log list', () => { const r = txRow(tx, rc, block); - assert.equal(r.hash, tx.hash.toLowerCase()); assert.equal(r.block_hash, block.hash.toLowerCase()); assert.equal(r.block_number, 25933); assert.equal(r.tx_index, 3); + assert.equal(r.hash, tx.hash.toLowerCase()); assert.equal(r.block_hash, block.hash.toLowerCase().slice(2)); assert.equal(r.block_number, 25933); assert.equal(r.tx_index, 3); assert.equal(r.from_addr, '0xe617a7f966fc009934e943fe0453821ff0c8716f'); assert.equal(r.to_addr, '0x7fe2f74b45dd8f0a739c906817f197631fdeff85'); assert.equal(r.value_wei, '0'); assert.equal(r.nonce, 26); assert.equal(r.gas, 231734); assert.equal(r.gas_used, 28254); assert.equal(r.status, 1); assert.equal(r.selector, '0xa9059cbb'); assert.equal(r.input_bytes, 16); assert.equal(r.logs_count, 1); assert.equal(r.logs[0].address, '0x7fe2f74b45dd8f0a739c906817f197631fdeff85');