From 05ce8347a1f3fa748679b38d17ed4f93886e0e0d Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Fri, 25 Oct 2024 22:45:30 +0200 Subject: [PATCH 1/7] test: deserialized mock payload debugging --- chunk-parser/src/common.ts | 6 +++++ chunk-parser/src/signer-message.ts | 43 ++++++++++++++++++++++++++---- 2 files changed, 44 insertions(+), 5 deletions(-) diff --git a/chunk-parser/src/common.ts b/chunk-parser/src/common.ts index 645c369..e2fc281 100644 --- a/chunk-parser/src/common.ts +++ b/chunk-parser/src/common.ts @@ -110,6 +110,12 @@ export class BufferCursor { return bytes.toString('utf8'); } + readU8LengthPrefixedString(): string { + const length = this.readU8(); + const bytes = this.readBytes(length); + return bytes.toString('utf8'); + } + } export class BufferWriter { diff --git a/chunk-parser/src/signer-message.ts b/chunk-parser/src/signer-message.ts index d6bada3..07c545d 100644 --- a/chunk-parser/src/signer-message.ts +++ b/chunk-parser/src/signer-message.ts @@ -149,15 +149,48 @@ function parseBlockPushed(cursor: BufferCursor) { } function parseMockProposal(cursor: BufferCursor) { - console.log('MockProposal ignored'); + const peerInfo = parseMockPeerInfo(cursor); + const signature = cursor.readBytes(65).toString('hex'); + return { peerInfo, signature }; +} + +// https://github.com/stacks-network/stacks-core/blob/09d920cd1926422a8e3fb76fe4e1b1ef649546b4/libsigner/src/v0/messages.rs#L283 +function parseMockPeerInfo(cursor: BufferCursor) { + const burnBlockHeight = cursor.readU64BE(); + const stacksTipConsensusHash = cursor.readBytes(20).toString('hex'); + const stacksTip = cursor.readBytes(32).toString('hex'); + const stacksTipHeight = cursor.readU64BE(); + const serverVersion = cursor.readU8LengthPrefixedString(); + const poxConsensusHash = cursor.readBytes(20).toString('hex'); + const networkId = cursor.readU32BE(); + const indexBlockHash = getIndexBlockHash(stacksTip, stacksTipConsensusHash); + return { + burnBlockHeight, + stacksTipConsensusHash, + stacksTip, + stacksTipHeight, + serverVersion, + poxConsensusHash, + networkId, + indexBlockHash, + } } function parseMockSignature(cursor: BufferCursor) { - console.log('MockSignature ignored'); + const signature = cursor.readBytes(65).toString('hex'); + const mockProposal = parseMockProposal(cursor); + const metadata = parseSignerMessageMetadata(cursor); + return { + signature, + mockProposal, + metadata, + } } function parseMockBlock(cursor: BufferCursor) { - console.log('MockBlock ignored'); + const mockProposal = parseMockProposal(cursor); + const mockSignatures = cursor.readArray(parseMockSignature); + return { mockProposal, mockSignatures }; } // https://github.com/stacks-network/stacks-core/blob/cd702e7dfba71456e4983cf530d5b174e34507dc/libsigner/src/events.rs#L74 @@ -172,7 +205,7 @@ function parseBlockProposal(cursor: BufferCursor) { function parseNakamotoBlock(cursor: BufferCursor) { const header = parseNakamotoBlockHeader(cursor); const blockHash = getNakamotoBlockHash(header); - const indexBlockHash = getNakamotoIndexBlockHash(blockHash, header.consensusHash); + const indexBlockHash = getIndexBlockHash(blockHash, header.consensusHash); const tx = cursor.readArray(parseStacksTransaction); return { blockHash, indexBlockHash, header, tx }; } @@ -186,7 +219,7 @@ function parseStacksTransaction(cursor: BufferCursor) { } // https://github.com/stacks-network/stacks-core/blob/a2dcd4c3ffdb625a6478bb2c0b23836bc9c72f9f/stacks-common/src/types/chainstate.rs#L268-L279 -function getNakamotoIndexBlockHash(blockHash: string, consensusHash: string): string { +function getIndexBlockHash(blockHash: string, consensusHash: string): string { const hasher = crypto.createHash('sha512-256'); hasher.update(Buffer.from(blockHash, 'hex')); hasher.update(Buffer.from(consensusHash, 'hex')); From 2511f77409e954c93153f60cdd9bb4ffe8b08a0c Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Fri, 25 Oct 2024 23:34:08 +0200 Subject: [PATCH 2/7] feat: pg schema for mock payload tables --- migrations/1729684505758_mock_proposals.ts | 61 ++++++++++++ migrations/1729684505759_mock_signature.ts | 82 ++++++++++++++++ migrations/1729684505760_mock_blocks.ts | 104 +++++++++++++++++++++ 3 files changed, 247 insertions(+) create mode 100644 migrations/1729684505758_mock_proposals.ts create mode 100644 migrations/1729684505759_mock_signature.ts create mode 100644 migrations/1729684505760_mock_blocks.ts diff --git a/migrations/1729684505758_mock_proposals.ts b/migrations/1729684505758_mock_proposals.ts new file mode 100644 index 0000000..4a2b3cb --- /dev/null +++ b/migrations/1729684505758_mock_proposals.ts @@ -0,0 +1,61 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { MigrationBuilder, ColumnDefinitions } from 'node-pg-migrate'; + +export const shorthands: ColumnDefinitions | undefined = undefined; + +export function up(pgm: MigrationBuilder): void { + pgm.createTable('mock_proposals', { + id: { + type: 'bigserial', + primaryKey: true, + }, + received_at: { + type: 'timestamptz', + notNull: true, + }, + miner_key: { + type: 'bytea', + notNull: true, + }, + burn_block_height: { + type: 'integer', + notNull: true, + }, + stacks_tip_consensus_hash: { + type: 'bytea', + notNull: true, + }, + // AKA block_hash + stacks_tip: { + type: 'bytea', + notNull: true, + }, + // AKA block_height + stacks_tip_height: { + type: 'integer', + notNull: true, + }, + server_version: { + type: 'text', + notNull: true, + }, + pox_consensus_hash: { + type: 'bytea', + notNull: true, + }, + network_id: { + type: 'integer', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + }); + + pgm.createIndex('mock_proposals', ['received_at']); + pgm.createIndex('mock_proposals', ['stacks_tip_height']); + pgm.createIndex('mock_proposals', ['stacks_tip']); + pgm.createIndex('mock_proposals', ['index_block_hash']); + pgm.createIndex('mock_proposals', ['burn_block_height']); +} diff --git a/migrations/1729684505759_mock_signature.ts b/migrations/1729684505759_mock_signature.ts new file mode 100644 index 0000000..3a4e6ec --- /dev/null +++ b/migrations/1729684505759_mock_signature.ts @@ -0,0 +1,82 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { MigrationBuilder, ColumnDefinitions } from 'node-pg-migrate'; + +export const shorthands: ColumnDefinitions | undefined = undefined; + +export function up(pgm: MigrationBuilder): void { + pgm.createTable('mock_signatures', { + id: { + type: 'bigserial', + primaryKey: true, + }, + received_at: { + type: 'timestamptz', + notNull: true, + }, + signer_key: { + type: 'bytea', + notNull: true, + }, + signature: { + type: 'bytea', + notNull: true, + }, + + // Mock proposal fields + mock_proposal_miner_key: { + type: 'bytea', + notNull: true, + }, + mock_proposal_signature: { + type: 'bytea', + notNull: true, + }, + burn_block_height: { + type: 'integer', + notNull: true, + }, + stacks_tip_consensus_hash: { + type: 'bytea', + notNull: true, + }, + // AKA block_hash + stacks_tip: { + type: 'bytea', + notNull: true, + }, + // AKA block_height + stacks_tip_height: { + type: 'integer', + notNull: true, + }, + server_version: { + type: 'text', + notNull: true, + }, + pox_consensus_hash: { + type: 'bytea', + notNull: true, + }, + network_id: { + type: 'integer', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + + // Metadata fields + metadata_server_version: { + type: 'text', + notNull: true, + }, + }); + + pgm.createIndex('mock_signatures', ['received_at']); + pgm.createIndex('mock_signatures', ['signer_key']); + pgm.createIndex('mock_signatures', ['stacks_tip_height']); + pgm.createIndex('mock_signatures', ['stacks_tip']); + pgm.createIndex('mock_signatures', ['index_block_hash']); + pgm.createIndex('mock_signatures', ['burn_block_height']); +} diff --git a/migrations/1729684505760_mock_blocks.ts b/migrations/1729684505760_mock_blocks.ts new file mode 100644 index 0000000..ecdd642 --- /dev/null +++ b/migrations/1729684505760_mock_blocks.ts @@ -0,0 +1,104 @@ +/* eslint-disable @typescript-eslint/naming-convention */ +import { MigrationBuilder, ColumnDefinitions } from 'node-pg-migrate'; + +export const shorthands: ColumnDefinitions | undefined = undefined; + +export function up(pgm: MigrationBuilder): void { + pgm.createTable('mock_blocks', { + id: { + type: 'bigserial', + primaryKey: true, + }, + received_at: { + type: 'timestamptz', + notNull: true, + }, + miner_key: { + type: 'bytea', + notNull: true, + }, + signature: { + type: 'bytea', + notNull: true, + }, + + // Mock proposal fields + mock_proposal_miner_key: { + type: 'bytea', + notNull: true, + }, + mock_proposal_signature: { + type: 'bytea', + notNull: true, + }, + burn_block_height: { + type: 'integer', + notNull: true, + }, + stacks_tip_consensus_hash: { + type: 'bytea', + notNull: true, + }, + // AKA block_hash + stacks_tip: { + type: 'bytea', + notNull: true, + }, + // AKA block_height + stacks_tip_height: { + type: 'integer', + notNull: true, + }, + server_version: { + type: 'text', + notNull: true, + }, + pox_consensus_hash: { + type: 'bytea', + notNull: true, + }, + network_id: { + type: 'integer', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + }); + + pgm.createIndex('mock_blocks', ['received_at']); + pgm.createIndex('mock_blocks', ['stacks_tip_height']); + pgm.createIndex('mock_blocks', ['stacks_tip']); + pgm.createIndex('mock_blocks', ['index_block_hash']); + pgm.createIndex('mock_blocks', ['burn_block_height']); + + // Mock block signer signatures + pgm.createTable('mock_block_signer_signatures', { + id: { + type: 'bigserial', + primaryKey: true, + }, + signer_key: { + type: 'bytea', + notNull: true, + }, + signer_signature: { + type: 'bytea', + notNull: true, + }, + // AKA block_height + stacks_tip: { + type: 'bytea', + notNull: true, + }, + index_block_hash: { + type: 'bytea', + notNull: true, + }, + }); + + pgm.createIndex('mock_block_signer_signatures', ['signer_key']); + pgm.createIndex('mock_block_signer_signatures', ['stacks_tip']); + pgm.createIndex('mock_block_signer_signatures', ['index_block_hash']); +} From d5139145a4157c8deab14ea946312c7c9e13f987 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Fri, 25 Oct 2024 23:45:24 +0200 Subject: [PATCH 3/7] chore: mock payload db type defs --- src/pg/types.ts | 59 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/src/pg/types.ts b/src/pg/types.ts index f3784be..6a92d34 100644 --- a/src/pg/types.ts +++ b/src/pg/types.ts @@ -48,3 +48,62 @@ export type DbBlockProposal = { burn_block_height: number; reward_cycle: number; }; + +export type DbMockProposal = { + received_at: string; + miner_key: PgBytea; + burn_block_height: number; + stacks_tip_consensus_hash: PgBytea; + stacks_tip: PgBytea; + stacks_tip_height: number; + server_version: string; + pox_consensus_hash: PgBytea; + network_id: number; + index_block_hash: PgBytea; +}; + +export type DbMockSignature = { + received_at: string; + signer_key: PgBytea; + signature: PgBytea; + + // Mock proposal fields + mock_proposal_miner_key: PgBytea; + mock_proposal_signature: PgBytea; + burn_block_height: number; + stacks_tip_consensus_hash: PgBytea; + stacks_tip: PgBytea; + stacks_tip_height: number; + server_version: string; + pox_consensus_hash: PgBytea; + network_id: number; + index_block_hash: PgBytea; + + // Metadata fields + metadata_server_version: string; +}; + +export type DbMockBlock = { + received_at: string; + miner_key: PgBytea; + signature: PgBytea; + + // Mock proposal fields + mock_proposal_miner_key: PgBytea; + mock_proposal_signature: PgBytea; + burn_block_height: number; + stacks_tip_consensus_hash: PgBytea; + stacks_tip: PgBytea; + stacks_tip_height: number; + server_version: string; + pox_consensus_hash: PgBytea; + network_id: number; + index_block_hash: PgBytea; +}; + +export type DbMockBlockSignerSignature = { + signer_key: PgBytea; + signer_signature: PgBytea; + stacks_tip: PgBytea; + index_block_hash: PgBytea; +}; From fb06793a8619b13df52e3fd31186dca856e6add3 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Sat, 26 Oct 2024 00:29:56 +0200 Subject: [PATCH 4/7] feat: sql writes for mock payloads --- migrations/1729684505758_mock_proposals.ts | 2 +- migrations/1729684505759_mock_signature.ts | 10 +- migrations/1729684505760_mock_blocks.ts | 10 +- package-lock.json | 12 +- package.json | 2 +- src/pg/chainhook/chainhook-pg-store.ts | 145 +++++++++++++++++++++ src/pg/types.ts | 4 - 7 files changed, 155 insertions(+), 30 deletions(-) diff --git a/migrations/1729684505758_mock_proposals.ts b/migrations/1729684505758_mock_proposals.ts index 4a2b3cb..a354180 100644 --- a/migrations/1729684505758_mock_proposals.ts +++ b/migrations/1729684505758_mock_proposals.ts @@ -44,7 +44,7 @@ export function up(pgm: MigrationBuilder): void { notNull: true, }, network_id: { - type: 'integer', + type: 'bigint', notNull: true, }, index_block_hash: { diff --git a/migrations/1729684505759_mock_signature.ts b/migrations/1729684505759_mock_signature.ts index 3a4e6ec..68d4062 100644 --- a/migrations/1729684505759_mock_signature.ts +++ b/migrations/1729684505759_mock_signature.ts @@ -23,14 +23,6 @@ export function up(pgm: MigrationBuilder): void { }, // Mock proposal fields - mock_proposal_miner_key: { - type: 'bytea', - notNull: true, - }, - mock_proposal_signature: { - type: 'bytea', - notNull: true, - }, burn_block_height: { type: 'integer', notNull: true, @@ -58,7 +50,7 @@ export function up(pgm: MigrationBuilder): void { notNull: true, }, network_id: { - type: 'integer', + type: 'bigint', notNull: true, }, index_block_hash: { diff --git a/migrations/1729684505760_mock_blocks.ts b/migrations/1729684505760_mock_blocks.ts index ecdd642..c06f273 100644 --- a/migrations/1729684505760_mock_blocks.ts +++ b/migrations/1729684505760_mock_blocks.ts @@ -23,14 +23,6 @@ export function up(pgm: MigrationBuilder): void { }, // Mock proposal fields - mock_proposal_miner_key: { - type: 'bytea', - notNull: true, - }, - mock_proposal_signature: { - type: 'bytea', - notNull: true, - }, burn_block_height: { type: 'integer', notNull: true, @@ -58,7 +50,7 @@ export function up(pgm: MigrationBuilder): void { notNull: true, }, network_id: { - type: 'integer', + type: 'bigint', notNull: true, }, index_block_hash: { diff --git a/package-lock.json b/package-lock.json index bf913cc..e725d0a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,11 +1,11 @@ { - "name": "@hirosystems/signer-monitor-api", + "name": "@hirosystems/signer-metrics-api", "version": "1.0.0", "lockfileVersion": 3, "requires": true, "packages": { "": { - "name": "@hirosystems/signer-monitor-api", + "name": "@hirosystems/signer-metrics-api", "version": "1.0.0", "license": "GPL-3.0", "dependencies": { @@ -13,7 +13,7 @@ "@fastify/swagger": "^7.6.1", "@fastify/type-provider-typebox": "^3.2.0", "@hirosystems/api-toolkit": "^1.7.1", - "@hirosystems/chainhook-client": "^2.1.1", + "@hirosystems/chainhook-client": "^2.3.0", "@sinclair/typebox": "^0.28.17", "@stacks/transactions": "^6.1.0", "@types/node": "^20.16.1", @@ -1233,9 +1233,9 @@ } }, "node_modules/@hirosystems/chainhook-client": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@hirosystems/chainhook-client/-/chainhook-client-2.1.1.tgz", - "integrity": "sha512-e7xjUswYjDsBuvYxSx8Qm3gsyCcKFvxXrfTVa06X7P9EQTKxfiBpO/b8JGok09YlIGJ8vZlyXzEIDsIQJ13auA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@hirosystems/chainhook-client/-/chainhook-client-2.3.0.tgz", + "integrity": "sha512-KvzYwm83oatk31VZGywUsPXine3Ah5wjArOWMuvcEQMzAc1IcjcHsQJM2+2z+8OAFZm9r8bkI72CVv/9wSsh6A==", "license": "Apache 2.0", "dependencies": { "@fastify/type-provider-typebox": "^3.2.0", diff --git a/package.json b/package.json index 6e1d523..fd28366 100644 --- a/package.json +++ b/package.json @@ -49,7 +49,7 @@ "@fastify/swagger": "^7.6.1", "@fastify/type-provider-typebox": "^3.2.0", "@hirosystems/api-toolkit": "^1.7.1", - "@hirosystems/chainhook-client": "^2.1.1", + "@hirosystems/chainhook-client": "^2.3.0", "@sinclair/typebox": "^0.28.17", "@stacks/transactions": "^6.1.0", "@types/node": "^20.16.1", diff --git a/src/pg/chainhook/chainhook-pg-store.ts b/src/pg/chainhook/chainhook-pg-store.ts index 6778e64..56f4465 100644 --- a/src/pg/chainhook/chainhook-pg-store.ts +++ b/src/pg/chainhook/chainhook-pg-store.ts @@ -11,6 +11,10 @@ import { DbBlockProposal, DbBlockResponse, DbBlockSignerSignature, + DbMockBlock, + DbMockBlockSignerSignature, + DbMockProposal, + DbMockSignature, DbRewardSetSigner, } from '../types'; import { normalizeHexString, unixTimeMillisecondsToISO, unixTimeSecondsToISO } from '../../helpers'; @@ -57,6 +61,21 @@ type BlockResponseData = Extract< { type: 'BlockResponse' } >['data']; +type MockProposalData = Extract< + SignerMessage['payload']['data']['message'], + { type: 'MockProposal' } +>['data']; + +type MockSignatureData = Extract< + SignerMessage['payload']['data']['message'], + { type: 'MockSignature' } +>['data']; + +type MockBlockData = Extract< + SignerMessage['payload']['data']['message'], + { type: 'MockBlock' } +>['data']; + export class ChainhookPgStore extends BasePgStoreModule { async processPayload(payload: StacksPayload): Promise { await this.sqlWriteTransaction(async sql => { @@ -135,6 +154,34 @@ export class ChainhookPgStore extends BasePgStoreModule { logger.info(`Ignoring BlockPushed StackerDB event`); break; } + case 'MockProposal': { + await this.applyMockProposal( + sql, + event.received_at_ms, + event.payload.data.pubkey, + event.payload.data.message.data + ); + break; + } + case 'MockSignature': { + await this.applyMockSignature( + sql, + event.received_at_ms, + event.payload.data.pubkey, + event.payload.data.message.data + ); + break; + } + case 'MockBlock': { + await this.applyMockBlock( + sql, + event.received_at_ms, + event.payload.data.pubkey, + event.payload.data.sig, + event.payload.data.message.data + ); + break; + } default: { logger.error(event.payload.data, `Unknown StackerDB event type`); break; @@ -142,6 +189,104 @@ export class ChainhookPgStore extends BasePgStoreModule { } } + private async applyMockBlock( + sql: PgSqlClient, + receivedAt: number, + minerPubkey: string, + minerSignature: string, + messageData: MockBlockData + ) { + const dbMockBlock: DbMockBlock = { + received_at: unixTimeMillisecondsToISO(receivedAt), + miner_key: normalizeHexString(minerPubkey), + signature: normalizeHexString(minerSignature), + + // Mock proposal fields + burn_block_height: messageData.mock_proposal.peer_info.burn_block_height, + stacks_tip_consensus_hash: normalizeHexString( + messageData.mock_proposal.peer_info.stacks_tip_consensus_hash + ), + stacks_tip: normalizeHexString(messageData.mock_proposal.peer_info.stacks_tip), + stacks_tip_height: messageData.mock_proposal.peer_info.stacks_tip_height, + server_version: messageData.mock_proposal.peer_info.server_version, + pox_consensus_hash: normalizeHexString(messageData.mock_proposal.peer_info.pox_consensus), + network_id: messageData.mock_proposal.peer_info.network_id, + index_block_hash: normalizeHexString(messageData.mock_proposal.peer_info.index_block_hash), + }; + await sql` + INSERT INTO mock_blocks ${sql(dbMockBlock)} + `; + + for (const batch of batchIterate(messageData.mock_signatures, 500)) { + const sigs = batch.map(sig => { + const dbSig: DbMockBlockSignerSignature = { + signer_key: normalizeHexString(sig.pubkey), + signer_signature: normalizeHexString(sig.signature), + stacks_tip: sig.mock_proposal.peer_info.stacks_tip, + index_block_hash: sig.mock_proposal.peer_info.index_block_hash, + }; + return dbSig; + }); + await sql` + INSERT INTO mock_block_signer_signatures ${sql(sigs)} + `; + } + } + + private async applyMockSignature( + sql: PgSqlClient, + receivedAt: number, + signerPubkey: string, + messageData: MockSignatureData + ) { + const dbMockSignature: DbMockSignature = { + received_at: unixTimeMillisecondsToISO(receivedAt), + signer_key: normalizeHexString(signerPubkey), + signature: normalizeHexString(messageData.signature), + + // Mock proposal fields + burn_block_height: messageData.mock_proposal.peer_info.burn_block_height, + stacks_tip_consensus_hash: normalizeHexString( + messageData.mock_proposal.peer_info.stacks_tip_consensus_hash + ), + stacks_tip: normalizeHexString(messageData.mock_proposal.peer_info.stacks_tip), + stacks_tip_height: messageData.mock_proposal.peer_info.stacks_tip_height, + server_version: messageData.mock_proposal.peer_info.server_version, + pox_consensus_hash: normalizeHexString(messageData.mock_proposal.peer_info.pox_consensus), + network_id: messageData.mock_proposal.peer_info.network_id, + index_block_hash: normalizeHexString(messageData.mock_proposal.peer_info.index_block_hash), + + // Metadata fields + metadata_server_version: messageData.metadata.server_version, + }; + await sql` + INSERT INTO mock_signatures ${sql(dbMockSignature)} + `; + } + + private async applyMockProposal( + sql: PgSqlClient, + receivedAt: number, + minerPubkey: string, + messageData: MockProposalData + ) { + const dbMockProposal: DbMockProposal = { + received_at: unixTimeMillisecondsToISO(receivedAt), + miner_key: normalizeHexString(minerPubkey), + burn_block_height: messageData.burn_block_height, + stacks_tip_consensus_hash: normalizeHexString(messageData.stacks_tip_consensus_hash), + stacks_tip: normalizeHexString(messageData.stacks_tip), + stacks_tip_height: messageData.stacks_tip_height, + server_version: messageData.server_version, + pox_consensus_hash: normalizeHexString(messageData.pox_consensus), + network_id: messageData.network_id, + index_block_hash: normalizeHexString(messageData.index_block_hash), + }; + await sql` + INSERT INTO mock_proposals ${sql(dbMockProposal)} + `; + } + private async applyBlockProposal( sql: PgSqlClient, receivedAt: number, diff --git a/src/pg/types.ts b/src/pg/types.ts index 6a92d34..b1a8a3d 100644 --- a/src/pg/types.ts +++ b/src/pg/types.ts @@ -68,8 +68,6 @@ export type DbMockSignature = { signature: PgBytea; // Mock proposal fields - mock_proposal_miner_key: PgBytea; - mock_proposal_signature: PgBytea; burn_block_height: number; stacks_tip_consensus_hash: PgBytea; stacks_tip: PgBytea; @@ -89,8 +87,6 @@ export type DbMockBlock = { signature: PgBytea; // Mock proposal fields - mock_proposal_miner_key: PgBytea; - mock_proposal_signature: PgBytea; burn_block_height: number; stacks_tip_consensus_hash: PgBytea; stacks_tip: PgBytea; From e001e584093c373979d69ad3dd56a5e3c667c3f0 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Sat, 26 Oct 2024 00:45:29 +0200 Subject: [PATCH 5/7] chore: include stacks_tip_height in mock signatures --- migrations/1729684505760_mock_blocks.ts | 8 +++++++- src/pg/chainhook/chainhook-pg-store.ts | 1 + src/pg/types.ts | 1 + 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/migrations/1729684505760_mock_blocks.ts b/migrations/1729684505760_mock_blocks.ts index c06f273..a316192 100644 --- a/migrations/1729684505760_mock_blocks.ts +++ b/migrations/1729684505760_mock_blocks.ts @@ -79,11 +79,16 @@ export function up(pgm: MigrationBuilder): void { type: 'bytea', notNull: true, }, - // AKA block_height + // AKA block_hash stacks_tip: { type: 'bytea', notNull: true, }, + // AKA block_height + stacks_tip_height: { + type: 'integer', + notNull: true, + }, index_block_hash: { type: 'bytea', notNull: true, @@ -92,5 +97,6 @@ export function up(pgm: MigrationBuilder): void { pgm.createIndex('mock_block_signer_signatures', ['signer_key']); pgm.createIndex('mock_block_signer_signatures', ['stacks_tip']); + pgm.createIndex('mock_block_signer_signatures', ['stacks_tip_height']); pgm.createIndex('mock_block_signer_signatures', ['index_block_hash']); } diff --git a/src/pg/chainhook/chainhook-pg-store.ts b/src/pg/chainhook/chainhook-pg-store.ts index 56f4465..6e22cdf 100644 --- a/src/pg/chainhook/chainhook-pg-store.ts +++ b/src/pg/chainhook/chainhook-pg-store.ts @@ -223,6 +223,7 @@ export class ChainhookPgStore extends BasePgStoreModule { signer_key: normalizeHexString(sig.pubkey), signer_signature: normalizeHexString(sig.signature), stacks_tip: sig.mock_proposal.peer_info.stacks_tip, + stacks_tip_height: sig.mock_proposal.peer_info.stacks_tip_height, index_block_hash: sig.mock_proposal.peer_info.index_block_hash, }; return dbSig; diff --git a/src/pg/types.ts b/src/pg/types.ts index b1a8a3d..2c5ac85 100644 --- a/src/pg/types.ts +++ b/src/pg/types.ts @@ -101,5 +101,6 @@ export type DbMockBlockSignerSignature = { signer_key: PgBytea; signer_signature: PgBytea; stacks_tip: PgBytea; + stacks_tip_height: number; index_block_hash: PgBytea; }; From 6bf9c491c56897a3dd60cb8db15ee11d825349ef Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Sat, 26 Oct 2024 00:51:47 +0200 Subject: [PATCH 6/7] chore: remove some todos --- src/pg/chainhook/chainhook-pg-store.ts | 41 ++++---------------------- 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/src/pg/chainhook/chainhook-pg-store.ts b/src/pg/chainhook/chainhook-pg-store.ts index 6e22cdf..3dc3d83 100644 --- a/src/pg/chainhook/chainhook-pg-store.ts +++ b/src/pg/chainhook/chainhook-pg-store.ts @@ -19,31 +19,6 @@ import { } from '../types'; import { normalizeHexString, unixTimeMillisecondsToISO, unixTimeSecondsToISO } from '../../helpers'; -// TODO: update chainhook-client types to get rid of this -type TodoStacksEvent = StacksEvent & { - metadata: { - tenure_height: number; - signer_public_keys?: string[]; - }; -}; - -// TODO: update chainhook-client types to get rid of this -type TodoBlockRejectReason = - | { - VALIDATION_FAILED: - | 'BAD_BLOCK_HASH' - | 'BAD_TRANSACTION' - | 'INVALID_BLOCK' - | 'CHAINSTATE_ERROR' - | 'UNKNOWN_PARENT' - | 'NON_CANONICAL_TENURE' - | 'NO_SUCH_TENURE'; - } - | 'CONNECTIVITY_ISSUES' - | 'REJECTED_IN_PRIOR_ROUND' - | 'NO_SORTITION_VIEW' - | 'SORTITION_VIEW_MISMATCH' - | 'TESTING_DIRECTIVE'; const RejectReasonValidationFailed = 'VALIDATION_FAILED'; type SignerMessage = Extract< @@ -320,16 +295,10 @@ export class ChainhookPgStore extends BasePgStoreModule { } const accepted = messageData.type === 'Accepted'; - // TODO: fix this unsafe cast when chainhook-client is updated - const serverVersion = (messageData.data as any).metadata.server_version; - - // TODO: fix this unsafe cast when chainhook-client is updated - const signature = (messageData.data as any).signature; - let rejectReasonCode: string | null = null; let rejectCode: string | null = null; if (!accepted) { - const rejectReason = messageData.data.reason_code as TodoBlockRejectReason; + const rejectReason = messageData.data.reason_code; if (typeof rejectReason === 'string') { rejectReasonCode = rejectReason; } else if (RejectReasonValidationFailed in rejectReason) { @@ -343,8 +312,8 @@ export class ChainhookPgStore extends BasePgStoreModule { signer_key: normalizeHexString(signerPubkey), accepted: accepted, signer_sighash: normalizeHexString(messageData.data.signer_signature_hash), - metadata_server_version: serverVersion, - signature: signature, + metadata_server_version: messageData.data.metadata.server_version, + signature: messageData.data.signature, reason_string: accepted ? null : messageData.data.reason, reason_code: rejectReasonCode, reject_code: rejectCode, @@ -362,7 +331,7 @@ export class ChainhookPgStore extends BasePgStoreModule { ) { switch (direction) { case 'apply': - await this.applyTransactions(sql, block as TodoStacksEvent); + await this.applyTransactions(sql, block); break; case 'rollback': await this.rollBackTransactions(sql, block); @@ -370,7 +339,7 @@ export class ChainhookPgStore extends BasePgStoreModule { } } - private async applyTransactions(sql: PgSqlClient, block: TodoStacksEvent) { + private async applyTransactions(sql: PgSqlClient, block: StacksEvent) { const dbBlock: DbBlock = { block_height: block.block_identifier.index, block_hash: normalizeHexString(block.metadata.stacks_block_hash), From bde46665e45e02c0da7e9701874b9ba2647b4211 Mon Sep 17 00:00:00 2001 From: Matthew Little Date: Sat, 26 Oct 2024 01:01:57 +0200 Subject: [PATCH 7/7] feat: include is_nakamoto_block flag in blocks table --- migrations/1729684505752_blocks.ts | 4 ++++ src/pg/chainhook/chainhook-pg-store.ts | 1 + src/pg/types.ts | 1 + 3 files changed, 6 insertions(+) diff --git a/migrations/1729684505752_blocks.ts b/migrations/1729684505752_blocks.ts index b0354d0..bccfc1e 100644 --- a/migrations/1729684505752_blocks.ts +++ b/migrations/1729684505752_blocks.ts @@ -38,6 +38,10 @@ export function up(pgm: MigrationBuilder): void { type: 'bytea', notNull: true, }, + is_nakamoto_block: { + type: 'boolean', + notNull: true, + }, }); pgm.createIndex('blocks', ['block_height']); diff --git a/src/pg/chainhook/chainhook-pg-store.ts b/src/pg/chainhook/chainhook-pg-store.ts index 3dc3d83..4bf2036 100644 --- a/src/pg/chainhook/chainhook-pg-store.ts +++ b/src/pg/chainhook/chainhook-pg-store.ts @@ -348,6 +348,7 @@ export class ChainhookPgStore extends BasePgStoreModule { burn_block_hash: normalizeHexString(block.metadata.bitcoin_anchor_block_identifier.hash), tenure_height: block.metadata.tenure_height ?? 0, block_time: unixTimeSecondsToISO(block.metadata.block_time ?? 0), + is_nakamoto_block: !!block.metadata.signer_bitvec, }; await this.insertBlock(sql, dbBlock); diff --git a/src/pg/types.ts b/src/pg/types.ts index 2c5ac85..d57a186 100644 --- a/src/pg/types.ts +++ b/src/pg/types.ts @@ -8,6 +8,7 @@ export type DbBlock = { index_block_hash: PgBytea; burn_block_height: number; burn_block_hash: PgBytea; + is_nakamoto_block: boolean; }; export type DbBlockSignerSignature = {