Skip to content

Commit 6b0c0b0

Browse files
authored
feat!: add support for sponsor nonce in transactions (#1140)
* fix: add support for sponsor_nonce for txs and mempool transactions * fix: fixed incorrect last executed nonce * test: add test for nonces endpoint * style: fixed style nit * refactor: improve condition * fix: fixed missing nonce to add support for sponsor_nonce
1 parent 508afc7 commit 6b0c0b0

File tree

8 files changed

+309
-15
lines changed

8 files changed

+309
-15
lines changed

docs/entities/transactions/base-transaction.schema.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@
3131
"type": "string",
3232
"description": "Address of the transaction initiator"
3333
},
34+
"sponsor_nonce": {
35+
"type": "integer"
36+
},
3437
"sponsored": {
3538
"type": "boolean",
3639
"description": "Denotes whether the originating account is the same as the paying account"

docs/generated.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,7 @@ export interface BaseTransaction {
10811081
* Address of the transaction initiator
10821082
*/
10831083
sender_address: string;
1084+
sponsor_nonce?: number;
10841085
/**
10851086
* Denotes whether the originating account is the same as the paying account
10861087
*/

src/api/controllers/db-controller.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -651,6 +651,7 @@ function parseDbBaseTx(dbTx: DbTx | DbMempoolTx): BaseTransaction {
651651
const tx: BaseTransaction = {
652652
tx_id: dbTx.tx_id,
653653
nonce: dbTx.nonce,
654+
sponsor_nonce: dbTx.sponsor_nonce,
654655
fee_rate: dbTx.fee_rate.toString(10),
655656
sender_address: dbTx.sender_address,
656657
sponsored: dbTx.sponsored,

src/datastore/common.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,8 @@ export interface BaseTx {
136136
fee_rate: bigint;
137137
sender_address: string;
138138
sponsored: boolean;
139-
sponsor_address: string | undefined;
139+
sponsor_address?: string;
140+
sponsor_nonce?: number;
140141
nonce: number;
141142
tx_id: string;
142143
anchor_mode: DbTxAnchorMode;
@@ -1077,6 +1078,10 @@ export function createDbMempoolTxFromCoreMsg(msg: {
10771078
const dbTx: DbMempoolTx = {
10781079
pruned: false,
10791080
nonce: Number(msg.txData.auth.originCondition.nonce),
1081+
sponsor_nonce:
1082+
msg.txData.auth.typeId === TransactionAuthTypeID.Sponsored
1083+
? Number(msg.txData.auth.sponsorCondition.nonce)
1084+
: undefined,
10801085
tx_id: msg.txId,
10811086
raw_tx: msg.rawTx,
10821087
type_id: parseEnum(DbTxTypeId, msg.txData.payload.typeId as number),
@@ -1100,11 +1105,11 @@ export function createDbTxFromCoreMsg(msg: CoreNodeParsedTxMessage): DbTx {
11001105
const dbTx: DbTx = {
11011106
tx_id: coreTx.txid,
11021107
tx_index: coreTx.tx_index,
1103-
nonce: Number(
1108+
nonce: Number(parsedTx.auth.originCondition.nonce),
1109+
sponsor_nonce:
11041110
parsedTx.auth.typeId === TransactionAuthTypeID.Sponsored
1105-
? parsedTx.auth.sponsorCondition.nonce
1106-
: parsedTx.auth.originCondition.nonce
1107-
),
1111+
? Number(parsedTx.auth.sponsorCondition.nonce)
1112+
: undefined,
11081113
raw_tx: msg.raw_tx,
11091114
index_block_hash: msg.index_block_hash,
11101115
parent_index_block_hash: msg.parent_index_block_hash,

src/datastore/postgres-store.ts

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ function isPgConnectionError(error: any): string | false {
324324
const TX_COLUMNS = `
325325
-- required columns
326326
tx_id, raw_tx, tx_index, index_block_hash, parent_index_block_hash, block_hash, parent_block_hash, block_height, burn_block_time, parent_burn_block_time,
327-
type_id, anchor_mode, status, canonical, post_conditions, nonce, fee_rate, sponsored, sponsor_address, sender_address, origin_hash_mode,
327+
type_id, anchor_mode, status, canonical, post_conditions, nonce, fee_rate, sponsored, sponsor_nonce, sponsor_address, sender_address, origin_hash_mode,
328328
microblock_canonical, microblock_sequence, microblock_hash,
329329
330330
-- token-transfer tx columns
@@ -355,7 +355,7 @@ const TX_COLUMNS = `
355355
const MEMPOOL_TX_COLUMNS = `
356356
-- required columns
357357
pruned, tx_id, raw_tx, type_id, anchor_mode, status, receipt_time, receipt_block_height,
358-
post_conditions, nonce, fee_rate, sponsored, sponsor_address, sender_address, origin_hash_mode,
358+
post_conditions, nonce, fee_rate, sponsored, sponsor_nonce, sponsor_address, sender_address, origin_hash_mode,
359359
360360
-- token-transfer tx columns
361361
token_transfer_recipient_address, token_transfer_amount, token_transfer_memo,
@@ -416,6 +416,7 @@ function txColumns(tableName: string = 'txs'): string {
416416
'fee_rate',
417417
'sponsored',
418418
'sponsor_address',
419+
'sponsor_nonce',
419420
'sender_address',
420421
'origin_hash_mode',
421422
'microblock_canonical',
@@ -520,6 +521,7 @@ interface MempoolTxQueryResult {
520521
tx_id: Buffer;
521522

522523
nonce: number;
524+
sponsor_nonce?: number;
523525
type_id: number;
524526
anchor_mode: number;
525527
status: number;
@@ -571,6 +573,7 @@ interface TxQueryResult {
571573
burn_block_time: number;
572574
parent_burn_block_time: number;
573575
nonce: number;
576+
sponsor_nonce?: number;
574577
type_id: number;
575578
anchor_mode: number;
576579
status: number;
@@ -2008,22 +2011,55 @@ export class PgDataStore
20082011
`
20092012
SELECT MAX(nonce) nonce
20102013
FROM txs
2011-
WHERE ((sender_address = $1 AND sponsored = false) OR (sponsor_address = $1 AND sponsored= true))
2014+
WHERE sender_address = $1
20122015
AND canonical = true AND microblock_canonical = true
20132016
`,
20142017
[args.stxAddress]
20152018
);
2019+
2020+
const executedTxSponsorNonce = await client.query<{ nonce: number | null }>(
2021+
`
2022+
SELECT MAX(sponsor_nonce) nonce
2023+
FROM txs
2024+
WHERE sponsor_address = $1 AND sponsored = true
2025+
AND canonical = true AND microblock_canonical = true
2026+
`,
2027+
[args.stxAddress]
2028+
);
2029+
20162030
const mempoolTxNonce = await client.query<{ nonce: number | null }>(
20172031
`
20182032
SELECT MAX(nonce) nonce
20192033
FROM mempool_txs
2020-
WHERE ((sender_address = $1 AND sponsored = false) OR (sponsor_address = $1 AND sponsored= true))
2034+
WHERE sender_address = $1
2035+
AND pruned = false
2036+
`,
2037+
[args.stxAddress]
2038+
);
2039+
2040+
const mempoolTxSponsorNonce = await client.query<{ nonce: number | null }>(
2041+
`
2042+
SELECT MAX(sponsor_nonce) nonce
2043+
FROM mempool_txs
2044+
WHERE sponsor_address = $1 AND sponsored= true
20212045
AND pruned = false
20222046
`,
20232047
[args.stxAddress]
20242048
);
2025-
const lastExecutedTxNonce = executedTxNonce.rows[0]?.nonce ?? null;
2026-
const lastMempoolTxNonce = mempoolTxNonce.rows[0]?.nonce ?? null;
2049+
2050+
let lastExecutedTxNonce = executedTxNonce.rows[0]?.nonce ?? null;
2051+
const lastExecutedTxSponsorNonce = executedTxSponsorNonce.rows[0]?.nonce ?? null;
2052+
if (lastExecutedTxNonce != null || lastExecutedTxSponsorNonce != null) {
2053+
lastExecutedTxNonce = Math.max(lastExecutedTxNonce ?? 0, lastExecutedTxSponsorNonce ?? 0);
2054+
}
2055+
2056+
let lastMempoolTxNonce = mempoolTxNonce.rows[0]?.nonce ?? null;
2057+
const lastMempoolTxSponsorNonce = mempoolTxSponsorNonce.rows[0]?.nonce ?? null;
2058+
2059+
if (lastMempoolTxNonce != null || lastMempoolTxSponsorNonce != null) {
2060+
lastMempoolTxNonce = Math.max(lastMempoolTxNonce ?? 0, lastMempoolTxSponsorNonce ?? 0);
2061+
}
2062+
20272063
let possibleNextNonce = 0;
20282064
if (lastExecutedTxNonce !== null || lastMempoolTxNonce !== null) {
20292065
possibleNextNonce = Math.max(lastExecutedTxNonce ?? 0, lastMempoolTxNonce ?? 0) + 1;
@@ -2041,7 +2077,12 @@ export class PgDataStore
20412077
`
20422078
SELECT nonce
20432079
FROM mempool_txs
2044-
WHERE ((sender_address = $1 AND sponsored = false) OR (sponsor_address = $1 AND sponsored= true)) AND nonce = ANY($2)
2080+
WHERE sender_address = $1 AND nonce = ANY($2)
2081+
AND pruned = false
2082+
UNION
2083+
SELECT sponsor_nonce as nonce
2084+
FROM mempool_txs
2085+
WHERE sponsor_address = $1 AND sponsored= true AND sponsor_nonce = ANY($2)
20452086
AND pruned = false
20462087
`,
20472088
[args.stxAddress, expectedNonces]
@@ -3453,7 +3494,7 @@ export class PgDataStore
34533494
) values(
34543495
$1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19,
34553496
$20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32, $33, $34, $35, $36, $37,
3456-
$38, $39, $40, $41, $42
3497+
$38, $39, $40, $41, $42, $43
34573498
)
34583499
ON CONFLICT ON CONSTRAINT unique_tx_id_index_block_hash_microblock_hash DO NOTHING
34593500
`,
@@ -3476,6 +3517,7 @@ export class PgDataStore
34763517
tx.nonce,
34773518
tx.fee_rate,
34783519
tx.sponsored,
3520+
tx.sponsor_nonce,
34793521
tx.sponsor_address,
34803522
tx.sender_address,
34813523
tx.origin_hash_mode,
@@ -3514,7 +3556,7 @@ export class PgDataStore
35143556
`
35153557
INSERT INTO mempool_txs(
35163558
${MEMPOOL_TX_COLUMNS}
3517-
) values($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26)
3559+
) values($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17, $18, $19, $20, $21, $22, $23, $24, $25, $26, $27)
35183560
ON CONFLICT ON CONSTRAINT unique_tx_id
35193561
DO NOTHING
35203562
`,
@@ -3531,6 +3573,7 @@ export class PgDataStore
35313573
tx.nonce,
35323574
tx.fee_rate,
35333575
tx.sponsored,
3576+
tx.sponsor_nonce,
35343577
tx.sponsor_address,
35353578
tx.sender_address,
35363579
tx.origin_hash_mode,
@@ -3587,6 +3630,7 @@ export class PgDataStore
35873630
pruned: result.pruned,
35883631
tx_id: bufferToHexPrefixString(result.tx_id),
35893632
nonce: result.nonce,
3633+
sponsor_nonce: result.sponsor_nonce ?? undefined,
35903634
raw_tx: result.raw_tx,
35913635
type_id: result.type_id as DbTxTypeId,
35923636
anchor_mode: result.anchor_mode as DbTxAnchorMode,
@@ -3623,6 +3667,7 @@ export class PgDataStore
36233667
tx_id: bufferToHexPrefixString(result.tx_id),
36243668
tx_index: result.tx_index,
36253669
nonce: result.nonce,
3670+
sponsor_nonce: result.sponsor_nonce ?? undefined,
36263671
raw_tx: result.raw_tx,
36273672
index_block_hash: bufferToHexPrefixString(result.index_block_hash),
36283673
parent_index_block_hash: bufferToHexPrefixString(result.parent_index_block_hash),

src/migrations/1584619633448_txs.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,9 @@ export async function up(pgm: MigrationBuilder): Promise<void> {
7777
sponsor_address: {
7878
type: 'string'
7979
},
80+
sponsor_nonce: {
81+
type: 'integer'
82+
},
8083
sender_address: {
8184
type: 'string',
8285
notNull: true,

src/migrations/1591291822107_mempool_txs.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,9 @@ export async function up(pgm: MigrationBuilder): Promise<void> {
4545
sponsor_address: {
4646
type: 'string'
4747
},
48+
sponsor_nonce: {
49+
type: 'integer'
50+
},
4851
sender_address: {
4952
type: 'string',
5053
notNull: true,

0 commit comments

Comments
 (0)