Skip to content

Commit 12b8378

Browse files
authored
Merge pull request #2143 from hirosystems/develop
Cut `v8.2.0`
2 parents 8438fc0 + a82583c commit 12b8378

29 files changed

+1708
-403
lines changed
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
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+
pgm.addColumn('blocks', {
13+
signer_signatures: {
14+
type: 'bytea[]',
15+
}
16+
});
17+
18+
pgm.createIndex('blocks', 'signer_signatures', { method: 'gin' });
19+
20+
};

src/api/controllers/db-controller.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,8 @@ function parseDbBlock(
682682
dbBlock.block_time > 0
683683
? unixEpochToIso(dbBlock.block_time)
684684
: unixEpochToIso(dbBlock.burn_block_time),
685+
// If `tenure_height` is not available, but `signer_bitvec` is set we can safely assume it's same as `block_height` (epoch2.x rules)
686+
tenure_height: dbBlock.tenure_height ?? (dbBlock.signer_bitvec ? -1 : dbBlock.block_height),
685687
index_block_hash: dbBlock.index_block_hash,
686688
parent_block_hash: dbBlock.parent_block_hash,
687689
burn_block_time: dbBlock.burn_block_time,

src/api/pagination.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ export enum ResourceType {
3939
Signer,
4040
PoxCycle,
4141
TokenHolders,
42+
BlockSignerSignature,
4243
}
4344

4445
export const pagingQueryLimits: Record<ResourceType, { defaultLimit: number; maxLimit: number }> = {
@@ -94,6 +95,10 @@ export const pagingQueryLimits: Record<ResourceType, { defaultLimit: number; max
9495
defaultLimit: 100,
9596
maxLimit: 200,
9697
},
98+
[ResourceType.BlockSignerSignature]: {
99+
defaultLimit: 500,
100+
maxLimit: 1000,
101+
},
97102
};
98103

99104
export function getPagingQueryLimit(

src/api/routes/v2/blocks.ts

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,16 @@ import { Server } from 'node:http';
99
import { CursorOffsetParam, LimitParam, OffsetParam } from '../../schemas/params';
1010
import { getPagingQueryLimit, pagingQueryLimits, ResourceType } from '../../pagination';
1111
import { PaginatedResponse } from '../../schemas/util';
12-
import { NakamotoBlock, NakamotoBlockSchema } from '../../schemas/entities/block';
12+
import {
13+
NakamotoBlock,
14+
NakamotoBlockSchema,
15+
SignerSignatureSchema,
16+
} from '../../schemas/entities/block';
1317
import { TransactionSchema } from '../../schemas/entities/transactions';
14-
import { BlockListV2ResponseSchema } from '../../schemas/responses/responses';
18+
import {
19+
BlockListV2ResponseSchema,
20+
BlockSignerSignatureResponseSchema,
21+
} from '../../schemas/responses/responses';
1522

1623
export const BlockRoutesV2: FastifyPluginAsync<
1724
Record<never, never>,
@@ -174,5 +181,53 @@ export const BlockRoutesV2: FastifyPluginAsync<
174181
}
175182
);
176183

184+
fastify.get(
185+
'/:height_or_hash/signer-signatures',
186+
{
187+
preHandler: handleBlockCache,
188+
preValidation: (req, _reply, done) => {
189+
cleanBlockHeightOrHashParam(req.params);
190+
done();
191+
},
192+
schema: {
193+
operationId: 'get_signer_signatures_for_block',
194+
summary: 'Get signer signatures for block',
195+
description: `Retrieves the signer signatures (an array of signature byte strings) in a single block`,
196+
tags: ['Blocks'],
197+
params: BlockParamsSchema,
198+
querystring: Type.Object({
199+
limit: LimitParam(ResourceType.BlockSignerSignature),
200+
offset: OffsetParam(),
201+
}),
202+
response: {
203+
200: BlockSignerSignatureResponseSchema,
204+
},
205+
},
206+
},
207+
async (req, reply) => {
208+
const params = parseBlockParam(req.params.height_or_hash);
209+
const query = req.query;
210+
211+
try {
212+
const { limit, offset, results, total } = await fastify.db.v2.getBlockSignerSignature({
213+
blockId: params,
214+
...query,
215+
});
216+
const response = {
217+
limit,
218+
offset,
219+
total,
220+
results: results,
221+
};
222+
await reply.send(response);
223+
} catch (error) {
224+
if (error instanceof InvalidRequestError) {
225+
throw new NotFoundError('Block not found');
226+
}
227+
throw error;
228+
}
229+
}
230+
);
231+
177232
await Promise.resolve();
178233
};

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/routes/v2/schemas.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ export const TransactionLimitParamSchema = Type.Integer({
4747
description: 'Transactions per page',
4848
});
4949

50+
export const BlockSignerSignatureLimitParamSchema = Type.Integer({
51+
minimum: 1,
52+
maximum: pagingQueryLimits[ResourceType.BlockSignerSignature].maxLimit,
53+
default: pagingQueryLimits[ResourceType.BlockSignerSignature].defaultLimit,
54+
title: 'Block signer signature limit',
55+
description: 'Block signer signatures per page',
56+
});
57+
5058
export const PoxCycleLimitParamSchema = Type.Integer({
5159
minimum: 1,
5260
maximum: pagingQueryLimits[ResourceType.PoxCycle].maxLimit,

src/api/schemas/entities/block.ts

Lines changed: 10 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',
@@ -116,3 +122,7 @@ export const NakamotoBlockSchema = Type.Object({
116122
execution_cost_write_length: Type.Integer({ description: 'Execution cost write length.' }),
117123
});
118124
export type NakamotoBlock = Static<typeof NakamotoBlockSchema>;
125+
126+
export const SignerSignatureSchema = Type.String({
127+
description: "Array of hex strings representing the block's signer signature",
128+
});

src/api/schemas/responses/responses.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
BurnchainRewardSchema,
1313
BurnchainRewardSlotHolderSchema,
1414
} from '../entities/burnchain-rewards';
15-
import { NakamotoBlockSchema } from '../entities/block';
15+
import { NakamotoBlockSchema, SignerSignatureSchema } from '../entities/block';
1616

1717
export const ErrorResponseSchema = Type.Object(
1818
{
@@ -182,3 +182,6 @@ export type RunFaucetResponse = Static<typeof RunFaucetResponseSchema>;
182182

183183
export const BlockListV2ResponseSchema = PaginatedCursorResponse(NakamotoBlockSchema);
184184
export type BlockListV2Response = Static<typeof BlockListV2ResponseSchema>;
185+
186+
export const BlockSignerSignatureResponseSchema = PaginatedResponse(SignerSignatureSchema);
187+
export type BlockSignerSignatureResponse = Static<typeof BlockSignerSignatureResponseSchema>;

src/datastore/common.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export interface DbBlock {
2525
tx_count: number;
2626
block_time: number;
2727
signer_bitvec: string | null;
28+
signer_signatures: string[] | null;
29+
tenure_height: number | null;
2830
}
2931

3032
/** An interface representing the microblock data that can be constructed _only_ from the /new_microblocks payload */
@@ -862,6 +864,7 @@ export interface BlockQueryResult {
862864
execution_cost_write_length: string;
863865
tx_count: number;
864866
signer_bitvec: string | null;
867+
tenure_height: number | null;
865868
}
866869

867870
export interface MicroblockQueryResult {
@@ -1286,6 +1289,8 @@ export interface BlockInsertValues {
12861289
execution_cost_write_length: number;
12871290
tx_count: number;
12881291
signer_bitvec: string | null;
1292+
signer_signatures: PgBytea[] | null;
1293+
tenure_height: number | null;
12891294
}
12901295

12911296
export interface MicroblockInsertValues {

src/datastore/helpers.ts

Lines changed: 3 additions & 38 deletions
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,
@@ -487,6 +487,8 @@ export function parseBlockQueryResult(row: BlockQueryResult): DbBlock {
487487
execution_cost_write_length: Number.parseInt(row.execution_cost_write_length),
488488
tx_count: row.tx_count,
489489
signer_bitvec: row.signer_bitvec,
490+
signer_signatures: null, // this field is not queried from db by default due to size constraints
491+
tenure_height: row.tenure_height,
490492
};
491493
return block;
492494
}
@@ -1282,43 +1284,6 @@ export function convertTxQueryResultToDbMempoolTx(txs: TxQueryResult[]): DbMempo
12821284
return dbMempoolTxs;
12831285
}
12841286

1285-
export function setTotalBlockUpdateDataExecutionCost(data: DataStoreBlockUpdateData) {
1286-
const cost = data.txs.reduce(
1287-
(previousValue, currentValue) => {
1288-
const {
1289-
execution_cost_read_count,
1290-
execution_cost_read_length,
1291-
execution_cost_runtime,
1292-
execution_cost_write_count,
1293-
execution_cost_write_length,
1294-
} = previousValue;
1295-
return {
1296-
execution_cost_read_count:
1297-
execution_cost_read_count + currentValue.tx.execution_cost_read_count,
1298-
execution_cost_read_length:
1299-
execution_cost_read_length + currentValue.tx.execution_cost_read_length,
1300-
execution_cost_runtime: execution_cost_runtime + currentValue.tx.execution_cost_runtime,
1301-
execution_cost_write_count:
1302-
execution_cost_write_count + currentValue.tx.execution_cost_write_count,
1303-
execution_cost_write_length:
1304-
execution_cost_write_length + currentValue.tx.execution_cost_write_length,
1305-
};
1306-
},
1307-
{
1308-
execution_cost_read_count: 0,
1309-
execution_cost_read_length: 0,
1310-
execution_cost_runtime: 0,
1311-
execution_cost_write_count: 0,
1312-
execution_cost_write_length: 0,
1313-
}
1314-
);
1315-
data.block.execution_cost_read_count = cost.execution_cost_read_count;
1316-
data.block.execution_cost_read_length = cost.execution_cost_read_length;
1317-
data.block.execution_cost_runtime = cost.execution_cost_runtime;
1318-
data.block.execution_cost_write_count = cost.execution_cost_write_count;
1319-
data.block.execution_cost_write_length = cost.execution_cost_write_length;
1320-
}
1321-
13221287
export function markBlockUpdateDataAsNonCanonical(data: DataStoreBlockUpdateData): void {
13231288
data.block = { ...data.block, canonical: false };
13241289
data.microblocks = data.microblocks.map(mb => ({ ...mb, canonical: false }));

0 commit comments

Comments
 (0)