fix: handle Problematic status in /drop_mempool_tx event (#1790)

This commit is contained in:
Matthew Little
2024-01-01 14:39:25 +01:00
committed by GitHub
parent eb36b33e54
commit ce9b38f051
8 changed files with 52 additions and 5 deletions

View File

@@ -2,5 +2,5 @@
"title": "MempoolTransactionStatus",
"description": "Status of the transaction",
"type": "string",
"enum": ["pending", "dropped_replace_by_fee", "dropped_replace_across_fork", "dropped_too_expensive", "dropped_stale_garbage_collect"]
"enum": ["pending", "dropped_replace_by_fee", "dropped_replace_across_fork", "dropped_too_expensive", "dropped_stale_garbage_collect", "dropped_problematic"]
}

3
docs/generated.d.ts vendored
View File

@@ -569,7 +569,8 @@ export type MempoolTransactionStatus =
| "dropped_replace_by_fee"
| "dropped_replace_across_fork"
| "dropped_too_expensive"
| "dropped_stale_garbage_collect";
| "dropped_stale_garbage_collect"
| "dropped_problematic";
/**
* Describes representation of a Type-1 Stacks 2.0 transaction. https://github.com/blockstack/stacks-blockchain/blob/master/sip/sip-005-blocks-and-transactions.md#type-1-instantiating-a-smart-contract
*/

View File

@@ -161,6 +161,8 @@ function getTxStatusString(txStatus: DbTxStatus): TransactionStatus | MempoolTra
return 'dropped_replace_across_fork';
case DbTxStatus.DroppedTooExpensive:
return 'dropped_too_expensive';
case DbTxStatus.DroppedProblematic:
return 'dropped_problematic';
case DbTxStatus.DroppedStaleGarbageCollect:
case DbTxStatus.DroppedApiGarbageCollect:
return 'dropped_stale_garbage_collect';

View File

@@ -117,6 +117,8 @@ export enum DbTxStatus {
DroppedStaleGarbageCollect = -13,
/** Dropped by the API (even though the Stacks node hadn't dropped it) because it exceeded maximum mempool age */
DroppedApiGarbageCollect = -14,
/** Transaction is problematic (e.g. a DDoS vector) and should be dropped. */
DroppedProblematic = -15,
}
export enum DbTxAnchorMode {

View File

@@ -990,6 +990,8 @@ export function getTxDbStatus(
return DbTxStatus.DroppedTooExpensive;
case 'StaleGarbageCollect':
return DbTxStatus.DroppedStaleGarbageCollect;
case 'Problematic':
return DbTxStatus.DroppedProblematic;
default:
throw new Error(`Unexpected tx status: ${txCoreStatus}`);
}

View File

@@ -1247,6 +1247,7 @@ export class PgStore extends BasePgStore {
DbTxStatus.DroppedTooExpensive,
DbTxStatus.DroppedStaleGarbageCollect,
DbTxStatus.DroppedApiGarbageCollect,
DbTxStatus.DroppedProblematic,
];
const resultQuery = await sql<(MempoolTxQueryResult & { count: number })[]>`
SELECT ${unsafeCols(sql, [

View File

@@ -301,7 +301,8 @@ export type CoreNodeDropMempoolTxReasonType =
| 'ReplaceByFee'
| 'ReplaceAcrossFork'
| 'TooExpensive'
| 'StaleGarbageCollect';
| 'StaleGarbageCollect'
| 'Problematic';
export interface CoreNodeDropMempoolTxMessage {
dropped_txids: string[];

View File

@@ -323,9 +323,14 @@ describe('mempool tests', () => {
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
receipt_time: 1594307705,
};
const mempoolTx6: DbMempoolTxRaw = {
...mempoolTx1,
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006',
receipt_time: 1594307706,
};
await db.updateMempoolTxs({
mempoolTxs: [mempoolTx1, mempoolTx2, mempoolTx3, mempoolTx4, mempoolTx5],
mempoolTxs: [mempoolTx1, mempoolTx2, mempoolTx3, mempoolTx4, mempoolTx5, mempoolTx6],
});
await db.dropMempoolTxs({
status: DbTxStatus.DroppedReplaceAcrossFork,
@@ -450,6 +455,31 @@ describe('mempool tests', () => {
};
expect(JSON.parse(searchResult5.text)).toEqual(expectedResp5);
await db.dropMempoolTxs({
status: DbTxStatus.DroppedProblematic,
txIds: [mempoolTx6.tx_id],
});
const searchResult6 = await supertest(api.server).get(`/extended/v1/tx/${mempoolTx6.tx_id}`);
expect(searchResult6.status).toBe(200);
expect(searchResult6.type).toBe('application/json');
const expectedResp6 = {
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006',
tx_status: 'dropped_problematic',
tx_type: 'coinbase',
fee_rate: '1234',
nonce: 0,
anchor_mode: 'any',
sender_address: 'sender-addr',
sponsor_address: 'sponsor-addr',
sponsored: true,
post_condition_mode: 'allow',
post_conditions: [],
receipt_time: 1594307706,
receipt_time_iso: '2020-07-09T15:15:06.000Z',
coinbase_payload: { data: '0x636f696e62617365206869', alt_recipient: null },
};
expect(JSON.parse(searchResult6.text)).toEqual(expectedResp6);
const mempoolDroppedResult1 = await supertest(api.server).get(
'/extended/v1/tx/mempool/dropped'
);
@@ -458,6 +488,10 @@ describe('mempool tests', () => {
expect(mempoolDroppedResult1.body).toEqual(
expect.objectContaining({
results: expect.arrayContaining([
expect.objectContaining({
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006',
tx_status: 'dropped_problematic',
}),
expect.objectContaining({
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
tx_status: 'dropped_stale_garbage_collect',
@@ -549,10 +583,14 @@ describe('mempool tests', () => {
);
expect(mempoolDroppedResult2.status).toBe(200);
expect(mempoolDroppedResult2.type).toBe('application/json');
expect(mempoolDroppedResult2.body.results).toHaveLength(4);
expect(mempoolDroppedResult2.body.results).toHaveLength(5);
expect(mempoolDroppedResult2.body).toEqual(
expect.objectContaining({
results: expect.arrayContaining([
expect.objectContaining({
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006',
tx_status: 'dropped_problematic',
}),
expect.objectContaining({
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
tx_status: 'dropped_stale_garbage_collect',