Skip to content

Commit 7ac7513

Browse files
authored
feat: store and expose vm_error for failed transactions (#2286)
* feat: store and expose vm_error in failed transactions * fix: tests * fix: load vm_error from table * fix: parse vm error * fix: standard null type * fix: tests * fix: property may not come in past node versions * fix: db controller
1 parent f5c2e01 commit 7ac7513

20 files changed

+1757
-764
lines changed

client/src/generated/schema.d.ts

Lines changed: 1622 additions & 762 deletions
Large diffs are not rendered by default.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* eslint-disable camelcase */
2+
3+
exports.shorthands = undefined;
4+
5+
exports.up = pgm => {
6+
pgm.addColumn('txs', {
7+
vm_error: {
8+
type: 'text',
9+
}
10+
});
11+
};

src/api/controllers/db-controller.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1135,6 +1135,7 @@ function parseDbAbstractTx(dbTx: DbTx, baseTx: BaseTransaction): AbstractTransac
11351135
execution_cost_runtime: dbTx.execution_cost_runtime,
11361136
execution_cost_write_count: dbTx.execution_cost_write_count,
11371137
execution_cost_write_length: dbTx.execution_cost_write_length,
1138+
vm_error: dbTx.vm_error ?? null,
11381139
};
11391140
return abstractTx;
11401141
}

src/api/schemas/entities/transactions.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ const AbstractTransactionProperties = {
150150
execution_cost_write_length: Type.Integer({
151151
description: 'Execution cost write length.',
152152
}),
153+
vm_error: Nullable(Type.String({ description: 'Clarity VM error produced by this transaction' })),
153154
events: Type.Array(TransactionEventSchema),
154155
};
155156
const AbstractTransactionSchema = Type.Object({

src/datastore/common.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,8 @@ export interface DbTx extends BaseTx {
236236
execution_cost_runtime: number;
237237
execution_cost_write_count: number;
238238
execution_cost_write_length: number;
239+
240+
vm_error?: string | null;
239241
}
240242

241243
export interface DbTxRaw extends DbTx {
@@ -1027,6 +1029,8 @@ export interface TxQueryResult {
10271029
execution_cost_runtime: string;
10281030
execution_cost_write_count: string;
10291031
execution_cost_write_length: string;
1032+
1033+
vm_error: string | null;
10301034
}
10311035

10321036
export interface ContractTxQueryResult extends TxQueryResult {
@@ -1228,6 +1232,7 @@ export interface TxInsertValues {
12281232
execution_cost_runtime: number;
12291233
execution_cost_write_count: number;
12301234
execution_cost_write_length: number;
1235+
vm_error: string | null;
12311236
}
12321237

12331238
export interface MempoolTxInsertValues {

src/datastore/helpers.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ export const TX_COLUMNS = [
124124
'execution_cost_runtime',
125125
'execution_cost_write_count',
126126
'execution_cost_write_length',
127+
'vm_error',
127128
];
128129

129130
export const MEMPOOL_TX_COLUMNS = [
@@ -384,6 +385,7 @@ export function parseTxQueryResult(result: ContractTxQueryResult): DbTx {
384385
execution_cost_write_count: Number.parseInt(result.execution_cost_write_count),
385386
execution_cost_write_length: Number.parseInt(result.execution_cost_write_length),
386387
abi: parseAbiColumn(result.abi),
388+
vm_error: result.vm_error,
387389
};
388390
parseTxTypeSpecificQueryResult(result, tx);
389391
return tx;
@@ -1206,6 +1208,7 @@ export function createDbTxFromCoreMsg(msg: CoreNodeParsedTxMessage): DbTxRaw {
12061208
execution_cost_runtime: coreTx.execution_cost.runtime,
12071209
execution_cost_write_count: coreTx.execution_cost.write_count,
12081210
execution_cost_write_length: coreTx.execution_cost.write_length,
1211+
vm_error: coreTx.vm_error,
12091212
};
12101213
extractTransactionPayload(parsedTx, dbTx);
12111214
return dbTx;

src/datastore/pg-write-store.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,6 +1896,7 @@ export class PgWriteStore extends PgStore {
18961896
execution_cost_runtime: tx.execution_cost_runtime,
18971897
execution_cost_write_count: tx.execution_cost_write_count,
18981898
execution_cost_write_length: tx.execution_cost_write_length,
1899+
vm_error: tx.vm_error ?? null,
18991900
}));
19001901

19011902
let count = 0;
@@ -3492,6 +3493,7 @@ export class PgWriteStore extends PgStore {
34923493
execution_cost_runtime: tx.execution_cost_runtime,
34933494
execution_cost_write_count: tx.execution_cost_write_count,
34943495
execution_cost_write_length: tx.execution_cost_write_length,
3496+
vm_error: tx.vm_error ?? null,
34953497
}));
34963498
await sql`INSERT INTO txs ${sql(values)}`;
34973499
}

src/event-stream/core-node-message.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,7 @@ export interface CoreNodeTxMessage {
245245
microblock_sequence: number | null;
246246
microblock_hash: string | null;
247247
microblock_parent_hash: string | null;
248+
vm_error?: string | null;
248249
burnchain_op?: BurnchainOp | null;
249250
}
250251

tests/api/address.test.ts

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,7 @@ describe('address tests', () => {
300300
execution_cost_runtime: 3,
301301
execution_cost_write_count: 4,
302302
execution_cost_write_length: 5,
303+
vm_error: null,
303304
},
304305
stx_sent: '1339',
305306
stx_received: '0',
@@ -390,6 +391,7 @@ describe('address tests', () => {
390391
execution_cost_runtime: 3,
391392
execution_cost_write_count: 4,
392393
execution_cost_write_length: 5,
394+
vm_error: null,
393395
},
394396
stx_sent: '1484',
395397
stx_received: '0',
@@ -454,6 +456,7 @@ describe('address tests', () => {
454456
execution_cost_runtime: 3,
455457
execution_cost_write_count: 4,
456458
execution_cost_write_length: 5,
459+
vm_error: null,
457460
},
458461
stx_sent: '1334',
459462
stx_received: '0',
@@ -792,6 +795,7 @@ describe('address tests', () => {
792795
execution_cost_runtime: 3,
793796
execution_cost_write_count: 4,
794797
execution_cost_write_length: 5,
798+
vm_error: null,
795799
},
796800
stx_sent: '0',
797801
stx_received: '105',
@@ -867,6 +871,7 @@ describe('address tests', () => {
867871
execution_cost_runtime: 3,
868872
execution_cost_write_count: 4,
869873
execution_cost_write_length: 5,
874+
vm_error: null,
870875
},
871876
stx_sent: '0',
872877
stx_received: '105',
@@ -957,6 +962,7 @@ describe('address tests', () => {
957962
execution_cost_runtime: 3,
958963
execution_cost_write_count: 4,
959964
execution_cost_write_length: 5,
965+
vm_error: null,
960966
},
961967
stx_sent: '0',
962968
stx_received: '15',
@@ -1950,6 +1956,7 @@ describe('address tests', () => {
19501956
execution_cost_runtime: 0,
19511957
execution_cost_write_count: 0,
19521958
execution_cost_write_length: 0,
1959+
vm_error: null,
19531960
},
19541961
{
19551962
tx_id: '0x1234',
@@ -1993,6 +2000,7 @@ describe('address tests', () => {
19932000
execution_cost_runtime: 0,
19942001
execution_cost_write_count: 0,
19952002
execution_cost_write_length: 0,
2003+
vm_error: null,
19962004
},
19972005
{
19982006
tx_id: '0x12340005',
@@ -2037,6 +2045,7 @@ describe('address tests', () => {
20372045
execution_cost_runtime: 0,
20382046
execution_cost_write_count: 0,
20392047
execution_cost_write_length: 0,
2048+
vm_error: null,
20402049
},
20412050
{
20422051
tx_id: '0x12340003',
@@ -2081,6 +2090,7 @@ describe('address tests', () => {
20812090
execution_cost_runtime: 0,
20822091
execution_cost_write_count: 0,
20832092
execution_cost_write_length: 0,
2093+
vm_error: null,
20842094
},
20852095
{
20862096
tx_id: '0x12340002',
@@ -2125,6 +2135,7 @@ describe('address tests', () => {
21252135
execution_cost_runtime: 0,
21262136
execution_cost_write_count: 0,
21272137
execution_cost_write_length: 0,
2138+
vm_error: null,
21282139
},
21292140
],
21302141
};
@@ -2199,6 +2210,7 @@ describe('address tests', () => {
21992210
execution_cost_runtime: 0,
22002211
execution_cost_write_count: 0,
22012212
execution_cost_write_length: 0,
2213+
vm_error: null,
22022214
},
22032215
],
22042216
};
@@ -2263,6 +2275,7 @@ describe('address tests', () => {
22632275
execution_cost_runtime: 0,
22642276
execution_cost_write_count: 0,
22652277
execution_cost_write_length: 0,
2278+
vm_error: null,
22662279
fee_rate: '10',
22672280
is_unanchored: false,
22682281
microblock_canonical: true,
@@ -2343,6 +2356,7 @@ describe('address tests', () => {
23432356
execution_cost_runtime: 0,
23442357
execution_cost_write_count: 0,
23452358
execution_cost_write_length: 0,
2359+
vm_error: null,
23462360
fee_rate: '10',
23472361
is_unanchored: false,
23482362
microblock_canonical: true,
@@ -2427,6 +2441,7 @@ describe('address tests', () => {
24272441
execution_cost_runtime: 0,
24282442
execution_cost_write_count: 0,
24292443
execution_cost_write_length: 0,
2444+
vm_error: null,
24302445
};
24312446

24322447
const blockTxsRows = await api.datastore.getBlockTxsRows(block.block_hash);
@@ -2438,7 +2453,7 @@ describe('address tests', () => {
24382453
abi: JSON.parse(contractCallResult1?.abi ?? ''),
24392454
}).toEqual({
24402455
...contractCall,
2441-
...{ abi: contractJsonAbi },
2456+
...{ abi: contractJsonAbi, vm_error: null },
24422457
});
24432458

24442459
const searchResult8 = await supertest(api.server).get(
@@ -2458,7 +2473,7 @@ describe('address tests', () => {
24582473
abi: JSON.parse(contractCallResult2?.abi ?? ''),
24592474
}).toEqual({
24602475
...contractCall,
2461-
...{ abi: contractJsonAbi },
2476+
...{ abi: contractJsonAbi, vm_error: null },
24622477
});
24632478
});
24642479

@@ -2518,6 +2533,7 @@ describe('address tests', () => {
25182533
microblock_hash: null,
25192534
microblock_parent_hash: null,
25202535
microblock_sequence: null,
2536+
vm_error: null,
25212537
execution_cost: {
25222538
read_count: 0,
25232539
read_length: 0,

tests/api/block.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ describe('block tests', () => {
127127
execution_cost_runtime: 0,
128128
execution_cost_write_count: 0,
129129
execution_cost_write_length: 0,
130+
vm_error: null,
130131
};
131132
await db.updateTx(client, tx);
132133

0 commit comments

Comments
 (0)