Skip to content

feat: store and expose vm_error for failed transactions #2286

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,384 changes: 1,622 additions & 762 deletions client/src/generated/schema.d.ts

Large diffs are not rendered by default.

11 changes: 11 additions & 0 deletions migrations/1747408872545_txs-vm-error.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/* eslint-disable camelcase */

exports.shorthands = undefined;

exports.up = pgm => {
pgm.addColumn('txs', {
vm_error: {
type: 'text',
}
});
};
1 change: 1 addition & 0 deletions src/api/controllers/db-controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,7 @@ function parseDbAbstractTx(dbTx: DbTx, baseTx: BaseTransaction): AbstractTransac
execution_cost_runtime: dbTx.execution_cost_runtime,
execution_cost_write_count: dbTx.execution_cost_write_count,
execution_cost_write_length: dbTx.execution_cost_write_length,
vm_error: dbTx.vm_error ?? null,
};
return abstractTx;
}
Expand Down
1 change: 1 addition & 0 deletions src/api/schemas/entities/transactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ const AbstractTransactionProperties = {
execution_cost_write_length: Type.Integer({
description: 'Execution cost write length.',
}),
vm_error: Nullable(Type.String({ description: 'Clarity VM error produced by this transaction' })),
events: Type.Array(TransactionEventSchema),
};
const AbstractTransactionSchema = Type.Object({
Expand Down
5 changes: 5 additions & 0 deletions src/datastore/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,8 @@ export interface DbTx extends BaseTx {
execution_cost_runtime: number;
execution_cost_write_count: number;
execution_cost_write_length: number;

vm_error?: string | null;
}

export interface DbTxRaw extends DbTx {
Expand Down Expand Up @@ -1027,6 +1029,8 @@ export interface TxQueryResult {
execution_cost_runtime: string;
execution_cost_write_count: string;
execution_cost_write_length: string;

vm_error: string | null;
}

export interface ContractTxQueryResult extends TxQueryResult {
Expand Down Expand Up @@ -1228,6 +1232,7 @@ export interface TxInsertValues {
execution_cost_runtime: number;
execution_cost_write_count: number;
execution_cost_write_length: number;
vm_error: string | null;
}

export interface MempoolTxInsertValues {
Expand Down
3 changes: 3 additions & 0 deletions src/datastore/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ export const TX_COLUMNS = [
'execution_cost_runtime',
'execution_cost_write_count',
'execution_cost_write_length',
'vm_error',
];

export const MEMPOOL_TX_COLUMNS = [
Expand Down Expand Up @@ -384,6 +385,7 @@ export function parseTxQueryResult(result: ContractTxQueryResult): DbTx {
execution_cost_write_count: Number.parseInt(result.execution_cost_write_count),
execution_cost_write_length: Number.parseInt(result.execution_cost_write_length),
abi: parseAbiColumn(result.abi),
vm_error: result.vm_error,
};
parseTxTypeSpecificQueryResult(result, tx);
return tx;
Expand Down Expand Up @@ -1206,6 +1208,7 @@ export function createDbTxFromCoreMsg(msg: CoreNodeParsedTxMessage): DbTxRaw {
execution_cost_runtime: coreTx.execution_cost.runtime,
execution_cost_write_count: coreTx.execution_cost.write_count,
execution_cost_write_length: coreTx.execution_cost.write_length,
vm_error: coreTx.vm_error,
};
extractTransactionPayload(parsedTx, dbTx);
return dbTx;
Expand Down
2 changes: 2 additions & 0 deletions src/datastore/pg-write-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1896,6 +1896,7 @@ export class PgWriteStore extends PgStore {
execution_cost_runtime: tx.execution_cost_runtime,
execution_cost_write_count: tx.execution_cost_write_count,
execution_cost_write_length: tx.execution_cost_write_length,
vm_error: tx.vm_error ?? null,
}));

let count = 0;
Expand Down Expand Up @@ -3492,6 +3493,7 @@ export class PgWriteStore extends PgStore {
execution_cost_runtime: tx.execution_cost_runtime,
execution_cost_write_count: tx.execution_cost_write_count,
execution_cost_write_length: tx.execution_cost_write_length,
vm_error: tx.vm_error ?? null,
}));
await sql`INSERT INTO txs ${sql(values)}`;
}
Expand Down
1 change: 1 addition & 0 deletions src/event-stream/core-node-message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,7 @@ export interface CoreNodeTxMessage {
microblock_sequence: number | null;
microblock_hash: string | null;
microblock_parent_hash: string | null;
vm_error?: string | null;
burnchain_op?: BurnchainOp | null;
}

Expand Down
20 changes: 18 additions & 2 deletions tests/api/address.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,7 @@ describe('address tests', () => {
execution_cost_runtime: 3,
execution_cost_write_count: 4,
execution_cost_write_length: 5,
vm_error: null,
},
stx_sent: '1339',
stx_received: '0',
Expand Down Expand Up @@ -390,6 +391,7 @@ describe('address tests', () => {
execution_cost_runtime: 3,
execution_cost_write_count: 4,
execution_cost_write_length: 5,
vm_error: null,
},
stx_sent: '1484',
stx_received: '0',
Expand Down Expand Up @@ -454,6 +456,7 @@ describe('address tests', () => {
execution_cost_runtime: 3,
execution_cost_write_count: 4,
execution_cost_write_length: 5,
vm_error: null,
},
stx_sent: '1334',
stx_received: '0',
Expand Down Expand Up @@ -792,6 +795,7 @@ describe('address tests', () => {
execution_cost_runtime: 3,
execution_cost_write_count: 4,
execution_cost_write_length: 5,
vm_error: null,
},
stx_sent: '0',
stx_received: '105',
Expand Down Expand Up @@ -867,6 +871,7 @@ describe('address tests', () => {
execution_cost_runtime: 3,
execution_cost_write_count: 4,
execution_cost_write_length: 5,
vm_error: null,
},
stx_sent: '0',
stx_received: '105',
Expand Down Expand Up @@ -957,6 +962,7 @@ describe('address tests', () => {
execution_cost_runtime: 3,
execution_cost_write_count: 4,
execution_cost_write_length: 5,
vm_error: null,
},
stx_sent: '0',
stx_received: '15',
Expand Down Expand Up @@ -1950,6 +1956,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
},
{
tx_id: '0x1234',
Expand Down Expand Up @@ -1993,6 +2000,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
},
{
tx_id: '0x12340005',
Expand Down Expand Up @@ -2037,6 +2045,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
},
{
tx_id: '0x12340003',
Expand Down Expand Up @@ -2081,6 +2090,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
},
{
tx_id: '0x12340002',
Expand Down Expand Up @@ -2125,6 +2135,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
},
],
};
Expand Down Expand Up @@ -2199,6 +2210,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
},
],
};
Expand Down Expand Up @@ -2263,6 +2275,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
fee_rate: '10',
is_unanchored: false,
microblock_canonical: true,
Expand Down Expand Up @@ -2343,6 +2356,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
fee_rate: '10',
is_unanchored: false,
microblock_canonical: true,
Expand Down Expand Up @@ -2427,6 +2441,7 @@ describe('address tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
};

const blockTxsRows = await api.datastore.getBlockTxsRows(block.block_hash);
Expand All @@ -2438,7 +2453,7 @@ describe('address tests', () => {
abi: JSON.parse(contractCallResult1?.abi ?? ''),
}).toEqual({
...contractCall,
...{ abi: contractJsonAbi },
...{ abi: contractJsonAbi, vm_error: null },
});

const searchResult8 = await supertest(api.server).get(
Expand All @@ -2458,7 +2473,7 @@ describe('address tests', () => {
abi: JSON.parse(contractCallResult2?.abi ?? ''),
}).toEqual({
...contractCall,
...{ abi: contractJsonAbi },
...{ abi: contractJsonAbi, vm_error: null },
});
});

Expand Down Expand Up @@ -2518,6 +2533,7 @@ describe('address tests', () => {
microblock_hash: null,
microblock_parent_hash: null,
microblock_sequence: null,
vm_error: null,
execution_cost: {
read_count: 0,
read_length: 0,
Expand Down
1 change: 1 addition & 0 deletions tests/api/block.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ describe('block tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
};
await db.updateTx(client, tx);

Expand Down
2 changes: 2 additions & 0 deletions tests/api/cache-control.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ describe('cache-control tests', () => {
execution_cost_runtime: 0,
execution_cost_write_count: 0,
execution_cost_write_length: 0,
vm_error: null,
};
await db.update({
block: block1,
Expand Down Expand Up @@ -272,6 +273,7 @@ describe('cache-control tests', () => {

// These properties can be determined with a db query, they are set while the db is inserting them.
block_height: -1,
vm_error: null,
};

await db.updateMicroblocks({
Expand Down
Loading