Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Bitcoin Core Provider Block Retrieval Functionality #32

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions src/block-data-providers/bitcoin-core/interfaces.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,21 @@ export interface BlockTransaction {
vout: Output[];
}

export interface NetworkInfo {
version: number;
}

export interface Input {
txid: string;
vout: number;
scriptSig: {
hex: string;
};
prevout?: {
scriptPubKey: {
hex: string;
};
};
txinwitness: string[];
}

Expand Down
2 changes: 1 addition & 1 deletion src/block-data-providers/bitcoin-core/provider.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ describe('Bitcoin Core Provider', () => {
});

it('should process each transaction of a block appropriately', async () => {
const result = await provider.processBlock(3);
const result = await provider.processBlock(3, 2);
expect(result).toHaveLength(1);
expect(result).toEqual(
expect.arrayContaining([...parsedTransactions.values()]),
Expand Down
52 changes: 42 additions & 10 deletions src/block-data-providers/bitcoin-core/provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@ import { ConfigService } from '@nestjs/config';
import { BitcoinCoreConfig } from '@/configuration.model';
import { Injectable, Logger, OnApplicationBootstrap } from '@nestjs/common';
import { BitcoinNetwork } from '@/common/enum';
import { SATS_PER_BTC, TAPROOT_ACTIVATION_HEIGHT } from '@/common/constants';
import {
BITCOIN_CORE_FULL_VERBOSITY_VERSION,
SATS_PER_BTC,
TAPROOT_ACTIVATION_HEIGHT,
} from '@/common/constants';
import { Cron, CronExpression } from '@nestjs/schedule';
import {
IndexerService,
Expand All @@ -19,6 +23,7 @@ import {
Output,
RPCRequestBody,
Input,
NetworkInfo,
} from '@/block-data-providers/bitcoin-core/interfaces';
import axios from 'axios';
import * as currency from 'currency.js';
Expand Down Expand Up @@ -86,9 +91,15 @@ export class BitcoinCoreProvider
return;
}

const networkInfo = await this.getNetworkInfo();
const verbosityLevel = this.versionToVerbosity(networkInfo.version);

let height = state.indexedBlockHeight + 1;
for (height; height <= tipHeight; height++) {
const transactions = await this.processBlock(height);
const transactions = await this.processBlock(
height,
verbosityLevel,
);

for (const transaction of transactions) {
const { txid, vin, vout, blockHeight, blockHash } = transaction;
Expand All @@ -108,6 +119,13 @@ export class BitcoinCoreProvider
this.isSyncing = false;
}

private async getNetworkInfo(): Promise<NetworkInfo> {
return this.request({
method: 'getnetworkinfo',
params: [],
});
}

private async getTipHeight(): Promise<number> {
return this.request({
method: 'getblockcount',
Expand Down Expand Up @@ -139,14 +157,17 @@ export class BitcoinCoreProvider
});
}

public async processBlock(height: number): Promise<Transaction[]> {
public async processBlock(
height: number,
verbosityLevel: number,
): Promise<Transaction[]> {
const parsedTransactionList: Transaction[] = [];
const blockHash = await this.getBlockHash(height);
this.logger.debug(
`Processing block at height ${height}, hash ${blockHash}`,
);

const block = await this.getBlock(blockHash, 2);
const block = await this.getBlock(blockHash, verbosityLevel);

for (let i = 1; i < block.tx.length; i++) {
const parsedTransaction = await this.parseTransaction(
Expand Down Expand Up @@ -185,13 +206,20 @@ export class BitcoinCoreProvider
private async parseTransactionInput(
txnInput: Input,
): Promise<TransactionInput> {
const prevTransaction = await this.getRawTransaction(
txnInput.txid,
true,
);
let prevOutScript: string;
const vout = txnInput.vout;
const prevOutScript = prevTransaction.vout.find((out) => out.n == vout)
.scriptPubKey.hex;

if (txnInput.prevout != undefined) {
prevOutScript = txnInput.prevout.scriptPubKey.hex;
} else {
const prevTransaction = await this.getRawTransaction(
txnInput.txid,
true,
);

prevOutScript = prevTransaction.vout.find((out) => out.n == vout)
.scriptPubKey.hex;
}

return {
txid: txnInput.txid,
Expand Down Expand Up @@ -243,4 +271,8 @@ export class BitcoinCoreProvider
private convertToSatoshi(amount: number): number {
return currency(amount, { precision: 8 }).multiply(SATS_PER_BTC).value;
}

private versionToVerbosity(version: number): 2 | 3 {
return version >= BITCOIN_CORE_FULL_VERBOSITY_VERSION ? 3 : 2;
}
}
2 changes: 2 additions & 0 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,5 @@ export const NUMS_H = Buffer.from(
export const TAPROOT_ACTIVATION_HEIGHT = 709632;

export const SATS_PER_BTC = 100_000_000;

export const BITCOIN_CORE_FULL_VERBOSITY_VERSION = 23_0000;