diff --git a/migrations/1729520843350_stacks_block_tenure-height.js b/migrations/1729520843350_stacks_block_tenure-height.js new file mode 100644 index 000000000..080c6a52d --- /dev/null +++ b/migrations/1729520843350_stacks_block_tenure-height.js @@ -0,0 +1,12 @@ +/* eslint-disable camelcase */ + +/** @param { import("node-pg-migrate").MigrationBuilder } pgm */ +exports.up = pgm => { + + pgm.addColumn('blocks', { + tenure_height: { + type: 'integer', + } + }); + +}; diff --git a/src/api/controllers/db-controller.ts b/src/api/controllers/db-controller.ts index 91724252c..19ddc73a7 100644 --- a/src/api/controllers/db-controller.ts +++ b/src/api/controllers/db-controller.ts @@ -674,6 +674,8 @@ function parseDbBlock( dbBlock.block_time > 0 ? unixEpochToIso(dbBlock.block_time) : unixEpochToIso(dbBlock.burn_block_time), + // If `tenure_height` is not available, but `signer_bitvec` is set we can safely assume it's same as `block_height` (epoch2.x rules) + tenure_height: dbBlock.tenure_height ?? (dbBlock.signer_bitvec ? -1 : dbBlock.block_height), index_block_hash: dbBlock.index_block_hash, parent_block_hash: dbBlock.parent_block_hash, burn_block_time: dbBlock.burn_block_time, diff --git a/src/api/routes/v2/helpers.ts b/src/api/routes/v2/helpers.ts index 66cf20691..5a5b0e8c4 100644 --- a/src/api/routes/v2/helpers.ts +++ b/src/api/routes/v2/helpers.ts @@ -31,6 +31,8 @@ export function parseDbNakamotoBlock(block: DbBlock): NakamotoBlock { hash: block.block_hash, block_time: block.block_time, block_time_iso: unixEpochToIso(block.block_time), + // If `tenure_height` is not available, but `signer_bitvec` is set we can safely assume it's same as `block_height` (epoch2.x rules) + tenure_height: block.tenure_height ?? (block.signer_bitvec ? -1 : block.block_height), index_block_hash: block.index_block_hash, parent_block_hash: block.parent_block_hash, parent_index_block_hash: block.parent_index_block_hash, diff --git a/src/api/schemas/entities/block.ts b/src/api/schemas/entities/block.ts index 77614edc3..57960f71a 100644 --- a/src/api/schemas/entities/block.ts +++ b/src/api/schemas/entities/block.ts @@ -17,6 +17,9 @@ export const BlockSchema = Type.Object( block_time_iso: Type.String({ description: 'An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined.', }), + tenure_height: Type.Integer({ + description: 'The tenure height (AKA coinbase height) of this block', + }), index_block_hash: Type.String({ description: 'The only hash that can uniquely identify an anchored block or an unconfirmed state trie', @@ -93,6 +96,9 @@ export const NakamotoBlockSchema = Type.Object({ block_time_iso: Type.String({ description: 'An ISO 8601 (YYYY-MM-DDTHH:mm:ss.sssZ) indicating when this block was mined.', }), + tenure_height: Type.Integer({ + description: 'The tenure height (AKA coinbase height) of this block', + }), index_block_hash: Type.String({ description: 'The only hash that can uniquely identify an anchored block or an unconfirmed state trie', diff --git a/src/datastore/common.ts b/src/datastore/common.ts index c0be3e42d..60ae03642 100644 --- a/src/datastore/common.ts +++ b/src/datastore/common.ts @@ -26,6 +26,7 @@ export interface DbBlock { block_time: number; signer_bitvec: string | null; signer_signatures: string[] | null; + tenure_height: number | null; } /** An interface representing the microblock data that can be constructed _only_ from the /new_microblocks payload */ @@ -863,6 +864,7 @@ export interface BlockQueryResult { execution_cost_write_length: string; tx_count: number; signer_bitvec: string | null; + tenure_height: number | null; } export interface MicroblockQueryResult { @@ -1288,6 +1290,7 @@ export interface BlockInsertValues { tx_count: number; signer_bitvec: string | null; signer_signatures: PgBytea[] | null; + tenure_height: number | null; } export interface MicroblockInsertValues { diff --git a/src/datastore/helpers.ts b/src/datastore/helpers.ts index 886d62001..bdaf3729f 100644 --- a/src/datastore/helpers.ts +++ b/src/datastore/helpers.ts @@ -186,6 +186,7 @@ export const BLOCK_COLUMNS = [ 'execution_cost_write_length', 'tx_count', 'signer_bitvec', + 'tenure_height', ]; export const MICROBLOCK_COLUMNS = [ @@ -465,7 +466,6 @@ export function parseFaucetRequestQueryResult(result: FaucetRequestQueryResult): } export function parseBlockQueryResult(row: BlockQueryResult): DbBlock { - // TODO(mb): is the tx_index preserved between microblocks and committed anchor blocks? const block: DbBlock = { block_hash: row.block_hash, index_block_hash: row.index_block_hash, @@ -488,6 +488,7 @@ export function parseBlockQueryResult(row: BlockQueryResult): DbBlock { tx_count: row.tx_count, signer_bitvec: row.signer_bitvec, signer_signatures: null, // this field is not queried from db by default due to size constraints + tenure_height: row.tenure_height, }; return block; } diff --git a/src/datastore/pg-write-store.ts b/src/datastore/pg-write-store.ts index 280d3a831..99cf8f0aa 100644 --- a/src/datastore/pg-write-store.ts +++ b/src/datastore/pg-write-store.ts @@ -483,6 +483,7 @@ export class PgWriteStore extends PgStore { tx_count: block.tx_count, signer_bitvec: block.signer_bitvec, signer_signatures: block.signer_signatures, + tenure_height: block.tenure_height, }; const result = await sql` INSERT INTO blocks ${sql(values)} @@ -3384,6 +3385,7 @@ export class PgWriteStore extends PgStore { tx_count: block.tx_count, signer_bitvec: block.signer_bitvec, signer_signatures: block.signer_signatures, + tenure_height: block.tenure_height, })); await sql` INSERT INTO blocks ${sql(values)} diff --git a/src/event-stream/core-node-message.ts b/src/event-stream/core-node-message.ts index 7233ef751..9c8b276de 100644 --- a/src/event-stream/core-node-message.ts +++ b/src/event-stream/core-node-message.ts @@ -308,6 +308,8 @@ export interface CoreNodeBlockMessage { pox_v3_unlock_height?: number; /** Available starting in epoch3, only included in blocks where the pox cycle rewards are first calculated */ cycle_number?: number; + /** 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 */ + tenure_height?: number | null; /** Available starting in epoch3, only included in blocks where the pox cycle rewards are first calculated */ reward_set?: { pox_ustx_threshold: string; // "666720000000000" diff --git a/src/event-stream/event-server.ts b/src/event-stream/event-server.ts index a957b5cc5..2a2154b73 100644 --- a/src/event-stream/event-server.ts +++ b/src/event-stream/event-server.ts @@ -1020,6 +1020,12 @@ export function parseNewBlockMessage( } ); + if (typeof msg.tenure_height !== 'number' && msg.signer_bitvec) { + logger.warn( + `Nakamoto block ${msg.block_height} event payload has no tenure_height. Use stacks-core version 3.0.0.0.0-rc6 or newer!` + ); + } + const dbBlock: DbBlock = { canonical: true, block_hash: msg.block_hash, @@ -1042,6 +1048,7 @@ export function parseNewBlockMessage( block_time: blockData.block_time, signer_bitvec: signerBitvec, signer_signatures: signerSignatures, + tenure_height: msg.tenure_height ?? null, }; logger.debug(`Received block ${msg.block_hash} (${msg.block_height}) from node`, dbBlock); diff --git a/tests/api/address.test.ts b/tests/api/address.test.ts index a9f1ba8e1..6f68f4a95 100644 --- a/tests/api/address.test.ts +++ b/tests/api/address.test.ts @@ -80,6 +80,7 @@ describe('address tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', @@ -1157,6 +1158,7 @@ describe('address tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', @@ -2375,6 +2377,7 @@ describe('address tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', diff --git a/tests/api/block.test.ts b/tests/api/block.test.ts index 39b49ee27..3d81c5307 100644 --- a/tests/api/block.test.ts +++ b/tests/api/block.test.ts @@ -74,6 +74,7 @@ describe('block tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1235, + tenure_height: 1235, block_time: 1594647996, burn_block_time: 1594647996, burn_block_hash: '0x1234', @@ -162,28 +163,28 @@ describe('block tests', () => { microblock_tx_count: {}, }; - expect(blockQuery.result).toEqual(expectedResp); + expect(blockQuery.result).toMatchObject(expectedResp); const fetchBlockByHash = await supertest(api.server).get( `/extended/v1/block/${block.block_hash}` ); expect(fetchBlockByHash.status).toBe(200); expect(fetchBlockByHash.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByHash.text)).toEqual(expectedResp); + expect(JSON.parse(fetchBlockByHash.text)).toMatchObject(expectedResp); const fetchBlockByHeight = await supertest(api.server).get( `/extended/v1/block/by_height/${block.block_height}` ); expect(fetchBlockByHeight.status).toBe(200); expect(fetchBlockByHeight.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByHeight.text)).toEqual(expectedResp); + expect(JSON.parse(fetchBlockByHeight.text)).toMatchObject(expectedResp); const fetchBlockByBurnBlockHeight = await supertest(api.server).get( `/extended/v1/block/by_burn_block_height/${block.burn_block_height}` ); expect(fetchBlockByBurnBlockHeight.status).toBe(200); expect(fetchBlockByBurnBlockHeight.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByBurnBlockHeight.text)).toEqual(expectedResp); + expect(JSON.parse(fetchBlockByBurnBlockHeight.text)).toMatchObject(expectedResp); const fetchBlockByInvalidBurnBlockHeight1 = await supertest(api.server).get( `/extended/v1/block/by_burn_block_height/999` @@ -216,7 +217,7 @@ describe('block tests', () => { ); expect(fetchBlockByBurnBlockHash.status).toBe(200); expect(fetchBlockByBurnBlockHash.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByBurnBlockHash.text)).toEqual(expectedResp); + expect(JSON.parse(fetchBlockByBurnBlockHash.text)).toMatchObject(expectedResp); const fetchBlockByInvalidBurnBlockHash = await supertest(api.server).get( `/extended/v1/block/by_burn_block_hash/0x000000` @@ -280,7 +281,103 @@ describe('block tests', () => { ], }; const result = await supertest(api.server).get(`/extended/v1/block/`); - expect(result.body).toEqual(expectedResp); + expect(result.body).toMatchObject(expectedResp); + }); + + test('block tenure-change', async () => { + const parentData = new TestBlockBuilder({ + block_height: 0, + }).build(); + + // Epoch2.x block (missing tenure-change in event payload) + const block1 = new TestBlockBuilder({ + block_height: 1, + block_hash: '0x1234', + index_block_hash: '0x123456', + parent_block_hash: parentData.block.block_hash, + parent_index_block_hash: parentData.block.index_block_hash, + }).build(); + block1.block.signer_bitvec = null; + block1.block.tenure_height = null; + + // Epoch2.x block + const block2 = new TestBlockBuilder({ + block_height: 2, + block_hash: '0x2234', + index_block_hash: '0x223456', + parent_block_hash: block1.block.block_hash, + parent_index_block_hash: block1.block.index_block_hash, + }).build(); + block2.block.signer_bitvec = null; + block2.block.tenure_height = 22; + + // Epoch3 block (missing tenure-change in event payload) + const block3 = new TestBlockBuilder({ + block_height: 3, + block_hash: '0x3234', + index_block_hash: '0x323456', + parent_block_hash: block2.block.block_hash, + parent_index_block_hash: block2.block.index_block_hash, + }).build(); + block3.block.signer_bitvec = '1111'; + block3.block.tenure_height = null; + + // Epoch3 block + const block4 = new TestBlockBuilder({ + block_height: 4, + block_hash: '0x4234', + index_block_hash: '0x423456', + parent_block_hash: block3.block.block_hash, + parent_index_block_hash: block3.block.index_block_hash, + }).build(); + block4.block.signer_bitvec = '1111'; + block4.block.tenure_height = 33; + + await db.update(parentData); + await db.update(block1); + await db.update(block2); + await db.update(block3); + await db.update(block4); + + const result1 = await supertest(api.server).get( + `/extended/v1/block/${block1.block.block_hash}` + ); + expect(result1.body).toMatchObject({ + canonical: true, + height: block1.block.block_height, + hash: block1.block.block_hash, + tenure_height: block1.block.block_height, // epoch2.x w/ missing tenure-change should default to block_height + }); + + const result2 = await supertest(api.server).get( + `/extended/v1/block/${block2.block.block_hash}` + ); + expect(result2.body).toMatchObject({ + canonical: true, + height: block2.block.block_height, + hash: block2.block.block_hash, + tenure_height: block2.block.tenure_height, // epoch2.x w/ tenure-change should use tenure_height + }); + + const result3 = await supertest(api.server).get( + `/extended/v1/block/${block3.block.block_hash}` + ); + expect(result3.body).toMatchObject({ + canonical: true, + height: block3.block.block_height, + hash: block3.block.block_hash, + tenure_height: -1, // epoch3 w/ missing tenure-change should return -1 to indicate problem + }); + + const result4 = await supertest(api.server).get( + `/extended/v1/block/${block4.block.block_hash}` + ); + expect(result4.body).toMatchObject({ + canonical: true, + height: block4.block.block_height, + hash: block4.block.block_hash, + tenure_height: block4.block.tenure_height, // epoch3 w/ tenure-change should use tenure_height + }); }); test('/block signer signatures', async () => { @@ -335,7 +432,7 @@ describe('block tests', () => { ], }; const result = await supertest(api.server).get(`/extended/v1/block/`); - expect(result.body).toEqual(expectedResp); + expect(result.body).toMatchObject(expectedResp); const sigReq = await supertest(api.server).get( `/extended/v2/blocks/${block1.block.block_height}/signer-signatures?limit=3&offset=70` @@ -544,7 +641,7 @@ describe('block tests', () => { ); expect(fetch1.status).toBe(200); expect(fetch1.type).toBe('application/json'); - expect(JSON.parse(fetch1.text)).toEqual(expectedResp1); + expect(JSON.parse(fetch1.text)).toMatchObject(expectedResp1); // Confirm the first microblock, but orphan the second const block2 = new TestBlockBuilder({ @@ -594,7 +691,7 @@ describe('block tests', () => { expect(fetch2.status).toBe(200); expect(fetch2.type).toBe('application/json'); - expect(JSON.parse(fetch2.text)).toEqual(expectedResp2); + expect(JSON.parse(fetch2.text)).toMatchObject(expectedResp2); }); test('blocks v2 filtered by burn block', async () => { @@ -655,14 +752,14 @@ describe('block tests', () => { let json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); expect(json.total).toEqual(5); - expect(json.results[0]).toStrictEqual(block5); + expect(json.results[0]).toMatchObject(block5); // Filter by burn height fetch = await supertest(api.server).get(`/extended/v2/burn-blocks/700000/blocks`); json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); expect(json.total).toEqual(5); - expect(json.results[0]).toStrictEqual(block5); + expect(json.results[0]).toMatchObject(block5); // Get latest block const block8 = { @@ -690,7 +787,7 @@ describe('block tests', () => { json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); expect(json.total).toEqual(3); - expect(json.results[0]).toStrictEqual(block8); + expect(json.results[0]).toMatchObject(block8); // Block hashes are validated fetch = await supertest(api.server).get(`/extended/v2/burn-blocks/testvalue/blocks`); @@ -901,6 +998,7 @@ describe('block tests', () => { }); test('blocks v2 retrieved by hash or height', async () => { + const blocks: DataStoreBlockUpdateData[] = []; for (let i = 1; i < 6; i++) { const block = new TestBlockBuilder({ block_height: i, @@ -917,6 +1015,14 @@ describe('block tests', () => { }) .addTx({ tx_id: `0x000${i}` }) .build(); + blocks.push(block); + } + + // set tenure-height on last block + const testTenureHeight = 4555; + blocks.slice(-1)[0].block.tenure_height = testTenureHeight; + + for (const block of blocks) { await db.update(block); } @@ -941,17 +1047,18 @@ describe('block tests', () => { parent_block_hash: '0x0000000000000000000000000000000000000000000000000000000000000004', parent_index_block_hash: '0x0000000000000000000000000000000000000000000000000000000000000114', tx_count: 1, + tenure_height: testTenureHeight, }; let fetch = await supertest(api.server).get(`/extended/v2/blocks/latest`); let json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); - expect(json).toStrictEqual(block5); + expect(json).toMatchObject(block5); // Get by height fetch = await supertest(api.server).get(`/extended/v2/blocks/5`); json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); - expect(json).toStrictEqual(block5); + expect(json).toMatchObject(block5); // Get by hash fetch = await supertest(api.server).get( @@ -959,7 +1066,7 @@ describe('block tests', () => { ); json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); - expect(json).toStrictEqual(block5); + expect(json).toMatchObject(block5); // Get by index block hash fetch = await supertest(api.server).get( @@ -967,7 +1074,7 @@ describe('block tests', () => { ); json = JSON.parse(fetch.text); expect(fetch.status).toBe(200); - expect(json).toStrictEqual(block5); + expect(json).toMatchObject(block5); }); test('blocks v2 retrieved by digit-only hash', async () => { diff --git a/tests/api/cache-control.test.ts b/tests/api/cache-control.test.ts index 09cadd5b8..8a083f606 100644 --- a/tests/api/cache-control.test.ts +++ b/tests/api/cache-control.test.ts @@ -47,6 +47,7 @@ describe('cache-control tests', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647996, burn_block_time: 1594647996, burn_block_hash: '0x1234', @@ -154,14 +155,14 @@ describe('cache-control tests', () => { microblock_tx_count: {}, }; - expect(blockQuery.result).toEqual(expectedResp1); + expect(blockQuery.result).toMatchObject(expectedResp1); const fetchBlockByHash1 = await supertest(api.server).get( `/extended/v1/block/${block1.block_hash}` ); expect(fetchBlockByHash1.status).toBe(200); expect(fetchBlockByHash1.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByHash1.text)).toEqual(expectedResp1); + expect(JSON.parse(fetchBlockByHash1.text)).toMatchObject(expectedResp1); expect(fetchBlockByHash1.headers['etag']).toBe(`"${block1.index_block_hash}"`); const fetchBlockByHashCached1 = await supertest(api.server) @@ -175,7 +176,7 @@ describe('cache-control tests', () => { .set('If-None-Match', '"0x12345678"'); expect(fetchBlockByHashCacheMiss.status).toBe(200); expect(fetchBlockByHashCacheMiss.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByHashCacheMiss.text)).toEqual(expectedResp1); + expect(JSON.parse(fetchBlockByHashCacheMiss.text)).toMatchObject(expectedResp1); expect(fetchBlockByHashCacheMiss.headers['etag']).toBe(`"${block1.index_block_hash}"`); const fetchBlockByHeight = await supertest(api.server).get( @@ -183,7 +184,7 @@ describe('cache-control tests', () => { ); expect(fetchBlockByHeight.status).toBe(200); expect(fetchBlockByHeight.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByHeight.text)).toEqual(expectedResp1); + expect(JSON.parse(fetchBlockByHeight.text)).toMatchObject(expectedResp1); expect(fetchBlockByHeight.headers['etag']).toBe(`"${block1.index_block_hash}"`); const fetchBlockByHeightCached = await supertest(api.server) @@ -197,7 +198,7 @@ describe('cache-control tests', () => { .set('If-None-Match', '"0x12345678"'); expect(fetchBlockByHashCacheMiss.status).toBe(200); expect(fetchBlockByHeightCacheMiss.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByHeightCacheMiss.text)).toEqual(expectedResp1); + expect(JSON.parse(fetchBlockByHeightCacheMiss.text)).toMatchObject(expectedResp1); expect(fetchBlockByHeightCacheMiss.headers['etag']).toBe(`"${block1.index_block_hash}"`); const fetchStxSupplyResp1 = expect.objectContaining({ total_stx: expect.any(String) }); @@ -330,7 +331,7 @@ describe('cache-control tests', () => { ); expect(fetchBlockByHash2.status).toBe(200); expect(fetchBlockByHash2.type).toBe('application/json'); - expect(JSON.parse(fetchBlockByHash2.text)).toEqual(expectedResp2); + expect(JSON.parse(fetchBlockByHash2.text)).toMatchObject(expectedResp2); expect(fetchBlockByHash2.headers['etag']).toBe(`"${mb1.microblock_hash}"`); const fetchBlockByHashCached2 = await supertest(api.server) diff --git a/tests/api/datastore.test.ts b/tests/api/datastore.test.ts index 71000c837..e2f4174ae 100644 --- a/tests/api/datastore.test.ts +++ b/tests/api/datastore.test.ts @@ -266,6 +266,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -435,6 +436,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -609,6 +611,7 @@ describe('postgres datastore', () => { parent_block_hash: '0xff0011', parent_microblock_hash: '0x00', block_height: 1235, + tenure_height: 1235, block_time: 94869287, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -681,6 +684,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -946,6 +950,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 2, + tenure_height: 2, block_time: 1594647996, burn_block_time: 1594647996, burn_block_hash: '0x1235', @@ -1022,6 +1027,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -1997,6 +2003,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2082,6 +2089,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2172,6 +2180,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2270,6 +2279,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2412,6 +2422,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2502,6 +2513,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2591,6 +2603,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2679,6 +2692,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2753,6 +2767,7 @@ describe('postgres datastore', () => { parent_block_hash: '0xff0011', parent_microblock_hash: '0x00', block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -3128,6 +3143,7 @@ describe('postgres datastore', () => { parent_block_hash: '0x00', parent_microblock_hash: '0x00', block_height: 1, + tenure_height: 1, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3151,6 +3167,7 @@ describe('postgres datastore', () => { parent_block_hash: block1.block_hash, parent_microblock_hash: '0x00', block_height: 2, + tenure_height: 2, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3174,6 +3191,7 @@ describe('postgres datastore', () => { parent_block_hash: block2.block_hash, parent_microblock_hash: '0x00', block_height: 3, + tenure_height: 3, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3203,6 +3221,7 @@ describe('postgres datastore', () => { parent_block_hash: block3B.block_hash, parent_microblock_hash: '0x00', block_height: 4, + tenure_height: 4, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3226,6 +3245,7 @@ describe('postgres datastore', () => { parent_block_hash: block3.block_hash, parent_microblock_hash: '0x00', block_height: 4, + tenure_height: 4, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3249,6 +3269,7 @@ describe('postgres datastore', () => { parent_block_hash: block4.block_hash, parent_microblock_hash: '0x00', block_height: 5, + tenure_height: 5, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3272,6 +3293,7 @@ describe('postgres datastore', () => { parent_block_hash: block5.block_hash, parent_microblock_hash: '0x00', block_height: 6, + tenure_height: 6, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3465,6 +3487,7 @@ describe('postgres datastore', () => { parent_block_hash: '0x00', parent_microblock_hash: '0x00', block_height: 1, + tenure_height: 1, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3488,6 +3511,7 @@ describe('postgres datastore', () => { parent_block_hash: block1.block_hash, parent_microblock_hash: '0x00', block_height: 2, + tenure_height: 2, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3511,6 +3535,7 @@ describe('postgres datastore', () => { parent_block_hash: block2.block_hash, parent_microblock_hash: '0x00', block_height: 3, + tenure_height: 3, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3540,6 +3565,7 @@ describe('postgres datastore', () => { parent_block_hash: block3.block_hash, parent_microblock_hash: '0x00', block_height: 4, + tenure_height: 4, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3676,6 +3702,7 @@ describe('postgres datastore', () => { parent_block_hash: block4.block_hash, parent_microblock_hash: '0x00', block_height: 5, + tenure_height: 5, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3758,6 +3785,7 @@ describe('postgres datastore', () => { parent_block_hash: '0x00', parent_microblock_hash: '0x00', block_height: 1, + tenure_height: 1, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -3781,6 +3809,7 @@ describe('postgres datastore', () => { parent_block_hash: block1.block_hash, parent_microblock_hash: '0x00', block_height: 2, + tenure_height: 2, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4062,6 +4091,7 @@ describe('postgres datastore', () => { parent_block_hash: block2.block_hash, parent_microblock_hash: '0x00', block_height: 3, + tenure_height: 3, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4087,6 +4117,7 @@ describe('postgres datastore', () => { parent_block_hash: block1.block_hash, parent_microblock_hash: '0x00', block_height: 2, + tenure_height: 2, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4299,6 +4330,7 @@ describe('postgres datastore', () => { parent_block_hash: block2b.block_hash, parent_microblock_hash: '0x00', block_height: 3, + tenure_height: 3, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4341,6 +4373,7 @@ describe('postgres datastore', () => { parent_block_hash: block3b.block_hash, parent_microblock_hash: '0x00', block_height: 4, + tenure_height: 4, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4452,6 +4485,7 @@ describe('postgres datastore', () => { parent_block_hash: '0x00', parent_microblock_hash: '0x00', block_height: 1, + tenure_height: 1, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4476,6 +4510,7 @@ describe('postgres datastore', () => { parent_block_hash: block1.block_hash, parent_microblock_hash: '0x00', block_height: 2, + tenure_height: 2, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4500,6 +4535,7 @@ describe('postgres datastore', () => { parent_block_hash: block1.block_hash, parent_microblock_hash: '0x00', block_height: 2, + tenure_height: 2, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4524,6 +4560,7 @@ describe('postgres datastore', () => { parent_block_hash: block2.block_hash, parent_microblock_hash: '0x00', block_height: 3, + tenure_height: 3, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4548,6 +4585,7 @@ describe('postgres datastore', () => { parent_block_hash: block2b.block_hash, parent_microblock_hash: '0x00', block_height: 3, + tenure_height: 3, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -4572,6 +4610,7 @@ describe('postgres datastore', () => { parent_block_hash: block3b.block_hash, parent_microblock_hash: '0x00', block_height: 4, + tenure_height: 4, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', @@ -5071,6 +5110,7 @@ describe('postgres datastore', () => { parent_block_hash: '0xff0011', parent_microblock_hash: '0x00', block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -5159,6 +5199,7 @@ describe('postgres datastore', () => { parent_block_hash: '0xff0011', parent_microblock_hash: '0x00', block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -5246,6 +5287,7 @@ describe('postgres datastore', () => { parent_block_hash: '0xff0011', parent_microblock_hash: '0x00', block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -5405,6 +5447,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -5468,6 +5511,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -5532,6 +5576,7 @@ describe('postgres datastore', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -5595,6 +5640,7 @@ describe('postgres datastore', () => { parent_block_hash: '0xff0011', parent_microblock_hash: '0x00', block_height: 1235, + tenure_height: 1235, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -5706,6 +5752,7 @@ describe('postgres datastore', () => { parent_block_hash: '0xff0011', parent_microblock_hash: '0x00', block_height: 1235, + tenure_height: 1235, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', diff --git a/tests/api/mempool.test.ts b/tests/api/mempool.test.ts index 648dbcc9d..410d099da 100644 --- a/tests/api/mempool.test.ts +++ b/tests/api/mempool.test.ts @@ -560,6 +560,7 @@ describe('mempool tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 2, + tenure_height: 2, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', @@ -1341,6 +1342,7 @@ describe('mempool tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -1417,6 +1419,7 @@ describe('mempool tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -1645,6 +1648,7 @@ describe('mempool tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 2, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', @@ -1668,6 +1672,7 @@ describe('mempool tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 2, + tenure_height: 2, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', @@ -1794,6 +1799,7 @@ describe('mempool tests', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', @@ -1817,6 +1823,7 @@ describe('mempool tests', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234bb', @@ -1840,6 +1847,7 @@ describe('mempool tests', () => { parent_microblock_hash: '0x00', parent_microblock_sequence: 0, block_height: 2, + tenure_height: 2, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', diff --git a/tests/api/microblock.test.ts b/tests/api/microblock.test.ts index 8d52de43e..a53064c67 100644 --- a/tests/api/microblock.test.ts +++ b/tests/api/microblock.test.ts @@ -273,6 +273,7 @@ describe('microblock tests', () => { parent_block_hash: '0x00', parent_microblock_hash: '', block_height: 1, + tenure_height: 1, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', diff --git a/tests/api/other.test.ts b/tests/api/other.test.ts index f3a0a481f..831877ffa 100644 --- a/tests/api/other.test.ts +++ b/tests/api/other.test.ts @@ -49,6 +49,7 @@ describe('other tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', diff --git a/tests/api/search.test.ts b/tests/api/search.test.ts index c39ad4be0..6cb5097f0 100644 --- a/tests/api/search.test.ts +++ b/tests/api/search.test.ts @@ -51,6 +51,7 @@ describe('search tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1235, + tenure_height: 1235, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -264,6 +265,7 @@ describe('search tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -405,7 +407,7 @@ describe('search tests', () => { metadata: blockMetadata, }, }; - expect(JSON.parse(searchResult1.text)).toEqual(expectedResp1); + expect(JSON.parse(searchResult1.text)).toMatchObject(expectedResp1); // test without 0x-prefix const searchResult2 = await supertest(api.server).get( @@ -428,7 +430,7 @@ describe('search tests', () => { metadata: blockMetadata, }, }; - expect(JSON.parse(searchResult2.text)).toEqual(expectedResp2); + expect(JSON.parse(searchResult2.text)).toMatchObject(expectedResp2); // test whitespace const searchResult3 = await supertest(api.server).get( @@ -451,7 +453,7 @@ describe('search tests', () => { metadata: blockMetadata, }, }; - expect(JSON.parse(searchResult3.text)).toEqual(expectedResp3); + expect(JSON.parse(searchResult3.text)).toMatchObject(expectedResp3); // test mempool tx search const searchResult4 = await supertest(api.server).get( @@ -605,6 +607,7 @@ describe('search tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 100123123, + tenure_height: 100123123, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', @@ -1051,6 +1054,7 @@ describe('search tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 39486, burn_block_time: 39486, burn_block_hash: '0x1234', diff --git a/tests/api/smart-contract.test.ts b/tests/api/smart-contract.test.ts index 04483ef8a..9ac0f4a6b 100644 --- a/tests/api/smart-contract.test.ts +++ b/tests/api/smart-contract.test.ts @@ -51,6 +51,7 @@ describe('smart contract tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647996, burn_block_time: 1594647996, burn_block_hash: '0x1234', @@ -205,6 +206,7 @@ describe('smart contract tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647996, burn_block_time: 1594647996, burn_block_hash: '0x1234', @@ -318,6 +320,7 @@ describe('smart contract tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647996, burn_block_time: 1594647996, burn_block_hash: '0x1234', @@ -429,6 +432,7 @@ describe('smart contract tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647996, burn_block_time: 1594647996, burn_block_hash: '0x1235', diff --git a/tests/api/tx.test.ts b/tests/api/tx.test.ts index db06fa588..b4d333909 100644 --- a/tests/api/tx.test.ts +++ b/tests/api/tx.test.ts @@ -145,6 +145,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1637003433, burn_block_time: 1637003433, burn_block_hash: '0x0000000000000000000342c6f7e9313ffa6f0a92618edaf86351ca265aee1c7a', @@ -343,6 +344,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -507,6 +509,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -654,6 +657,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -801,6 +805,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -994,6 +999,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647997, burn_block_time: 1594647997, burn_block_hash: '0x1234ab', @@ -1196,6 +1202,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -1400,6 +1407,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -1654,6 +1662,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -1808,6 +1817,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647995, burn_block_time: 1594647995, burn_block_hash: '0x1234', @@ -2649,6 +2659,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -2770,6 +2781,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -3427,6 +3439,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1594647996, burn_block_time: 1594647996, burn_block_hash: '0x1234', @@ -3685,6 +3698,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 1637003433, burn_block_time: 1637003433, burn_block_hash: '0x0000000000000000000342c6f7e9313ffa6f0a92618edaf86351ca265aee1c7a', @@ -4024,6 +4038,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', @@ -4227,6 +4242,7 @@ describe('tx tests', () => { parent_microblock_hash: '', parent_microblock_sequence: 0, block_height: 1, + tenure_height: 1, block_time: 94869286, burn_block_time: 94869286, burn_block_hash: '0x1234', diff --git a/tests/api/v2-proxy.test.ts b/tests/api/v2-proxy.test.ts index 6fd2358ba..a60564fa6 100644 --- a/tests/api/v2-proxy.test.ts +++ b/tests/api/v2-proxy.test.ts @@ -63,6 +63,7 @@ describe('v2-proxy tests', () => { parent_block_hash: '0x00', parent_microblock_hash: '', block_height: 1, + tenure_height: 1, block_time: 1234, burn_block_time: 1234, burn_block_hash: '0x1234', diff --git a/tests/utils/test-builders.ts b/tests/utils/test-builders.ts index 2633c387b..4a2cc03e2 100644 --- a/tests/utils/test-builders.ts +++ b/tests/utils/test-builders.ts @@ -100,6 +100,7 @@ export interface TestBlockArgs { canonical?: boolean; signer_bitvec?: string; signer_signatures?: string[]; + tenure_height?: number; } /** @@ -130,6 +131,7 @@ function testBlock(args?: TestBlockArgs): DbBlock { tx_count: 1, signer_bitvec: args?.signer_bitvec ?? null, signer_signatures: args?.signer_signatures ?? null, + tenure_height: args?.tenure_height ?? args?.block_height ?? BLOCK_HEIGHT, }; }