Skip to content

Commit 07426a2

Browse files
authored
feat: include tenure-height in block responses (#2134)
* feat: include tenure-height in block responses * feat: add tenure_height to block endpoint responses * test: fix tests * test: add tests for tenure-height in block responses
1 parent 2cd69fa commit 07426a2

21 files changed

+258
-26
lines changed
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/* eslint-disable camelcase */
2+
3+
/** @param { import("node-pg-migrate").MigrationBuilder } pgm */
4+
exports.up = pgm => {
5+
6+
pgm.addColumn('blocks', {
7+
tenure_height: {
8+
type: 'integer',
9+
}
10+
});
11+
12+
};

src/api/controllers/db-controller.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -674,6 +674,8 @@ function parseDbBlock(
674674
dbBlock.block_time > 0
675675
? unixEpochToIso(dbBlock.block_time)
676676
: unixEpochToIso(dbBlock.burn_block_time),
677+
// If `tenure_height` is not available, but `signer_bitvec` is set we can safely assume it's same as `block_height` (epoch2.x rules)
678+
tenure_height: dbBlock.tenure_height ?? (dbBlock.signer_bitvec ? -1 : dbBlock.block_height),
677679
index_block_hash: dbBlock.index_block_hash,
678680
parent_block_hash: dbBlock.parent_block_hash,
679681
burn_block_time: dbBlock.burn_block_time,

src/api/routes/v2/helpers.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ export function parseDbNakamotoBlock(block: DbBlock): NakamotoBlock {
3131
hash: block.block_hash,
3232
block_time: block.block_time,
3333
block_time_iso: unixEpochToIso(block.block_time),
34+
// If `tenure_height` is not available, but `signer_bitvec` is set we can safely assume it's same as `block_height` (epoch2.x rules)
35+
tenure_height: block.tenure_height ?? (block.signer_bitvec ? -1 : block.block_height),
3436
index_block_hash: block.index_block_hash,
3537
parent_block_hash: block.parent_block_hash,
3638
parent_index_block_hash: block.parent_index_block_hash,

src/api/schemas/entities/block.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ export const BlockSchema = Type.Object(
1717
block_time_iso: Type.String({
1818
description: 'An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined.',
1919
}),
20+
tenure_height: Type.Integer({
21+
description: 'The tenure height (AKA coinbase height) of this block',
22+
}),
2023
index_block_hash: Type.String({
2124
description:
2225
'The only hash that can uniquely identify an anchored block or an unconfirmed state trie',
@@ -93,6 +96,9 @@ export const NakamotoBlockSchema = Type.Object({
9396
block_time_iso: Type.String({
9497
description: 'An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined.',
9598
}),
99+
tenure_height: Type.Integer({
100+
description: 'The tenure height (AKA coinbase height) of this block',
101+
}),
96102
index_block_hash: Type.String({
97103
description:
98104
'The only hash that can uniquely identify an anchored block or an unconfirmed state trie',

src/datastore/common.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export interface DbBlock {
2626
block_time: number;
2727
signer_bitvec: string | null;
2828
signer_signatures: string[] | null;
29+
tenure_height: number | null;
2930
}
3031

3132
/** An interface representing the microblock data that can be constructed _only_ from the /new_microblocks payload */
@@ -863,6 +864,7 @@ export interface BlockQueryResult {
863864
execution_cost_write_length: string;
864865
tx_count: number;
865866
signer_bitvec: string | null;
867+
tenure_height: number | null;
866868
}
867869

868870
export interface MicroblockQueryResult {
@@ -1288,6 +1290,7 @@ export interface BlockInsertValues {
12881290
tx_count: number;
12891291
signer_bitvec: string | null;
12901292
signer_signatures: PgBytea[] | null;
1293+
tenure_height: number | null;
12911294
}
12921295

12931296
export interface MicroblockInsertValues {

src/datastore/helpers.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ export const BLOCK_COLUMNS = [
186186
'execution_cost_write_length',
187187
'tx_count',
188188
'signer_bitvec',
189+
'tenure_height',
189190
];
190191

191192
export const MICROBLOCK_COLUMNS = [
@@ -465,7 +466,6 @@ export function parseFaucetRequestQueryResult(result: FaucetRequestQueryResult):
465466
}
466467

467468
export function parseBlockQueryResult(row: BlockQueryResult): DbBlock {
468-
// TODO(mb): is the tx_index preserved between microblocks and committed anchor blocks?
469469
const block: DbBlock = {
470470
block_hash: row.block_hash,
471471
index_block_hash: row.index_block_hash,
@@ -488,6 +488,7 @@ export function parseBlockQueryResult(row: BlockQueryResult): DbBlock {
488488
tx_count: row.tx_count,
489489
signer_bitvec: row.signer_bitvec,
490490
signer_signatures: null, // this field is not queried from db by default due to size constraints
491+
tenure_height: row.tenure_height,
491492
};
492493
return block;
493494
}

src/datastore/pg-write-store.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -483,6 +483,7 @@ export class PgWriteStore extends PgStore {
483483
tx_count: block.tx_count,
484484
signer_bitvec: block.signer_bitvec,
485485
signer_signatures: block.signer_signatures,
486+
tenure_height: block.tenure_height,
486487
};
487488
const result = await sql`
488489
INSERT INTO blocks ${sql(values)}
@@ -3384,6 +3385,7 @@ export class PgWriteStore extends PgStore {
33843385
tx_count: block.tx_count,
33853386
signer_bitvec: block.signer_bitvec,
33863387
signer_signatures: block.signer_signatures,
3388+
tenure_height: block.tenure_height,
33873389
}));
33883390
await sql`
33893391
INSERT INTO blocks ${sql(values)}

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,8 @@ export interface CoreNodeBlockMessage {
308308
pox_v3_unlock_height?: number;
309309
/** Available starting in epoch3, only included in blocks where the pox cycle rewards are first calculated */
310310
cycle_number?: number;
311+
/** AKA `coinbase_height`. In epoch2.x this is the same as `block_height`. In epoch3 this is used to track tenure heights. Only available starting in stacks-core 3.0.0.0.0-rc6 */
312+
tenure_height?: number | null;
311313
/** Available starting in epoch3, only included in blocks where the pox cycle rewards are first calculated */
312314
reward_set?: {
313315
pox_ustx_threshold: string; // "666720000000000"

src/event-stream/event-server.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1020,6 +1020,12 @@ export function parseNewBlockMessage(
10201020
}
10211021
);
10221022

1023+
if (typeof msg.tenure_height !== 'number' && msg.signer_bitvec) {
1024+
logger.warn(
1025+
`Nakamoto block ${msg.block_height} event payload has no tenure_height. Use stacks-core version 3.0.0.0.0-rc6 or newer!`
1026+
);
1027+
}
1028+
10231029
const dbBlock: DbBlock = {
10241030
canonical: true,
10251031
block_hash: msg.block_hash,
@@ -1042,6 +1048,7 @@ export function parseNewBlockMessage(
10421048
block_time: blockData.block_time,
10431049
signer_bitvec: signerBitvec,
10441050
signer_signatures: signerSignatures,
1051+
tenure_height: msg.tenure_height ?? null,
10451052
};
10461053

10471054
logger.debug(`Received block ${msg.block_hash} (${msg.block_height}) from node`, dbBlock);

tests/api/address.test.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ describe('address tests', () => {
8080
parent_microblock_hash: '',
8181
parent_microblock_sequence: 0,
8282
block_height: 1,
83+
tenure_height: 1,
8384
block_time: 39486,
8485
burn_block_time: 39486,
8586
burn_block_hash: '0x1234',
@@ -1157,6 +1158,7 @@ describe('address tests', () => {
11571158
parent_microblock_hash: '',
11581159
parent_microblock_sequence: 0,
11591160
block_height: 1,
1161+
tenure_height: 1,
11601162
block_time: 39486,
11611163
burn_block_time: 39486,
11621164
burn_block_hash: '0x1234',
@@ -2375,6 +2377,7 @@ describe('address tests', () => {
23752377
parent_microblock_hash: '',
23762378
parent_microblock_sequence: 0,
23772379
block_height: 1,
2380+
tenure_height: 1,
23782381
block_time: 1594647995,
23792382
burn_block_time: 1594647995,
23802383
burn_block_hash: '0x1234',

0 commit comments

Comments
 (0)