mirror of
https://github.com/alexgo-io/stacks-blockchain-api.git
synced 2026-04-28 21:05:36 +08:00
fix: handle Problematic status in /drop_mempool_tx event (#1790)
This commit is contained in:
@@ -2,5 +2,5 @@
|
|||||||
"title": "MempoolTransactionStatus",
|
"title": "MempoolTransactionStatus",
|
||||||
"description": "Status of the transaction",
|
"description": "Status of the transaction",
|
||||||
"type": "string",
|
"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
3
docs/generated.d.ts
vendored
@@ -569,7 +569,8 @@ export type MempoolTransactionStatus =
|
|||||||
| "dropped_replace_by_fee"
|
| "dropped_replace_by_fee"
|
||||||
| "dropped_replace_across_fork"
|
| "dropped_replace_across_fork"
|
||||||
| "dropped_too_expensive"
|
| "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
|
* 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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -161,6 +161,8 @@ function getTxStatusString(txStatus: DbTxStatus): TransactionStatus | MempoolTra
|
|||||||
return 'dropped_replace_across_fork';
|
return 'dropped_replace_across_fork';
|
||||||
case DbTxStatus.DroppedTooExpensive:
|
case DbTxStatus.DroppedTooExpensive:
|
||||||
return 'dropped_too_expensive';
|
return 'dropped_too_expensive';
|
||||||
|
case DbTxStatus.DroppedProblematic:
|
||||||
|
return 'dropped_problematic';
|
||||||
case DbTxStatus.DroppedStaleGarbageCollect:
|
case DbTxStatus.DroppedStaleGarbageCollect:
|
||||||
case DbTxStatus.DroppedApiGarbageCollect:
|
case DbTxStatus.DroppedApiGarbageCollect:
|
||||||
return 'dropped_stale_garbage_collect';
|
return 'dropped_stale_garbage_collect';
|
||||||
|
|||||||
@@ -117,6 +117,8 @@ export enum DbTxStatus {
|
|||||||
DroppedStaleGarbageCollect = -13,
|
DroppedStaleGarbageCollect = -13,
|
||||||
/** Dropped by the API (even though the Stacks node hadn't dropped it) because it exceeded maximum mempool age */
|
/** Dropped by the API (even though the Stacks node hadn't dropped it) because it exceeded maximum mempool age */
|
||||||
DroppedApiGarbageCollect = -14,
|
DroppedApiGarbageCollect = -14,
|
||||||
|
/** Transaction is problematic (e.g. a DDoS vector) and should be dropped. */
|
||||||
|
DroppedProblematic = -15,
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DbTxAnchorMode {
|
export enum DbTxAnchorMode {
|
||||||
|
|||||||
@@ -990,6 +990,8 @@ export function getTxDbStatus(
|
|||||||
return DbTxStatus.DroppedTooExpensive;
|
return DbTxStatus.DroppedTooExpensive;
|
||||||
case 'StaleGarbageCollect':
|
case 'StaleGarbageCollect':
|
||||||
return DbTxStatus.DroppedStaleGarbageCollect;
|
return DbTxStatus.DroppedStaleGarbageCollect;
|
||||||
|
case 'Problematic':
|
||||||
|
return DbTxStatus.DroppedProblematic;
|
||||||
default:
|
default:
|
||||||
throw new Error(`Unexpected tx status: ${txCoreStatus}`);
|
throw new Error(`Unexpected tx status: ${txCoreStatus}`);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1247,6 +1247,7 @@ export class PgStore extends BasePgStore {
|
|||||||
DbTxStatus.DroppedTooExpensive,
|
DbTxStatus.DroppedTooExpensive,
|
||||||
DbTxStatus.DroppedStaleGarbageCollect,
|
DbTxStatus.DroppedStaleGarbageCollect,
|
||||||
DbTxStatus.DroppedApiGarbageCollect,
|
DbTxStatus.DroppedApiGarbageCollect,
|
||||||
|
DbTxStatus.DroppedProblematic,
|
||||||
];
|
];
|
||||||
const resultQuery = await sql<(MempoolTxQueryResult & { count: number })[]>`
|
const resultQuery = await sql<(MempoolTxQueryResult & { count: number })[]>`
|
||||||
SELECT ${unsafeCols(sql, [
|
SELECT ${unsafeCols(sql, [
|
||||||
|
|||||||
@@ -301,7 +301,8 @@ export type CoreNodeDropMempoolTxReasonType =
|
|||||||
| 'ReplaceByFee'
|
| 'ReplaceByFee'
|
||||||
| 'ReplaceAcrossFork'
|
| 'ReplaceAcrossFork'
|
||||||
| 'TooExpensive'
|
| 'TooExpensive'
|
||||||
| 'StaleGarbageCollect';
|
| 'StaleGarbageCollect'
|
||||||
|
| 'Problematic';
|
||||||
|
|
||||||
export interface CoreNodeDropMempoolTxMessage {
|
export interface CoreNodeDropMempoolTxMessage {
|
||||||
dropped_txids: string[];
|
dropped_txids: string[];
|
||||||
|
|||||||
@@ -323,9 +323,14 @@ describe('mempool tests', () => {
|
|||||||
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
|
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
|
||||||
receipt_time: 1594307705,
|
receipt_time: 1594307705,
|
||||||
};
|
};
|
||||||
|
const mempoolTx6: DbMempoolTxRaw = {
|
||||||
|
...mempoolTx1,
|
||||||
|
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006',
|
||||||
|
receipt_time: 1594307706,
|
||||||
|
};
|
||||||
|
|
||||||
await db.updateMempoolTxs({
|
await db.updateMempoolTxs({
|
||||||
mempoolTxs: [mempoolTx1, mempoolTx2, mempoolTx3, mempoolTx4, mempoolTx5],
|
mempoolTxs: [mempoolTx1, mempoolTx2, mempoolTx3, mempoolTx4, mempoolTx5, mempoolTx6],
|
||||||
});
|
});
|
||||||
await db.dropMempoolTxs({
|
await db.dropMempoolTxs({
|
||||||
status: DbTxStatus.DroppedReplaceAcrossFork,
|
status: DbTxStatus.DroppedReplaceAcrossFork,
|
||||||
@@ -450,6 +455,31 @@ describe('mempool tests', () => {
|
|||||||
};
|
};
|
||||||
expect(JSON.parse(searchResult5.text)).toEqual(expectedResp5);
|
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(
|
const mempoolDroppedResult1 = await supertest(api.server).get(
|
||||||
'/extended/v1/tx/mempool/dropped'
|
'/extended/v1/tx/mempool/dropped'
|
||||||
);
|
);
|
||||||
@@ -458,6 +488,10 @@ describe('mempool tests', () => {
|
|||||||
expect(mempoolDroppedResult1.body).toEqual(
|
expect(mempoolDroppedResult1.body).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
results: expect.arrayContaining([
|
results: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006',
|
||||||
|
tx_status: 'dropped_problematic',
|
||||||
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
|
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
|
||||||
tx_status: 'dropped_stale_garbage_collect',
|
tx_status: 'dropped_stale_garbage_collect',
|
||||||
@@ -549,10 +583,14 @@ describe('mempool tests', () => {
|
|||||||
);
|
);
|
||||||
expect(mempoolDroppedResult2.status).toBe(200);
|
expect(mempoolDroppedResult2.status).toBe(200);
|
||||||
expect(mempoolDroppedResult2.type).toBe('application/json');
|
expect(mempoolDroppedResult2.type).toBe('application/json');
|
||||||
expect(mempoolDroppedResult2.body.results).toHaveLength(4);
|
expect(mempoolDroppedResult2.body.results).toHaveLength(5);
|
||||||
expect(mempoolDroppedResult2.body).toEqual(
|
expect(mempoolDroppedResult2.body).toEqual(
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
results: expect.arrayContaining([
|
results: expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000006',
|
||||||
|
tx_status: 'dropped_problematic',
|
||||||
|
}),
|
||||||
expect.objectContaining({
|
expect.objectContaining({
|
||||||
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
|
tx_id: '0x8912000000000000000000000000000000000000000000000000000000000005',
|
||||||
tx_status: 'dropped_stale_garbage_collect',
|
tx_status: 'dropped_stale_garbage_collect',
|
||||||
|
|||||||
Reference in New Issue
Block a user