@@ -204,18 +204,22 @@ async function generateContractComparison() {
204204 // Get all transactions with contract_id extracted in SQL
205205 const txRows = db . prepare ( `
206206 SELECT
207- contract_id,
208- contract_name,
209- transaction_name,
210- gas_used,
211- weight_consumed_ref_time,
212- weight_consumed_proof_size,
213- base_call_weight_ref_time,
214- base_call_weight_proof_size
215- FROM transactions
216- WHERE chain_name == 'eth-rpc'
217- ORDER BY contract_id, transaction_name, (base_call_weight_ref_time + weight_consumed_ref_time) ASC
207+ t.chain_name,
208+ t.contract_id,
209+ t.contract_name,
210+ t.transaction_name,
211+ t.gas_used,
212+ t.weight_consumed_ref_time,
213+ t.weight_consumed_proof_size,
214+ t.base_call_weight_ref_time,
215+ t.base_call_weight_proof_size,
216+ SUM(s.gas_cost) as total_opcode_gas
217+ FROM transactions t
218+ LEFT JOIN transaction_steps s ON s.hash = t.hash AND s.chain_name = t.chain_name
219+ GROUP BY t.hash, t.chain_name
220+ ORDER BY t.chain_name, t.contract_id, t.transaction_name, t.gas_used ASC
218221 ` ) . all ( ) as Array < {
222+ chain_name : string
219223 contract_name : string
220224 transaction_name : string
221225 gas_used : number
@@ -224,68 +228,134 @@ async function generateContractComparison() {
224228 weight_consumed_proof_size : number | null
225229 base_call_weight_ref_time : number | null
226230 base_call_weight_proof_size : number | null
231+ total_opcode_gas : number | null
227232 } >
228233
229- const groupedByContractAndTx = Object . groupBy (
230- txRows ,
231- ( row ) => `${ row . contract_id } :${ row . transaction_name } ` ,
232- )
234+ // Group by chain first
235+ const byChain = Object . groupBy ( txRows , ( row ) => row . chain_name )
236+
237+ for ( const [ chainName , chainRows ] of Object . entries ( byChain ) ) {
238+ if ( ! chainRows ) continue
239+
240+ markdown += `## Chain: ${ chainName } \n\n`
233241
234- // Generate one table per (contract_id, operation)
235- for (
236- const [ groupKey , implementations ] of Object . entries (
237- groupedByContractAndTx ,
242+ const groupedByContractAndTx = Object . groupBy (
243+ chainRows ,
244+ ( row ) => `${ row . contract_id } :${ row . transaction_name } ` ,
238245 )
239- ) {
240- if ( ! implementations ) continue
241246
242- const [ contract_id , transaction_name ] = groupKey . split ( ':' )
243- markdown += `## ${ contract_id } - ${ transaction_name } \n\n`
247+ // Generate one table per (contract_id, operation)
248+ for (
249+ const [ groupKey , implementations ] of Object . entries (
250+ groupedByContractAndTx ,
251+ )
252+ ) {
253+ if ( ! implementations ) continue
244254
245- // Find best (lowest) total weight ref_time
246- const bestRefTime = Math . min (
247- ...implementations
248- . filter ( ( row ) =>
255+ const [ contract_id , transaction_name ] = groupKey . split ( ':' )
256+ markdown += `### ${ contract_id } - ${ transaction_name } \n\n`
257+
258+ // Check if this chain has weight data (eth-rpc) or just gas_used (Geth)
259+ const hasWeightData = implementations . some (
260+ ( row ) =>
249261 row . weight_consumed_ref_time !== null &&
250- row . base_call_weight_ref_time !== null
262+ row . base_call_weight_ref_time !== null ,
263+ )
264+
265+ if ( hasWeightData ) {
266+ // For eth-rpc: show ref_time, vs Best, % metered, pov
267+ // Find best (lowest) total weight ref_time
268+ const bestRefTime = Math . min (
269+ ...implementations
270+ . filter ( ( row ) =>
271+ row . weight_consumed_ref_time !== null &&
272+ row . base_call_weight_ref_time !== null
273+ )
274+ . map ( ( row ) =>
275+ row . base_call_weight_ref_time ! +
276+ row . weight_consumed_ref_time !
277+ ) ,
251278 )
252- . map ( ( row ) =>
253- row . base_call_weight_ref_time ! +
254- row . weight_consumed_ref_time !
255- ) ,
256- )
257279
258- const tableData = implementations . map ( ( row ) => {
259- const result : Record < string , string > = {
260- 'Implementation' : row . contract_name ,
261- }
280+ // Sort by total ref_time
281+ const sorted = [ ...implementations ] . sort ( ( a , b ) => {
282+ const aTotal = ( a . base_call_weight_ref_time ?? 0 ) +
283+ ( a . weight_consumed_ref_time ?? 0 )
284+ const bTotal = ( b . base_call_weight_ref_time ?? 0 ) +
285+ ( b . weight_consumed_ref_time ?? 0 )
286+ return aTotal - bTotal
287+ } )
288+
289+ const tableData = sorted . map ( ( row ) => {
290+ const result : Record < string , string > = {
291+ 'Implementation' : row . contract_name ,
292+ }
293+
294+ if (
295+ row . weight_consumed_ref_time !== null &&
296+ row . base_call_weight_ref_time !== null
297+ ) {
298+ const totalRefTime = row . base_call_weight_ref_time +
299+ row . weight_consumed_ref_time
300+ const totalProofSize =
301+ ( row . base_call_weight_proof_size ?? 0 ) +
302+ ( row . weight_consumed_proof_size ?? 0 )
303+ const meterPercent =
304+ ( ( row . weight_consumed_ref_time / totalRefTime ) *
305+ 100 )
306+ . toFixed ( 1 )
307+ const vsBest = totalRefTime === bestRefTime
308+ ? '-'
309+ : `+${
310+ ( ( totalRefTime / bestRefTime - 1 ) * 100 )
311+ . toFixed ( 1 )
312+ } %`
313+
314+ result [ 'ref_time' ] = totalRefTime
315+ . toLocaleString ( )
316+ result [ 'vs Best' ] = vsBest
317+ result [ '% metered' ] = `${ meterPercent } %`
318+ result [ 'pov' ] = totalProofSize . toLocaleString ( )
319+ }
320+
321+ return result
322+ } )
323+
324+ markdown += table ( tableData ) + '\n\n'
325+ } else {
326+ // For Geth: show gas_used, vs Best, % metered
327+ const bestGasUsed = Math . min (
328+ ...implementations . map ( ( row ) => row . gas_used ) ,
329+ )
262330
263- if (
264- row . weight_consumed_ref_time !== null &&
265- row . base_call_weight_ref_time !== null
266- ) {
267- const totalRefTime = row . base_call_weight_ref_time +
268- row . weight_consumed_ref_time
269- const totalProofSize = ( row . base_call_weight_proof_size ?? 0 ) +
270- ( row . weight_consumed_proof_size ?? 0 )
271- const meterPercent =
272- ( ( row . weight_consumed_ref_time / totalRefTime ) * 100 )
273- . toFixed ( 1 )
274- const vsBest = totalRefTime === bestRefTime
275- ? '-'
276- : `+${ ( ( totalRefTime / bestRefTime - 1 ) * 100 ) . toFixed ( 1 ) } %`
277-
278- result [ 'ref_time' ] = totalRefTime
279- . toLocaleString ( )
280- result [ 'vs Best' ] = vsBest
281- result [ '% metered' ] = `${ meterPercent } %`
282- result [ 'pov' ] = totalProofSize . toLocaleString ( )
283- }
331+ // Sort by gas_used
332+ const sorted = [ ...implementations ] . sort ( ( a , b ) =>
333+ a . gas_used - b . gas_used
334+ )
284335
285- return result
286- } )
336+ const tableData = sorted . map ( ( row ) => {
337+ const vsBest = row . gas_used === bestGasUsed
338+ ? '-'
339+ : `+${
340+ ( ( row . gas_used / bestGasUsed - 1 ) * 100 ) . toFixed ( 1 )
341+ } %`
342+ const meterPercent = row . total_opcode_gas
343+ ? ( ( row . total_opcode_gas / row . gas_used ) * 100 ) . toFixed (
344+ 1 ,
345+ )
346+ : '0.0'
287347
288- markdown += table ( tableData ) + '\n\n'
348+ return {
349+ 'Implementation' : row . contract_name ,
350+ 'gas_used' : row . gas_used . toLocaleString ( ) ,
351+ 'vs Best' : vsBest ,
352+ '% metered' : `${ meterPercent } %` ,
353+ }
354+ } )
355+
356+ markdown += table ( tableData ) + '\n\n'
357+ }
358+ }
289359 }
290360
291361 await Deno . writeTextFile (
0 commit comments