diff --git a/docker/config/btc.conf.example b/docker/config/btc.conf.example index 121c170ea..352dc35b0 100644 --- a/docker/config/btc.conf.example +++ b/docker/config/btc.conf.example @@ -60,7 +60,6 @@ UTXO_SAVE_INTERVAL = 120000 # Save UTXOs interval in milliseconds [OP_NET] MODE = "ARCHIVE" # ARCHIVE, FULL, SNAP, LIGHT. Only ARCHIVE is supported at this time -ENABLED_AT_BLOCK = 0 # Block height at which the OP_NET should be enabled REINDEX = false # Set to true to reindex the OP_NET REINDEX_FROM_BLOCK = 0 # Block height from which to reindex the OP_NET diff --git a/src/components/openapi.yaml b/src/components/openapi.yaml index e58643f68..ccc0c8a5d 100644 --- a/src/components/openapi.yaml +++ b/src/components/openapi.yaml @@ -4,12 +4,12 @@ info: title: OpNet RPC API description: This document is the official API documentation of OpNet JSON-RPC. version: 1.0.0 - pointerResolutionBasePath: "/" + pointerResolutionBasePath: '/' swagger: 2.0 - basePath: "/" + basePath: '/' tags: - - name: "Websocket" - description: "OpNet websocket configuration related endpoints." + - name: 'Websocket' + description: 'OpNet websocket configuration related endpoints.' components: securitySchemes: BearerAuth: diff --git a/src/components/schemas/_index.yaml b/src/components/schemas/_index.yaml index 9d94274f9..71c76039a 100644 --- a/src/components/schemas/_index.yaml +++ b/src/components/schemas/_index.yaml @@ -48,7 +48,7 @@ components: address: type: string description: An address or public key hash. - example: "0222513da2b72f9f8e26a016087ee191fc60be4671cae286bd2f16261c026dcb12" + example: '0222513da2b72f9f8e26a016087ee191fc60be4671cae286bd2f16261c026dcb12' required: true InteractionTransaction: allOf: @@ -181,7 +181,7 @@ components: data: type: string description: The transaction to broadcast. - example: "02000000000101" + example: '02000000000101' required: true psbt: type: boolean @@ -200,6 +200,6 @@ components: amount: type: number description: The amount to wrap in satoshis - example: "0" + example: '0' default: 1000 required: true diff --git a/src/config/btc.sample.conf b/src/config/btc.sample.conf index 55aed91cd..40bafdeba 100644 --- a/src/config/btc.sample.conf +++ b/src/config/btc.sample.conf @@ -44,7 +44,6 @@ MODE = "ARCHIVE" # ARCHIVE, FULL, LIGHT. Only ARCHIVE is supported at this time # LIGHT NODES HAVE A LIMITED VIEW OF THE BLOCKCHAIN, they ONLY index 10k blocks from the latest block LIGHT_MODE_FROM_BLOCK = 10000 # Number of blocks to index in light mode -ENABLED_AT_BLOCK = 0 # Block height at which the OP_NET should be enabled REINDEX = true # Set to true to reindex the OP_NET REINDEX_FROM_BLOCK = 800000 # Block height from which to reindex the OP_NET diff --git a/src/protocols/OPNetAPIProtocol.proto b/src/protocols/OPNetAPIProtocol.proto index aa70840c9..ed0d95423 100644 --- a/src/protocols/OPNetAPIProtocol.proto +++ b/src/protocols/OPNetAPIProtocol.proto @@ -701,12 +701,12 @@ message PendingTransactionResponse { string firstSeen = 2; // Block height at which the transaction was observed (0x-prefixed hex). string blockHeight = 3; - // Theoretical gas limit for OPNet execution (0x-prefixed hex). - string theoreticalGasLimit = 4; - // Priority fee attached to the transaction (0x-prefixed hex). - string priorityFee = 5; - // Whether this transaction targets an OPNet contract. - bool isOPNet = 6; + // Theoretical gas limit for OPNet execution (0x-prefixed hex). Present only for OPNet transactions. + optional string theoreticalGasLimit = 4; + // Priority fee attached to the transaction (0x-prefixed hex). Present only for OPNet transactions. + optional string priorityFee = 5; + // The OPNet transaction type (Generic, Interaction, Deployment). + string transactionType = 6; // Whether the transaction was submitted as a PSBT. bool psbt = 7; // The transaction inputs. @@ -715,6 +715,14 @@ message PendingTransactionResponse { repeated MempoolTransactionOutput outputs = 9; // The full raw transaction as a hex string. string raw = 10; + // The sender address (p2tr format). Present only for OPNet transactions. + optional string from = 11; + // The target contract address (p2op format). Present only for OPNet transactions. + optional string contractAddress = 12; + // Hex-encoded calldata. Present only for OPNet transactions. + optional string calldata = 13; + // Hex-encoded bytecode. Present only for deployment transactions. + optional string bytecode = 14; } // Request: fetch the latest pending transactions with optional address filter. @@ -755,8 +763,8 @@ message NewMempoolTransactionNotification { uint32 subscriptionId = 1; // The txid of the new mempool transaction. string txId = 2; - // Whether this transaction targets an OPNet contract. - bool isOPNet = 3; + // The OPNet transaction type (Generic, Interaction, Deployment). + string transactionType = 3; // Unix timestamp in milliseconds when the transaction was observed. uint64 timestamp = 4; } diff --git a/src/src/api/data-converter/TransactionConverterForAPI.ts b/src/src/api/data-converter/TransactionConverterForAPI.ts index 538f6b746..78bde56dd 100644 --- a/src/src/api/data-converter/TransactionConverterForAPI.ts +++ b/src/src/api/data-converter/TransactionConverterForAPI.ts @@ -1,5 +1,5 @@ import { DataConverter } from '@btc-vision/bsi-common'; -import { toBase64, toHex } from '@btc-vision/bitcoin'; +import { toHex } from '@btc-vision/bitcoin'; import { Binary } from 'mongodb'; import { OPNetTransactionTypes } from '../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; import { @@ -40,18 +40,35 @@ export class TransactionConverterForAPI { ) satisfies EventReceiptDataForAPI[]) : []; + const hash: string = + transaction.hash instanceof Uint8Array + ? toHex(transaction.hash) + : (transaction.hash as Binary).toString('hex'); + + const id: string = + transaction.id instanceof Uint8Array + ? toHex(transaction.id) + : (transaction.id as Binary).toString('hex'); + const newTx: TransactionDocumentForAPI = { ...transaction, - hash: toHex(transaction.hash), - id: toHex(transaction.id), + hash: hash, + id: id, blockNumber: '0x' + DataConverter.fromDecimal128(transaction.blockHeight || 0n).toString(16), inputs: transaction.inputs?.map((input) => { + let originalTransactionId: string | undefined; + + if (input.originalTransactionId) { + originalTransactionId = + input.originalTransactionId instanceof Uint8Array + ? toHex(input.originalTransactionId) + : (input.originalTransactionId as Binary).toString('hex'); + } + return { ...input, - originalTransactionId: input.originalTransactionId - ? toHex(input.originalTransactionId) - : undefined, + originalTransactionId: originalTransactionId, scriptSignature: input.scriptSignature, }; }), diff --git a/src/src/api/json-rpc/types/interfaces/params/blocks/BlockByChecksumParams.ts b/src/src/api/json-rpc/types/interfaces/params/blocks/BlockByChecksumParams.ts index 948ac7506..d32302c47 100644 --- a/src/src/api/json-rpc/types/interfaces/params/blocks/BlockByChecksumParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/blocks/BlockByChecksumParams.ts @@ -1,8 +1,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; -export interface BlockByChecksumAsObject - extends JSONRpcParams { +export interface BlockByChecksumAsObject extends JSONRpcParams { readonly blockHash: string; readonly sendTransactions?: boolean; } diff --git a/src/src/api/json-rpc/types/interfaces/params/epochs/EpochByNumberParams.ts b/src/src/api/json-rpc/types/interfaces/params/epochs/EpochByNumberParams.ts index 5a5e481f6..688af057f 100644 --- a/src/src/api/json-rpc/types/interfaces/params/epochs/EpochByNumberParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/epochs/EpochByNumberParams.ts @@ -1,8 +1,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; -export interface EpochByNumberParamsAsObject - extends JSONRpcParams { +export interface EpochByNumberParamsAsObject extends JSONRpcParams { readonly height: bigint | -1 | string; readonly includeSubmissions?: boolean; } diff --git a/src/src/api/json-rpc/types/interfaces/params/epochs/GetEpochTemplateParams.ts b/src/src/api/json-rpc/types/interfaces/params/epochs/GetEpochTemplateParams.ts index 62afa8c94..5cd72491e 100644 --- a/src/src/api/json-rpc/types/interfaces/params/epochs/GetEpochTemplateParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/epochs/GetEpochTemplateParams.ts @@ -1,8 +1,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; -export interface EpochTemplateParamsAsObject - extends JSONRpcParams {} +export interface EpochTemplateParamsAsObject extends JSONRpcParams {} export type EpochTemplateAsArray = [EpochTemplateParamsAsObject]; diff --git a/src/src/api/json-rpc/types/interfaces/params/mempool/GetLatestPendingTransactionsParams.ts b/src/src/api/json-rpc/types/interfaces/params/mempool/GetLatestPendingTransactionsParams.ts index 5f19b55c8..2b9279c35 100644 --- a/src/src/api/json-rpc/types/interfaces/params/mempool/GetLatestPendingTransactionsParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/mempool/GetLatestPendingTransactionsParams.ts @@ -2,8 +2,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; /** Object-form parameters for {@link JSONRpcMethods.GET_LATEST_PENDING_TRANSACTIONS}. */ -export interface GetLatestPendingTransactionsParamsAsObject - extends JSONRpcParams { +export interface GetLatestPendingTransactionsParamsAsObject extends JSONRpcParams { /** A single address to auto-resolve into all derived wallet address types. */ readonly address?: string; /** Explicit list of addresses to filter mempool transactions by. */ diff --git a/src/src/api/json-rpc/types/interfaces/params/mempool/GetMempoolInfoParams.ts b/src/src/api/json-rpc/types/interfaces/params/mempool/GetMempoolInfoParams.ts index 865015737..a843e1a39 100644 --- a/src/src/api/json-rpc/types/interfaces/params/mempool/GetMempoolInfoParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/mempool/GetMempoolInfoParams.ts @@ -2,8 +2,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; /** Object-form parameters for {@link JSONRpcMethods.GET_MEMPOOL_INFO} (none required). */ -export interface GetMempoolInfoParamsAsObject - extends JSONRpcParams {} +export interface GetMempoolInfoParamsAsObject extends JSONRpcParams {} /** Array-form parameters (empty). */ export type GetMempoolInfoParamsAsArray = []; diff --git a/src/src/api/json-rpc/types/interfaces/params/mempool/GetPendingTransactionParams.ts b/src/src/api/json-rpc/types/interfaces/params/mempool/GetPendingTransactionParams.ts index 0badec8f3..595fe81a0 100644 --- a/src/src/api/json-rpc/types/interfaces/params/mempool/GetPendingTransactionParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/mempool/GetPendingTransactionParams.ts @@ -2,8 +2,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; /** Object-form parameters for {@link JSONRpcMethods.GET_PENDING_TRANSACTION}. */ -export interface GetPendingTransactionParamsAsObject - extends JSONRpcParams { +export interface GetPendingTransactionParamsAsObject extends JSONRpcParams { /** The 64-character hex transaction hash. */ readonly hash: string; } diff --git a/src/src/api/json-rpc/types/interfaces/params/transactions/BroadcastTransactionParams.ts b/src/src/api/json-rpc/types/interfaces/params/transactions/BroadcastTransactionParams.ts index ee6d98a4d..8c661bb03 100644 --- a/src/src/api/json-rpc/types/interfaces/params/transactions/BroadcastTransactionParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/transactions/BroadcastTransactionParams.ts @@ -1,8 +1,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; -export interface BroadcastTransactionParamsAsObject - extends JSONRpcParams { +export interface BroadcastTransactionParamsAsObject extends JSONRpcParams { readonly data: string; readonly psbt?: boolean; } diff --git a/src/src/api/json-rpc/types/interfaces/params/transactions/TransactionByHashParams.ts b/src/src/api/json-rpc/types/interfaces/params/transactions/TransactionByHashParams.ts index b5b0d7775..94e35f6e7 100644 --- a/src/src/api/json-rpc/types/interfaces/params/transactions/TransactionByHashParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/transactions/TransactionByHashParams.ts @@ -1,8 +1,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; -export interface TransactionByHashParamsAsObject - extends JSONRpcParams { +export interface TransactionByHashParamsAsObject extends JSONRpcParams { readonly hash: string; } diff --git a/src/src/api/json-rpc/types/interfaces/params/transactions/TransactionReceiptsParams.ts b/src/src/api/json-rpc/types/interfaces/params/transactions/TransactionReceiptsParams.ts index e6a476160..48889d7fe 100644 --- a/src/src/api/json-rpc/types/interfaces/params/transactions/TransactionReceiptsParams.ts +++ b/src/src/api/json-rpc/types/interfaces/params/transactions/TransactionReceiptsParams.ts @@ -1,8 +1,7 @@ import { JSONRpcMethods } from '../../../enums/JSONRpcMethods.js'; import { JSONRpcParams } from '../../JSONRpcParams.js'; -export interface TransactionReceiptsParamsAsObject - extends JSONRpcParams { +export interface TransactionReceiptsParamsAsObject extends JSONRpcParams { readonly hash: string; } diff --git a/src/src/api/json-rpc/types/interfaces/results/mempool/MempoolTransactionData.ts b/src/src/api/json-rpc/types/interfaces/results/mempool/MempoolTransactionData.ts index 169fcdbec..6bf7a8724 100644 --- a/src/src/api/json-rpc/types/interfaces/results/mempool/MempoolTransactionData.ts +++ b/src/src/api/json-rpc/types/interfaces/results/mempool/MempoolTransactionData.ts @@ -26,12 +26,8 @@ export interface MempoolTransactionData { readonly firstSeen: string; /** Block height at which the transaction was observed (`0x`-prefixed hex). */ readonly blockHeight: string; - /** Theoretical gas limit for OPNet execution (`0x`-prefixed hex). */ - readonly theoreticalGasLimit: string; - /** Priority fee attached to the transaction (`0x`-prefixed hex). */ - readonly priorityFee: string; - /** Whether this transaction targets an OPNet contract. */ - readonly isOPNet: boolean; + /** The OPNet transaction type (Generic, Interaction, Deployment). */ + readonly transactionType: string; /** Whether the transaction was submitted as a PSBT. */ readonly psbt: boolean; /** The transaction inputs. */ @@ -40,4 +36,19 @@ export interface MempoolTransactionData { readonly outputs: MempoolTransactionOutput[]; /** The full raw transaction as a hex string. */ readonly raw: string; + + // OPNet-specific fields (present only for OPNet transactions) + + /** Theoretical gas limit for OPNet execution (`0x`-prefixed hex). */ + readonly theoreticalGasLimit?: string; + /** Priority fee attached to the transaction (`0x`-prefixed hex). */ + readonly priorityFee?: string; + /** The sender address (p2tr format). */ + readonly from?: string; + /** The target contract address (p2op format). */ + readonly contractAddress?: string; + /** Hex-encoded calldata. */ + readonly calldata?: string; + /** Hex-encoded bytecode (deployment transactions only). */ + readonly bytecode?: string; } diff --git a/src/src/api/json-rpc/types/interfaces/results/transactions/BroadcastTransactionResult.ts b/src/src/api/json-rpc/types/interfaces/results/transactions/BroadcastTransactionResult.ts index 12336bee7..301351e24 100644 --- a/src/src/api/json-rpc/types/interfaces/results/transactions/BroadcastTransactionResult.ts +++ b/src/src/api/json-rpc/types/interfaces/results/transactions/BroadcastTransactionResult.ts @@ -7,6 +7,7 @@ interface IBroadcastTransactionResult { identifier?: bigint; modifiedTransaction?: string; finalizedTransaction?: boolean; + transactionType?: string; } export type BroadcastTransactionResult = IBroadcastTransactionResult; diff --git a/src/src/api/routes/api/v1/address/GetBalanceRoute.ts b/src/src/api/routes/api/v1/address/GetBalanceRoute.ts index 81fb3931b..78136418d 100644 --- a/src/src/api/routes/api/v1/address/GetBalanceRoute.ts +++ b/src/src/api/routes/api/v1/address/GetBalanceRoute.ts @@ -73,7 +73,9 @@ export class GetBalanceRoute extends Route< if (data) { this.safeJson(res, 200, data); } else { - this.safeJson(res, 400, { error: 'Could not fetch balance for the given address.' }); + this.safeJson(res, 400, { + error: 'Could not fetch balance for the given address.', + }); } } catch (err) { this.handleDefaultError(res, err as Error); diff --git a/src/src/api/routes/api/v1/block/BlockByChecksum.ts b/src/src/api/routes/api/v1/block/BlockByChecksum.ts index 304d62092..72ca058dd 100644 --- a/src/src/api/routes/api/v1/block/BlockByChecksum.ts +++ b/src/src/api/routes/api/v1/block/BlockByChecksum.ts @@ -23,7 +23,12 @@ export class BlockByChecksum extends BlockRoute { let blockChecksum: SafeString = BlockParamsConverter.getParameterAsStringForBlock(params); - blockChecksum = blockChecksum ? (blockChecksum.startsWith('0x') ? blockChecksum.slice(2) : blockChecksum).toLowerCase() : null; + blockChecksum = blockChecksum + ? (blockChecksum.startsWith('0x') + ? blockChecksum.slice(2) + : blockChecksum + ).toLowerCase() + : null; const includeTransactions: boolean = this.getParameterAsBoolean(params); if (!blockChecksum) { @@ -34,7 +39,12 @@ export class BlockByChecksum extends BlockRoute { if (blockChecksum.length !== 64) throw new Error(`Invalid checksum length`); - return await this.getCachedBlockData(includeTransactions, undefined, blockChecksum, true); + return await this.getCachedBlockData( + includeTransactions, + undefined, + blockChecksum, + true, + ); } catch (e) { if (Config.DEV_MODE) { this.error(`Error details: ${(e as Error).stack}`); @@ -86,7 +96,9 @@ export class BlockByChecksum extends BlockRoute { if (data) { this.safeJson(res, 200, data); } else { - this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' }); + this.safeJson(res, 400, { + error: 'Could not fetch latest block header. Is this node synced?', + }); } } catch (err) { this.handleDefaultError(res, err as Error); diff --git a/src/src/api/routes/api/v1/block/BlockByHash.ts b/src/src/api/routes/api/v1/block/BlockByHash.ts index a3f4bcd3b..bf33c88c3 100644 --- a/src/src/api/routes/api/v1/block/BlockByHash.ts +++ b/src/src/api/routes/api/v1/block/BlockByHash.ts @@ -80,7 +80,9 @@ export class BlockByHash extends BlockRoute { if (data) { this.safeJson(res, 200, data); } else { - this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' }); + this.safeJson(res, 400, { + error: 'Could not fetch latest block header. Is this node synced?', + }); } } catch (err) { this.handleDefaultError(res, err as Error); diff --git a/src/src/api/routes/api/v1/block/BlockByNumber.ts b/src/src/api/routes/api/v1/block/BlockByNumber.ts index e7943f247..5074b9043 100644 --- a/src/src/api/routes/api/v1/block/BlockByNumber.ts +++ b/src/src/api/routes/api/v1/block/BlockByNumber.ts @@ -72,7 +72,9 @@ export class BlockByNumber extends BlockRoute { if (data) { this.safeJson(res, 200, data); } else { - this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' }); + this.safeJson(res, 400, { + error: 'Could not fetch latest block header. Is this node synced?', + }); } } catch (err) { this.handleDefaultError(res, err as Error); diff --git a/src/src/api/routes/api/v1/block/GasRoute.ts b/src/src/api/routes/api/v1/block/GasRoute.ts index cb064465b..ddd27f3bf 100644 --- a/src/src/api/routes/api/v1/block/GasRoute.ts +++ b/src/src/api/routes/api/v1/block/GasRoute.ts @@ -112,7 +112,9 @@ export class GasRoute extends Route extends Route< throw new Error('Invalid hash parameter: expected a string'); } - const cleanHash: string | undefined = params.hash?.startsWith('0x') ? params.hash.slice(2) : params.hash; + const cleanHash: string | undefined = params.hash?.startsWith('0x') + ? params.hash.slice(2) + : params.hash; if (cleanHash.length !== 64) { throw new Error('Invalid hash length. Expected 64 hex characters for SHA-256 hash'); } diff --git a/src/src/api/routes/api/v1/epochs/LatestEpoch.ts b/src/src/api/routes/api/v1/epochs/LatestEpoch.ts index e1c2353f8..63ff09ae5 100644 --- a/src/src/api/routes/api/v1/epochs/LatestEpoch.ts +++ b/src/src/api/routes/api/v1/epochs/LatestEpoch.ts @@ -57,7 +57,9 @@ export class LatestEpoch extends Route< if (data) { this.safeJson(res, 200, data); } else { - this.safeJson(res, 400, { error: 'Could not fetch latest epoch. Is this node synced?' }); + this.safeJson(res, 400, { + error: 'Could not fetch latest epoch. Is this node synced?', + }); } } catch (err) { this.handleDefaultError(res, err as Error); diff --git a/src/src/api/routes/api/v1/mempool/GetLatestPendingTransactions.ts b/src/src/api/routes/api/v1/mempool/GetLatestPendingTransactions.ts index b9401912d..519e7737c 100644 --- a/src/src/api/routes/api/v1/mempool/GetLatestPendingTransactions.ts +++ b/src/src/api/routes/api/v1/mempool/GetLatestPendingTransactions.ts @@ -4,12 +4,8 @@ import { MiddlewareNext } from '@btc-vision/hyper-express/types/components/middl import { Config } from '../../../../../config/Config.js'; import { Routes, RouteType } from '../../../../enums/Routes.js'; import { JSONRpcMethods } from '../../../../json-rpc/types/enums/JSONRpcMethods.js'; -import { - GetLatestPendingTransactionsParams -} from '../../../../json-rpc/types/interfaces/params/mempool/GetLatestPendingTransactionsParams.js'; -import { - GetLatestPendingTransactionsResult -} from '../../../../json-rpc/types/interfaces/results/mempool/GetLatestPendingTransactionsResult.js'; +import { GetLatestPendingTransactionsParams } from '../../../../json-rpc/types/interfaces/params/mempool/GetLatestPendingTransactionsParams.js'; +import { GetLatestPendingTransactionsResult } from '../../../../json-rpc/types/interfaces/results/mempool/GetLatestPendingTransactionsResult.js'; import { IPubKeyNotFoundError, PublicKeyInfo, diff --git a/src/src/api/routes/api/v1/mempool/GetMempoolInfo.ts b/src/src/api/routes/api/v1/mempool/GetMempoolInfo.ts index be7a2109d..3c5d9f15f 100644 --- a/src/src/api/routes/api/v1/mempool/GetMempoolInfo.ts +++ b/src/src/api/routes/api/v1/mempool/GetMempoolInfo.ts @@ -41,9 +41,7 @@ export class GetMempoolInfo extends Route< } /** {@inheritDoc Route.getDataRPC} */ - public async getDataRPC( - _params?: GetMempoolInfoParams, - ): Promise { + public async getDataRPC(_params?: GetMempoolInfoParams): Promise { return await this.getData(); } diff --git a/src/src/api/routes/api/v1/mempool/MempoolTransactionConverter.ts b/src/src/api/routes/api/v1/mempool/MempoolTransactionConverter.ts index 06afe5509..d16c0b5ab 100644 --- a/src/src/api/routes/api/v1/mempool/MempoolTransactionConverter.ts +++ b/src/src/api/routes/api/v1/mempool/MempoolTransactionConverter.ts @@ -17,9 +17,7 @@ export class MempoolTransactionConverter { id: tx.id, firstSeen: tx.firstSeen ? tx.firstSeen.toISOString() : new Date(0).toISOString(), blockHeight: '0x' + tx.blockHeight.toString(16), - theoreticalGasLimit: '0x' + tx.theoreticalGasLimit.toString(16), - priorityFee: '0x' + tx.priorityFee.toString(16), - isOPNet: tx.isOPNet, + transactionType: tx.transactionType, psbt: tx.psbt, inputs: tx.inputs.map((input) => ({ transactionId: input.transactionId, @@ -32,6 +30,16 @@ export class MempoolTransactionConverter { scriptPubKey: toHex(output.data), })), raw: toHex(tx.data), + theoreticalGasLimit: + tx.theoreticalGasLimit !== undefined + ? '0x' + tx.theoreticalGasLimit.toString(16) + : undefined, + priorityFee: + tx.priorityFee !== undefined ? '0x' + tx.priorityFee.toString(16) : undefined, + from: tx.from, + contractAddress: tx.contractAddress, + calldata: tx.calldata, + bytecode: tx.bytecode, }; } diff --git a/src/src/api/routes/api/v1/opnet/OPNetWitnessRoute.ts b/src/src/api/routes/api/v1/opnet/OPNetWitnessRoute.ts index 905d3e1b3..b165192c7 100644 --- a/src/src/api/routes/api/v1/opnet/OPNetWitnessRoute.ts +++ b/src/src/api/routes/api/v1/opnet/OPNetWitnessRoute.ts @@ -81,7 +81,9 @@ export class OPNetWitnessRoute extends Route< if (data) { this.safeJson(res, 200, data); } else { - this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' }); + this.safeJson(res, 400, { + error: 'Could not fetch latest block header. Is this node synced?', + }); } } catch (err) { this.handleDefaultError(res, err as Error); diff --git a/src/src/api/routes/api/v1/transaction/BroadcastTransaction.ts b/src/src/api/routes/api/v1/transaction/BroadcastTransaction.ts index 33cddf94a..582ebcc74 100644 --- a/src/src/api/routes/api/v1/transaction/BroadcastTransaction.ts +++ b/src/src/api/routes/api/v1/transaction/BroadcastTransaction.ts @@ -21,6 +21,7 @@ import { TransactionSizeValidator } from '../../../../../poc/mempool/data-valida import { Config } from '../../../../../config/Config.js'; import { fromBase64, fromHex, Transaction } from '@btc-vision/bitcoin'; import { WSManager } from '../../../../websocket/WebSocketManager.js'; +import { OPNetTransactionTypes } from '../../../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; export class BroadcastTransaction extends Route< Routes.BROADCAST_TRANSACTION, @@ -105,7 +106,11 @@ export class BroadcastTransaction extends Route< // Notify mempool subscribers of the new transaction if (mergedResult.success && mergedResult.result) { - WSManager.onMempoolTransaction(mergedResult.result, true); + const txType = + (mergedResult.transactionType as OPNetTransactionTypes) || + OPNetTransactionTypes.Generic; + + WSManager.onMempoolTransaction(mergedResult.result, txType); } return mergedResult; @@ -171,7 +176,9 @@ export class BroadcastTransaction extends Route< if (data) { this.safeJson(res, 200, data); } else { - this.safeJson(res, 400, { error: 'Could not fetch latest block header. Is this node synced?' }); + this.safeJson(res, 400, { + error: 'Could not fetch latest block header. Is this node synced?', + }); } } catch (err) { this.handleDefaultError(res, err as Error); diff --git a/src/src/api/routes/api/v1/transaction/GetPreimage.ts b/src/src/api/routes/api/v1/transaction/GetPreimage.ts index 9e7e30b05..ca553d948 100644 --- a/src/src/api/routes/api/v1/transaction/GetPreimage.ts +++ b/src/src/api/routes/api/v1/transaction/GetPreimage.ts @@ -65,7 +65,9 @@ export class GetPreimage extends Route< if (data) { this.safeJson(res, 200, data); } else { - this.safeJson(res, 400, { error: 'Could not fetch preimage data. Is this node synced?' }); + this.safeJson(res, 400, { + error: 'Could not fetch preimage data. Is this node synced?', + }); } } catch (err) { this.handleDefaultError(res, err as Error); diff --git a/src/src/api/websocket/OpcodeRegistry.ts b/src/src/api/websocket/OpcodeRegistry.ts index 448a1e162..3b6a721ca 100644 --- a/src/src/api/websocket/OpcodeRegistry.ts +++ b/src/src/api/websocket/OpcodeRegistry.ts @@ -2,7 +2,11 @@ import { Type } from 'protobufjs'; import { APIProtobufLoader } from './proto/APIProtobufLoader.js'; import { APIPacket, PackedMessage } from './packets/APIPacket.js'; import { APIPacketType } from './packets/types/APIPacketTypes.js'; -import { OpcodeNames, WebSocketRequestOpcode, WebSocketResponseOpcode, } from './types/opcodes/WebSocketOpcodes.js'; +import { + OpcodeNames, + WebSocketRequestOpcode, + WebSocketResponseOpcode, +} from './types/opcodes/WebSocketOpcodes.js'; /** * Handler function type for processing incoming requests. diff --git a/src/src/api/websocket/ProtocolHandler.ts b/src/src/api/websocket/ProtocolHandler.ts index 493564ecf..20f588dd1 100644 --- a/src/src/api/websocket/ProtocolHandler.ts +++ b/src/src/api/websocket/ProtocolHandler.ts @@ -130,7 +130,11 @@ export class ProtocolHandler extends Logger { const opcodeName = OpcodeNames[opcode as WebSocketRequestOpcode] ?? `0x${opcode.toString(16)}`; this.warn(`Failed to deserialize ${opcodeName}: ${error}`); - client.sendError(requestId, ProtocolError.MALFORMED_MESSAGE, 'Failed to deserialize request'); + client.sendError( + requestId, + ProtocolError.MALFORMED_MESSAGE, + 'Failed to deserialize request', + ); return false; } @@ -353,7 +357,11 @@ export class ProtocolHandler extends Logger { this.warn( `Failed to decode plugin request for opcode 0x${opcode.toString(16)}: ${error}`, ); - client.sendError(requestId, ProtocolError.MALFORMED_MESSAGE, 'Failed to deserialize request'); + client.sendError( + requestId, + ProtocolError.MALFORMED_MESSAGE, + 'Failed to deserialize request', + ); return false; } diff --git a/src/src/api/websocket/WebSocketClient.ts b/src/src/api/websocket/WebSocketClient.ts index 7085338ff..956efa5f2 100644 --- a/src/src/api/websocket/WebSocketClient.ts +++ b/src/src/api/websocket/WebSocketClient.ts @@ -325,7 +325,11 @@ export class WebSocketClient extends Logger { // Use packPayload to get just the protobuf bytes (no opcode) const payload = errorPacket.packPayload(errorData); // Send using sendResponse to ensure consistent format: [opcode][requestId][payload] - return this.sendResponse(errorPacket.getOpcode() as WebSocketResponseOpcode, requestId, payload); + return this.sendResponse( + errorPacket.getOpcode() as WebSocketResponseOpcode, + requestId, + payload, + ); } catch (error) { this.error(`Failed to send error response: ${error}`); return false; @@ -336,7 +340,11 @@ export class WebSocketClient extends Logger { * Send a response with a specific opcode and requestId * Format: [opcode (1)] [requestId (4 bytes LE)] [payload] */ - public sendResponse(opcode: WebSocketResponseOpcode, requestId: number, payload: Uint8Array): boolean { + public sendResponse( + opcode: WebSocketResponseOpcode, + requestId: number, + payload: Uint8Array, + ): boolean { const message = new Uint8Array(1 + 4 + payload.length); message[0] = opcode; // Write requestId as little-endian uint32 diff --git a/src/src/api/websocket/WebSocketManager.ts b/src/src/api/websocket/WebSocketManager.ts index 5fcad4334..1c16f0bf0 100644 --- a/src/src/api/websocket/WebSocketManager.ts +++ b/src/src/api/websocket/WebSocketManager.ts @@ -12,6 +12,7 @@ import { WebSocketConfig } from '../../config/interfaces/IBtcIndexerConfig.js'; import { P2PVersion } from '../../poc/configurations/P2PVersion.js'; import type { PluginOpcodeRegistry } from '../../plugins/api/websocket/PluginOpcodeRegistry.js'; import type { IPluginOpcodeInfo } from '../../plugins/interfaces/IPluginMessages.js'; +import { OPNetTransactionTypes } from '../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; /** * Manager metrics @@ -445,9 +446,9 @@ export class WebSocketManager extends Logger { * Broadcasts a new mempool transaction notification to all subscribed WebSocket clients. * * @param txId - The txid of the transaction that entered the mempool. - * @param isOPNet - Whether the transaction targets an OPNet contract. + * @param transactionType - The OPNet transaction type (Generic, Interaction, Deployment). */ - public onMempoolTransaction(txId: string, isOPNet: boolean): void { + public onMempoolTransaction(txId: string, transactionType: OPNetTransactionTypes): void { if (!this.enabled) { return; } @@ -462,7 +463,7 @@ export class WebSocketManager extends Logger { const notification = { subscriptionId: 0, // Will be set per-client txId, - isOPNet, + transactionType, timestamp: BigInt(Date.now()), }; diff --git a/src/src/api/websocket/handlers/HandlerRegistry.ts b/src/src/api/websocket/handlers/HandlerRegistry.ts index 070196f62..18b7b882a 100644 --- a/src/src/api/websocket/handlers/HandlerRegistry.ts +++ b/src/src/api/websocket/handlers/HandlerRegistry.ts @@ -9,12 +9,8 @@ import { WebSocketAPIError } from '../ProtocolHandler.js'; import { DefinedRoutes } from '../../routes/DefinedRoutes.js'; import { Routes } from '../../enums/Routes.js'; import { PackedMessage } from '../packets/APIPacket.js'; -import { - BlockHeaderAPIDocumentWithTransactions -} from '../../../db/documents/interfaces/BlockHeaderAPIDocumentWithTransactions.js'; -import { - OPNetTransactionTypes -} from '../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; +import { BlockHeaderAPIDocumentWithTransactions } from '../../../db/documents/interfaces/BlockHeaderAPIDocumentWithTransactions.js'; +import { OPNetTransactionTypes } from '../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; // Import typed request interfaces import { @@ -430,9 +426,10 @@ export class HandlerRegistry extends Logger { WebSocketRequestOpcode.BROADCAST_TRANSACTION, async (request: PackedMessage) => { const route = DefinedRoutes[Routes.BROADCAST_TRANSACTION] as BroadcastTransaction; - const txHex = request.transaction instanceof Uint8Array - ? toHex(request.transaction) - : toHex(new Uint8Array(request.transaction)); + const txHex = + request.transaction instanceof Uint8Array + ? toHex(request.transaction) + : toHex(new Uint8Array(request.transaction)); const result = await route.getData({ data: txHex, @@ -495,7 +492,9 @@ export class HandlerRegistry extends Logger { APIRegistry.registerHandler( WebSocketRequestOpcode.GET_LATEST_PENDING_TRANSACTIONS, async (request: PackedMessage) => { - const route = DefinedRoutes[Routes.MEMPOOL_TRANSACTIONS] as GetLatestPendingTransactions; + const route = DefinedRoutes[ + Routes.MEMPOOL_TRANSACTIONS + ] as GetLatestPendingTransactions; const result = await route.getData({ address: request.address || undefined, addresses: request.addresses?.length ? request.addresses : undefined, diff --git a/src/src/api/websocket/types/opcodes/WebSocketOpcodes.ts b/src/src/api/websocket/types/opcodes/WebSocketOpcodes.ts index ce4ae153b..91d271c1b 100644 --- a/src/src/api/websocket/types/opcodes/WebSocketOpcodes.ts +++ b/src/src/api/websocket/types/opcodes/WebSocketOpcodes.ts @@ -146,7 +146,8 @@ export const RequestToResponseOpcode: Readonly< [WebSocketRequestOpcode.GET_MEMPOOL_INFO]: WebSocketResponseOpcode.MEMPOOL_INFO, [WebSocketRequestOpcode.GET_PENDING_TRANSACTION]: WebSocketResponseOpcode.PENDING_TRANSACTION, - [WebSocketRequestOpcode.GET_LATEST_PENDING_TRANSACTIONS]: WebSocketResponseOpcode.LATEST_PENDING_TRANSACTIONS, + [WebSocketRequestOpcode.GET_LATEST_PENDING_TRANSACTIONS]: + WebSocketResponseOpcode.LATEST_PENDING_TRANSACTIONS, [WebSocketRequestOpcode.GET_BALANCE]: WebSocketResponseOpcode.BALANCE, [WebSocketRequestOpcode.GET_UTXOS]: WebSocketResponseOpcode.UTXOS, diff --git a/src/src/blockchain-indexer/fetcher/RPCBlockFetcher.ts b/src/src/blockchain-indexer/fetcher/RPCBlockFetcher.ts index 38a0c457f..b3b9ef91a 100644 --- a/src/src/blockchain-indexer/fetcher/RPCBlockFetcher.ts +++ b/src/src/blockchain-indexer/fetcher/RPCBlockFetcher.ts @@ -136,9 +136,7 @@ export class RPCBlockFetcher extends BlockFetcher { throw new Error(`Error fetching block ${blockHash}. (response is null)`); } - private async getBlockHashAndRetryIfNull( - blockHeight: bigint, - ): Promise { + private async getBlockHashAndRetryIfNull(blockHeight: bigint): Promise { for (let retries = 0; retries <= this.maxRetries; retries++) { try { const blockHash: string | null = await this.rpc.getBlockHash(Number(blockHeight)); diff --git a/src/src/blockchain-indexer/processor/block/Block.ts b/src/src/blockchain-indexer/processor/block/Block.ts index 23d26a9f9..20426f1da 100644 --- a/src/src/blockchain-indexer/processor/block/Block.ts +++ b/src/src/blockchain-indexer/processor/block/Block.ts @@ -3,11 +3,20 @@ import { TransactionData } from '@btc-vision/bitcoin-rpc'; import { DataConverter, DebugLevel, Logger } from '@btc-vision/bsi-common'; import { fromHex, Network, toHex } from '@btc-vision/bitcoin'; import { Config } from '../../../config/Config.js'; -import { BlockHeaderChecksumProof, BlockHeaderDocument, } from '../../../db/interfaces/IBlockHeaderBlockDocument.js'; -import { ITransactionDocumentBasic, TransactionDocument, } from '../../../db/interfaces/ITransactionDocument.js'; +import { + BlockHeaderChecksumProof, + BlockHeaderDocument, +} from '../../../db/interfaces/IBlockHeaderBlockDocument.js'; +import { + ITransactionDocumentBasic, + TransactionDocument, +} from '../../../db/interfaces/ITransactionDocument.js'; import { EvaluatedStates } from '../../../vm/evaluated/EvaluatedStates.js'; import { VMManager } from '../../../vm/VMManager.js'; -import { OPNetInteractionTypeValues, OPNetTransactionTypes, } from '../transaction/enums/OPNetTransactionTypes.js'; +import { + OPNetInteractionTypeValues, + OPNetTransactionTypes, +} from '../transaction/enums/OPNetTransactionTypes.js'; import { TransactionFactory } from '../transaction/transaction-factory/TransactionFactory.js'; import { TransactionSorter } from '../transaction/transaction-sorter/TransactionSorter.js'; import { Transaction } from '../transaction/Transaction.js'; @@ -1318,7 +1327,6 @@ export class Block { this.height, this.network, this.allowedSolutions, - true, this.addressCache, ); diff --git a/src/src/blockchain-indexer/processor/block/merkle/EpochMerkleTree.ts b/src/src/blockchain-indexer/processor/block/merkle/EpochMerkleTree.ts index 3d01873e3..21b481076 100644 --- a/src/src/blockchain-indexer/processor/block/merkle/EpochMerkleTree.ts +++ b/src/src/blockchain-indexer/processor/block/merkle/EpochMerkleTree.ts @@ -171,7 +171,11 @@ export class EpochMerkleTree { return merkleProof.verify(root, RustMerkleTree.hash(attestationBytes)); } - public static verifyEpochData(root: Uint8Array, proofs: Uint8Array[], data: Uint8Array): boolean { + public static verifyEpochData( + root: Uint8Array, + proofs: Uint8Array[], + data: Uint8Array, + ): boolean { const merkleProof = new MerkleProof(proofs); return merkleProof.verifyData(root, data); } @@ -221,7 +225,11 @@ export class EpochMerkleTree { const attestation: Attestation = { type: attPackage.attestation.type, blockNumber: attPackage.attestation.blockNumber, - checksumRoot: fromHex(attPackage.attestation.checksumRoot.startsWith('0x') ? attPackage.attestation.checksumRoot.slice(2) : attPackage.attestation.checksumRoot), + checksumRoot: fromHex( + attPackage.attestation.checksumRoot.startsWith('0x') + ? attPackage.attestation.checksumRoot.slice(2) + : attPackage.attestation.checksumRoot, + ), signature: attPackage.attestation.signature, timestamp: attPackage.attestation.timestamp, publicKey: attPackage.attestation.publicKey, @@ -229,7 +237,11 @@ export class EpochMerkleTree { const isValid = EpochMerkleTree.verifyAttestation(root, attestation, attPackage.proofs); const computedRoot = new MerkleProof(attPackage.proofs).rootHex( - fromHex(attPackage.leafHash.startsWith('0x') ? attPackage.leafHash.slice(2) : attPackage.leafHash), + fromHex( + attPackage.leafHash.startsWith('0x') + ? attPackage.leafHash.slice(2) + : attPackage.leafHash, + ), ); return { @@ -414,7 +426,9 @@ export class EpochMerkleTree { .map((hash) => new Uint8Array(hash)); } - public getEpochDataProof(epochDataBytes: Uint8Array | undefined = this.epochBytes): Uint8Array[] { + public getEpochDataProof( + epochDataBytes: Uint8Array | undefined = this.epochBytes, + ): Uint8Array[] { if (!epochDataBytes) { throw new Error('Epoch data bytes are not provided'); } @@ -512,8 +526,7 @@ export class EpochMerkleTree { epoch: this.getEpochData(), metadata: { chainId: '0x' + toHex(new Uint8Array(chainId)), - protocolId: - '0x' + toHex(new Uint8Array(OPNetConsensus.consensus.PROTOCOL_ID)), + protocolId: '0x' + toHex(new Uint8Array(OPNetConsensus.consensus.PROTOCOL_ID)), treeHeight: Math.ceil(Math.log2(this.attestations.length + 1)), leafCount: this.attestations.length + 1, generatedAt: Date.now(), diff --git a/src/src/blockchain-indexer/processor/block/merkle/ReceiptMerkleTree.ts b/src/src/blockchain-indexer/processor/block/merkle/ReceiptMerkleTree.ts index c2791310d..e4cdf6fdc 100644 --- a/src/src/blockchain-indexer/processor/block/merkle/ReceiptMerkleTree.ts +++ b/src/src/blockchain-indexer/processor/block/merkle/ReceiptMerkleTree.ts @@ -144,7 +144,9 @@ export class ReceiptMerkleTree extends MerkleTree { return proofs; } - public getEverythingWithProofs(): AddressMap> | undefined { + public getEverythingWithProofs(): + | AddressMap> + | undefined { if (!this._tree) { return; } diff --git a/src/src/blockchain-indexer/processor/epoch/EpochManager.ts b/src/src/blockchain-indexer/processor/epoch/EpochManager.ts index 97faea1a2..7cb468306 100644 --- a/src/src/blockchain-indexer/processor/epoch/EpochManager.ts +++ b/src/src/blockchain-indexer/processor/epoch/EpochManager.ts @@ -299,7 +299,11 @@ export class EpochManager extends Logger { throw new Error(`No block header found for mining target block ${targetBlock}`); } - const checksumRoot = fromHex(header.checksumRoot.startsWith('0x') ? header.checksumRoot.slice(2) : header.checksumRoot); + const checksumRoot = fromHex( + header.checksumRoot.startsWith('0x') + ? header.checksumRoot.slice(2) + : header.checksumRoot, + ); if (checksumRoot.length !== 32) { throw new Error( `Invalid checksum root length: ${checksumRoot.length}. Expected 32 bytes.`, @@ -325,7 +329,11 @@ export class EpochManager extends Logger { for (const header of headers) { if (header) { const blockNumber = DataConverter.fromDecimal128(header.height); - const checksumRoot = fromHex(header.checksumRoot.startsWith('0x') ? header.checksumRoot.slice(2) : header.checksumRoot); + const checksumRoot = fromHex( + header.checksumRoot.startsWith('0x') + ? header.checksumRoot.slice(2) + : header.checksumRoot, + ); if (checksumRoot.length !== 32) { throw new Error( `Invalid checksum root length: ${checksumRoot.length}. Expected 32 bytes.`, @@ -660,7 +668,11 @@ export class EpochManager extends Logger { ); } - const root = fromHex(blockHeader.checksumRoot.startsWith('0x') ? blockHeader.checksumRoot.slice(2) : blockHeader.checksumRoot); + const root = fromHex( + blockHeader.checksumRoot.startsWith('0x') + ? blockHeader.checksumRoot.slice(2) + : blockHeader.checksumRoot, + ); if (root.length !== 32) { throw new Error(`Invalid checksum root length: ${root.length}. Expected 32 bytes.`); } diff --git a/src/src/blockchain-indexer/processor/transaction/Transaction.ts b/src/src/blockchain-indexer/processor/transaction/Transaction.ts index 87b480a66..29617ffdc 100644 --- a/src/src/blockchain-indexer/processor/transaction/Transaction.ts +++ b/src/src/blockchain-indexer/processor/transaction/Transaction.ts @@ -1,6 +1,18 @@ import { TransactionData, VIn, VOut } from '@btc-vision/bitcoin-rpc'; import { DataConverter } from '@btc-vision/bsi-common'; -import { alloc, concat, equals, fromHex, fromUtf8, Bytes32, Network, Script, Satoshi, script, Transaction as BitcoinTransaction } from '@btc-vision/bitcoin'; +import { + alloc, + concat, + equals, + fromHex, + fromUtf8, + Bytes32, + Network, + Script, + Satoshi, + script, + Transaction as BitcoinTransaction, +} from '@btc-vision/bitcoin'; import { createBytes32, createPublicKey, createSatoshi } from '@btc-vision/ecpair'; import crypto from 'crypto'; import { Binary, Long } from 'mongodb'; @@ -78,9 +90,7 @@ export abstract class Transaction { this.txid = fromHex(rawTransactionData.txid); this.txidHex = rawTransactionData.txid; this.transactionHash = fromHex(rawTransactionData.hash); - this.raw = rawTransactionData.hex - ? fromHex(rawTransactionData.hex) - : new Uint8Array(0); + this.raw = rawTransactionData.hex ? fromHex(rawTransactionData.hex) : new Uint8Array(0); this.inActiveChain = rawTransactionData.in_active_chain || false; this.size = rawTransactionData.size; @@ -257,7 +267,10 @@ export abstract class Transaction { }); } - public static verifyChecksum(scriptData: (number | Uint8Array)[], typeChecksum: Uint8Array): boolean { + public static verifyChecksum( + scriptData: (number | Uint8Array)[], + typeChecksum: Uint8Array, + ): boolean { const checksum = this.getDataChecksum(scriptData); return equals(checksum, typeChecksum); } @@ -273,7 +286,14 @@ export abstract class Transaction { finishFlush: zlib.constants.Z_SYNC_FLUSH, maxOutputLength: OPNetConsensus.consensus.COMPRESSION.MAX_DECOMPRESSED_SIZE, }); - return { out: new Uint8Array(decompressed.buffer, decompressed.byteOffset, decompressed.byteLength), compressed: true }; + return { + out: new Uint8Array( + decompressed.buffer, + decompressed.byteOffset, + decompressed.byteLength, + ), + compressed: true, + }; } catch { throw new Error('OP_NET: Invalid compressed data.'); } @@ -606,7 +626,10 @@ export abstract class Transaction { const h1 = crypto.createHash('sha256').update(prefix).digest(); const h2 = crypto.createHash('sha256').update(prefix).digest(); - const tagHash = concat([new Uint8Array(h1.buffer, h1.byteOffset, h1.byteLength), new Uint8Array(h2.buffer, h2.byteOffset, h2.byteLength)]); // 64 bytes + const tagHash = concat([ + new Uint8Array(h1.buffer, h1.byteOffset, h1.byteLength), + new Uint8Array(h2.buffer, h2.byteOffset, h2.byteLength), + ]); // 64 bytes const result = crypto.createHash('sha256').update(tagHash).update(data).digest(); return new Uint8Array(result.buffer, result.byteOffset, result.byteLength); } @@ -678,7 +701,13 @@ export abstract class Transaction { // 4) call hashForWitnessV1 // -> If leafHash is provided, it's Tapscript path - return txObj.hashForWitnessV1(this.vInputIndex, prevOutScripts, values, hashType, createBytes32(leafHash)); + return txObj.hashForWitnessV1( + this.vInputIndex, + prevOutScripts, + values, + hashType, + createBytes32(leafHash), + ); } private strToBuffer(str: string): Uint8Array { diff --git a/src/src/blockchain-indexer/processor/transaction/contract/ContractInformation.ts b/src/src/blockchain-indexer/processor/transaction/contract/ContractInformation.ts index 19be7bf82..f35464692 100644 --- a/src/src/blockchain-indexer/processor/transaction/contract/ContractInformation.ts +++ b/src/src/blockchain-indexer/processor/transaction/contract/ContractInformation.ts @@ -35,29 +35,35 @@ export class ContractInformation { ) {} public static fromDocument(contractDocument: IContractDocument): ContractInformation { - const bytecodeBytes = contractDocument.bytecode instanceof Uint8Array - ? contractDocument.bytecode - : new Uint8Array(contractDocument.bytecode.buffer); + const bytecodeBytes = + contractDocument.bytecode instanceof Uint8Array + ? contractDocument.bytecode + : new Uint8Array(contractDocument.bytecode.buffer); - const deployerPubKeyBytes = contractDocument.deployerPubKey instanceof Uint8Array - ? contractDocument.deployerPubKey - : new Uint8Array(contractDocument.deployerPubKey.buffer); + const deployerPubKeyBytes = + contractDocument.deployerPubKey instanceof Uint8Array + ? contractDocument.deployerPubKey + : new Uint8Array(contractDocument.deployerPubKey.buffer); - const contractSeedBytes = contractDocument.contractSeed instanceof Uint8Array - ? contractDocument.contractSeed - : new Uint8Array(contractDocument.contractSeed.buffer); + const contractSeedBytes = + contractDocument.contractSeed instanceof Uint8Array + ? contractDocument.contractSeed + : new Uint8Array(contractDocument.contractSeed.buffer); - const contractSaltHashBytes = contractDocument.contractSaltHash instanceof Uint8Array - ? contractDocument.contractSaltHash - : new Uint8Array(contractDocument.contractSaltHash.buffer); + const contractSaltHashBytes = + contractDocument.contractSaltHash instanceof Uint8Array + ? contractDocument.contractSaltHash + : new Uint8Array(contractDocument.contractSaltHash.buffer); - const transactionIdBytes = contractDocument.deployedTransactionId instanceof Uint8Array - ? contractDocument.deployedTransactionId - : new Uint8Array(contractDocument.deployedTransactionId.buffer); + const transactionIdBytes = + contractDocument.deployedTransactionId instanceof Uint8Array + ? contractDocument.deployedTransactionId + : new Uint8Array(contractDocument.deployedTransactionId.buffer); - const deployedTransactionHashBytes = contractDocument.deployedTransactionHash instanceof Uint8Array - ? contractDocument.deployedTransactionHash - : new Uint8Array(contractDocument.deployedTransactionHash.buffer); + const deployedTransactionHashBytes = + contractDocument.deployedTransactionHash instanceof Uint8Array + ? contractDocument.deployedTransactionHash + : new Uint8Array(contractDocument.deployedTransactionHash.buffer); return new ContractInformation( DataConverter.fromDecimal128(contractDocument.blockHeight), diff --git a/src/src/blockchain-indexer/processor/transaction/inputs/TransactionInput.ts b/src/src/blockchain-indexer/processor/transaction/inputs/TransactionInput.ts index 2cb9369e2..8d9cfdcc4 100644 --- a/src/src/blockchain-indexer/processor/transaction/inputs/TransactionInput.ts +++ b/src/src/blockchain-indexer/processor/transaction/inputs/TransactionInput.ts @@ -68,9 +68,7 @@ export class TransactionInput implements ITransactionInput { this.scriptSignature = data.scriptSig; this.sequenceId = data.sequence; - this.transactionInWitness = data.txinwitness - ? data.txinwitness.map((w) => fromHex(w)) - : []; + this.transactionInWitness = data.txinwitness ? data.txinwitness.map((w) => fromHex(w)) : []; // for P2PK, P2WPKH, and P2PKH this.decodedPubKey = this.decodePubKey(); @@ -112,7 +110,9 @@ export class TransactionInput implements ITransactionInput { return { txId: this.originalTransactionId, outputIndex: this.outputTransactionIndex || 0, - scriptSig: this.scriptSignature?.hex ? fromHex(this.scriptSignature.hex) : new Uint8Array(0), + scriptSig: this.scriptSignature?.hex + ? fromHex(this.scriptSignature.hex) + : new Uint8Array(0), witnesses: this.transactionInWitness, flags: flags, coinbase: this.coinbase, @@ -140,7 +140,11 @@ export class TransactionInput implements ITransactionInput { const secondPart = parts[1]; // Check for P2PKH with compressed (66 hex = 33 bytes) or uncompressed (130 hex = 65 bytes) public key - if (parts.length === 2 && secondPart && (secondPart.length === 66 || secondPart.length === 130)) { + if ( + parts.length === 2 && + secondPart && + (secondPart.length === 66 || secondPart.length === 130) + ) { const pubkeyBytes = fromHex(secondPart); // Validate the public key prefix to avoid mistaking scripts for pubkeys if (this.isValidPublicKeyBytes(pubkeyBytes, pubkeyBytes.length)) { diff --git a/src/src/blockchain-indexer/processor/transaction/interfaces/OPNetHeader.ts b/src/src/blockchain-indexer/processor/transaction/interfaces/OPNetHeader.ts index 69f6a73b0..341d23e17 100644 --- a/src/src/blockchain-indexer/processor/transaction/interfaces/OPNetHeader.ts +++ b/src/src/blockchain-indexer/processor/transaction/interfaces/OPNetHeader.ts @@ -79,8 +79,6 @@ export class OPNetHeader { // Read 3-byte big-endian unsigned integer from bytes [1..3] this._flags = - (this._headerBytes[1] << 16) | - (this._headerBytes[2] << 8) | - this._headerBytes[3]; + (this._headerBytes[1] << 16) | (this._headerBytes[2] << 8) | this._headerBytes[3]; } } diff --git a/src/src/blockchain-indexer/processor/transaction/transaction-factory/TransactionFactory.ts b/src/src/blockchain-indexer/processor/transaction/transaction-factory/TransactionFactory.ts index 7c1b06d32..25d8c4508 100644 --- a/src/src/blockchain-indexer/processor/transaction/transaction-factory/TransactionFactory.ts +++ b/src/src/blockchain-indexer/processor/transaction/transaction-factory/TransactionFactory.ts @@ -24,7 +24,6 @@ export class TransactionFactory { blockHeight: bigint, network: networks.Network, allowedChallenges: ChallengeSolution, - enableVerification: boolean, addressCache?: AddressCache, ): Transaction { const parser: TransactionInformation = this.getTransactionType(data); diff --git a/src/src/blockchain-indexer/processor/transaction/transactions/DeploymentTransaction.ts b/src/src/blockchain-indexer/processor/transaction/transactions/DeploymentTransaction.ts index 5a5dd935d..f7ad23d7f 100644 --- a/src/src/blockchain-indexer/processor/transaction/transactions/DeploymentTransaction.ts +++ b/src/src/blockchain-indexer/processor/transaction/transactions/DeploymentTransaction.ts @@ -1,5 +1,12 @@ import { TransactionData, VIn, VOut } from '@btc-vision/bitcoin-rpc'; -import bitcoin, { alloc, concat, equals as bytesEquals, networks, opcodes, toXOnly } from '@btc-vision/bitcoin'; +import bitcoin, { + alloc, + concat, + equals as bytesEquals, + networks, + opcodes, + toXOnly, +} from '@btc-vision/bitcoin'; import { createPublicKey, UniversalSigner } from '@btc-vision/ecpair'; import { DeploymentTransactionDocument } from '../../../../db/interfaces/ITransactionDocument.js'; import { OPNetTransactionTypes } from '../enums/OPNetTransactionTypes.js'; @@ -254,7 +261,10 @@ export class DeploymentTransaction extends SharedInteractionParameters 0 - ? this._calldata - : undefined, + calldata: this._calldata && this._calldata.length > 0 ? this._calldata : undefined, challenge: unsafePreimage, network: this.network, priorityFee: priorityFee, @@ -471,7 +478,11 @@ export class DeploymentTransaction extends SharedInteractionParameters): Uint8Array | undefined { + public static getDataUntilBufferEnd( + scriptData: Array, + ): Uint8Array | undefined { let data: Uint8Array | undefined; // Keep reading until we see the break opcode or run out of script data. @@ -116,7 +118,10 @@ export abstract class SharedInteractionParameters< scriptData: Array, ): OPNetHeader | undefined { const header = scriptData.shift(); - if (!(header instanceof Uint8Array) || header.length !== OPNetHeader.EXPECTED_HEADER_LENGTH) { + if ( + !(header instanceof Uint8Array) || + header.length !== OPNetHeader.EXPECTED_HEADER_LENGTH + ) { return; } diff --git a/src/src/blockchain-indexer/rpc/thread/BitcoinRPCThread.ts b/src/src/blockchain-indexer/rpc/thread/BitcoinRPCThread.ts index 66ab152a4..71ce42d3d 100644 --- a/src/src/blockchain-indexer/rpc/thread/BitcoinRPCThread.ts +++ b/src/src/blockchain-indexer/rpc/thread/BitcoinRPCThread.ts @@ -154,10 +154,7 @@ export class BitcoinRPCThread extends Thread { for (let i = 0; i < value.length; i++) { const innerValue = value[i]; - const event: NetEvent = new NetEvent( - innerValue[0], - fromHex(innerValue[1]), - ); + const event: NetEvent = new NetEvent(innerValue[0], fromHex(innerValue[1])); events.push(event); } diff --git a/src/src/blockchain-indexer/sync/solver/AnyoneCanSpendDetector.ts b/src/src/blockchain-indexer/sync/solver/AnyoneCanSpendDetector.ts index 237319bab..7baecf943 100644 --- a/src/src/blockchain-indexer/sync/solver/AnyoneCanSpendDetector.ts +++ b/src/src/blockchain-indexer/sync/solver/AnyoneCanSpendDetector.ts @@ -160,7 +160,9 @@ export class AnyoneCanSpendDetector extends Logger { return undefined; } - private detectOpSuccessBare(asm: (number | Uint8Array)[] | null): AnyoneCanSpendHit | undefined { + private detectOpSuccessBare( + asm: (number | Uint8Array)[] | null, + ): AnyoneCanSpendHit | undefined { if (!asm || asm.length === 0) return; let i = 0; while (i < asm.length && asm[i] === opcodes.OP_NOP) i++; @@ -249,7 +251,9 @@ export class AnyoneCanSpendDetector extends Logger { }; } - private detectFutureWitness(asm: (number | Uint8Array)[] | null): AnyoneCanSpendHit | undefined { + private detectFutureWitness( + asm: (number | Uint8Array)[] | null, + ): AnyoneCanSpendHit | undefined { if (!asm || asm.length !== 2) return; const [vOp, prog] = asm; if (typeof vOp !== 'number' || !(prog instanceof Uint8Array)) return; diff --git a/src/src/config/BtcIndexerConfig.ts b/src/src/config/BtcIndexerConfig.ts index 4a429aade..4295e8ce2 100644 --- a/src/src/config/BtcIndexerConfig.ts +++ b/src/src/config/BtcIndexerConfig.ts @@ -1,8 +1,6 @@ import { ConfigBase, IConfig } from '@btc-vision/bsi-common'; import { APIExtendedConfigurations, - Base58Config, - Bech32Config, BitcoinConfig, BlockchainConfig, DevConfig, @@ -39,9 +37,6 @@ export class BtcIndexerConfig extends ConfigBase> { public readonly DEV: DevConfig; public readonly DEV_MODE: boolean = false; - public readonly BECH32: Bech32Config; - public readonly BASE58: Base58Config; - public readonly BLOCKCHAIN: BlockchainConfig; public readonly BITCOIN: BitcoinConfig; @@ -57,9 +52,6 @@ export class BtcIndexerConfig extends ConfigBase> { this.EPOCH = config.EPOCH; - this.BECH32 = config.BECH32; - this.BASE58 = config.BASE58; - this.BITCOIN = config.BITCOIN; this.INDEXER = config.INDEXER; diff --git a/src/src/config/BtcIndexerConfigLoader.ts b/src/src/config/BtcIndexerConfigLoader.ts index e8cfbccf4..12ada5adb 100644 --- a/src/src/config/BtcIndexerConfigLoader.ts +++ b/src/src/config/BtcIndexerConfigLoader.ts @@ -11,7 +11,7 @@ import { BitcoinNetwork } from './network/BitcoinNetwork.js'; export class BtcIndexerConfigManager extends ConfigManager> { private defaultConfig: Partial = { DOCS: { - ENABLED: true, + ENABLED: false, PORT: 7000, }, @@ -54,42 +54,43 @@ export class BtcIndexerConfigManager extends ConfigManager): void { - if (parsedConfig.HRP && typeof parsedConfig.HRP !== 'string') { - throw new Error(`Oops the property BECH32.HRP is not a string.`); - } - } - private verifyWebSocketConfig( parsedConfig: Partial, ): void { @@ -1146,70 +1134,6 @@ export class BtcIndexerConfigManager extends ConfigManager): void { - if ( - typeof parsedConfig.PUBKEY_ADDRESS !== 'string' && - parsedConfig.PUBKEY_ADDRESS !== undefined - ) { - throw new Error(`Oops the property BASE58.PUBKEY_ADDRESS is not a string.`); - } else if (parsedConfig.PUBKEY_ADDRESS) { - parsedConfig.PUBKEY_ADDRESS = Number(parsedConfig.PUBKEY_ADDRESS); - - if (isNaN(parsedConfig.PUBKEY_ADDRESS)) { - throw new Error(`Oops the property BASE58.PUBKEY_ADDRESS is not a number.`); - } - } - - if ( - typeof parsedConfig.SCRIPT_ADDRESS !== 'string' && - parsedConfig.SCRIPT_ADDRESS !== undefined - ) { - throw new Error(`Oops the property BASE58.SCRIPT_ADDRESS is not a string.`); - } else if (parsedConfig.SCRIPT_ADDRESS) { - parsedConfig.SCRIPT_ADDRESS = Number(parsedConfig.SCRIPT_ADDRESS); - - if (isNaN(parsedConfig.SCRIPT_ADDRESS)) { - throw new Error(`Oops the property BASE58.SCRIPT_ADDRESS is not a number.`); - } - } - - if (typeof parsedConfig.SECRET_KEY !== 'string' && parsedConfig.SECRET_KEY !== undefined) { - throw new Error(`Oops the property BASE58.SECRET_KEY is not a number.`); - } else if (parsedConfig.SECRET_KEY) { - parsedConfig.SECRET_KEY = Number(parsedConfig.SECRET_KEY); - - if (isNaN(parsedConfig.SECRET_KEY)) { - throw new Error(`Oops the property BASE58.SECRET_KEY is not a number.`); - } - } - - if ( - typeof parsedConfig.EXT_PUBLIC_KEY !== 'string' && - parsedConfig.EXT_PUBLIC_KEY !== undefined - ) { - throw new Error(`Oops the property BASE58.EXT_PUBLIC_KEY is not a string.`); - } else if (parsedConfig.EXT_PUBLIC_KEY) { - parsedConfig.EXT_PUBLIC_KEY = Number(parsedConfig.EXT_PUBLIC_KEY); - - if (isNaN(parsedConfig.EXT_PUBLIC_KEY)) { - throw new Error(`Oops the property BASE58.EXT_PUBLIC_KEY is not a number.`); - } - } - - if ( - typeof parsedConfig.EXT_SECRET_KEY !== 'string' && - parsedConfig.EXT_SECRET_KEY !== undefined - ) { - throw new Error(`Oops the property BASE58.EXT_SECRET_KEY is not a string.`); - } else if (parsedConfig.EXT_SECRET_KEY) { - parsedConfig.EXT_SECRET_KEY = Number(parsedConfig.EXT_SECRET_KEY); - - if (isNaN(parsedConfig.EXT_SECRET_KEY)) { - throw new Error(`Oops the property BASE58.EXT_SECRET_KEY is not a number.`); - } - } - } - private parseConfig(parsedConfig: Partial): void { const defaultConfigs = this.getDefaultConfig(); @@ -1316,16 +1240,6 @@ export class BtcIndexerConfigManager extends ConfigManager(parsedConfig.BECH32 || {}, defaultConfigs.BECH32 || {}); - - this.config.BASE58 = this.getConfigModified< - keyof IBtcIndexerConfig, - IBtcIndexerConfig['BASE58'] - >(parsedConfig.BASE58 || {}, defaultConfigs.BASE58 || {}); - this.config.BITCOIN = this.getConfigModified< keyof IBtcIndexerConfig, IBtcIndexerConfig['BITCOIN'] diff --git a/src/src/config/interfaces/IBtcIndexerConfig.ts b/src/src/config/interfaces/IBtcIndexerConfig.ts index 527be57a5..d2f3839e2 100644 --- a/src/src/config/interfaces/IBtcIndexerConfig.ts +++ b/src/src/config/interfaces/IBtcIndexerConfig.ts @@ -180,19 +180,6 @@ export interface DevConfig { readonly ENABLE_REORG_NIGHTMARE: boolean; } -export interface Bech32Config { - readonly HRP?: string; -} - -export interface Base58Config { - PUBKEY_ADDRESS?: number; - SCRIPT_ADDRESS?: number; - SECRET_KEY?: number; - - EXT_PUBLIC_KEY?: number; - EXT_SECRET_KEY?: number; -} - export interface BitcoinConfig { readonly CHAIN_ID: ChainIds; readonly NETWORK: BitcoinNetwork; @@ -234,8 +221,6 @@ export interface IBtcIndexerConfig extends IConfig { EPOCH: EpochConfigs; BITCOIN: BitcoinConfig; - BECH32: Bech32Config; - BASE58: Base58Config; INDEXER: IndexerConfig; RPC: RPCConfig; diff --git a/src/src/db/documents/interfaces/BlockHeaderAPIDocumentWithTransactions.ts b/src/src/db/documents/interfaces/BlockHeaderAPIDocumentWithTransactions.ts index 1337db539..9c96f5ac6 100644 --- a/src/src/db/documents/interfaces/BlockHeaderAPIDocumentWithTransactions.ts +++ b/src/src/db/documents/interfaces/BlockHeaderAPIDocumentWithTransactions.ts @@ -13,8 +13,10 @@ export interface EventReceiptDataForAPI { readonly data: string; } -export interface TransactionDocumentForAPI - extends Omit, 'outputs' | 'inputs' | 'id' | 'hash'> { +export interface TransactionDocumentForAPI extends Omit< + TransactionDocumentBase, + 'outputs' | 'inputs' | 'id' | 'hash' +> { readonly hash: string; readonly id: string; readonly blockNumber?: string; diff --git a/src/src/db/documents/interfaces/IContractDocument.ts b/src/src/db/documents/interfaces/IContractDocument.ts index ea3625813..82c2a7a8e 100644 --- a/src/src/db/documents/interfaces/IContractDocument.ts +++ b/src/src/db/documents/interfaces/IContractDocument.ts @@ -14,8 +14,10 @@ export interface IContractDocumentBase { readonly contractSaltHash: Binary | string; } -export interface IContractAPIDocument - extends Omit { +export interface IContractAPIDocument extends Omit< + IContractDocumentBase, + 'deployerPubKey' | 'blockHeight' +> { readonly bytecode: string; readonly deployerPubKey: string; readonly deployerAddress: string; diff --git a/src/src/db/indexes/required/IndexedMempool.ts b/src/src/db/indexes/required/IndexedMempool.ts index dd3a17d57..b6c3515a7 100644 --- a/src/src/db/indexes/required/IndexedMempool.ts +++ b/src/src/db/indexes/required/IndexedMempool.ts @@ -55,9 +55,32 @@ export class IndexedMempool extends IndexedCollection { key: { - isOPNet: 1, + transactionType: 1, }, - name: 'isOPNet_1', + name: 'transactionType_1', + }, + + { + key: { + from: 1, + }, + name: 'from_1', + sparse: true, + }, + + { + key: { + contractAddress: 1, + }, + name: 'contractAddress_1', + sparse: true, + }, + + { + key: { + firstSeen: -1, + }, + name: 'firstSeen_-1', }, ]; } diff --git a/src/src/db/interfaces/IBlockHeaderBlockDocument.ts b/src/src/db/interfaces/IBlockHeaderBlockDocument.ts index b74d669ab..1e28a2ee6 100644 --- a/src/src/db/interfaces/IBlockHeaderBlockDocument.ts +++ b/src/src/db/interfaces/IBlockHeaderBlockDocument.ts @@ -32,8 +32,10 @@ export interface BaseBlockDocument { gasUsed: bigint; } -export interface BlockHeaderDocument - extends Omit { +export interface BlockHeaderDocument extends Omit< + BaseBlockDocument, + 'ema' | 'baseGas' | 'gasUsed' +> { height: Decimal128; time: Date; medianTime: Date; @@ -42,8 +44,10 @@ export interface BlockHeaderDocument gasUsed: Long; } -export interface BlockHeaderAPIBlockDocument - extends Omit { +export interface BlockHeaderAPIBlockDocument extends Omit< + BaseBlockDocument, + 'ema' | 'baseGas' | 'gasUsed' +> { height: string; time: number; diff --git a/src/src/db/interfaces/IMempoolTransaction.ts b/src/src/db/interfaces/IMempoolTransaction.ts index deab55d23..2d6393a76 100644 --- a/src/src/db/interfaces/IMempoolTransaction.ts +++ b/src/src/db/interfaces/IMempoolTransaction.ts @@ -1,4 +1,5 @@ import { Binary, Decimal128, Long } from 'mongodb'; +import { OPNetTransactionTypes } from '../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; export interface IMempoolTransaction { id: string; @@ -9,11 +10,17 @@ export interface IMempoolTransaction { readonly previousPsbtId?: string | null; readonly blockHeight: Decimal128; - readonly theoreticalGasLimit: Long; - readonly priorityFee: Long; readonly firstSeen: Date | undefined; - readonly isOPNet: boolean; + readonly transactionType: string; + + // OPNet-specific fields (present only for OPNet transactions) + readonly theoreticalGasLimit?: Long; + readonly priorityFee?: Long; + readonly from?: string; + readonly contractAddress?: string; + readonly calldata?: string; + readonly bytecode?: string; readonly inputs: { readonly transactionId: string; @@ -28,17 +35,25 @@ export interface IMempoolTransaction { }[]; } -export interface IMempoolTransactionObj - extends Omit< - IMempoolTransaction, - 'data' | 'blockHeight' | 'outputs' | 'inputs' | 'theoreticalGasLimit' | 'priorityFee' - > { +export interface IMempoolTransactionObj { + id: string; + readonly data: Uint8Array; + readonly psbt: boolean; + readonly previousPsbtId?: string | null; + readonly blockHeight: bigint; + readonly firstSeen: Date | undefined; - isOPNet: boolean; - theoreticalGasLimit: bigint; - priorityFee: bigint; + transactionType: OPNetTransactionTypes; + + // OPNet-specific fields (optional on base, required on OPNet subtypes) + theoreticalGasLimit?: bigint; + priorityFee?: bigint; + from?: string; + contractAddress?: string; + calldata?: string; + bytecode?: string; readonly inputs: { readonly transactionId: string; @@ -52,3 +67,22 @@ export interface IMempoolTransactionObj value: Long; }[]; } + +export interface IMempoolOPNetTransactionObj extends IMempoolTransactionObj { + theoreticalGasLimit: bigint; + priorityFee: bigint; + from: string; + contractAddress: string; + calldata: string; +} + +export interface IMempoolInteractionTransactionObj extends IMempoolOPNetTransactionObj {} + +export interface IMempoolDeploymentTransactionObj extends IMempoolOPNetTransactionObj { + bytecode: string; +} + +export type AnyMempoolTransactionObj = + | IMempoolTransactionObj + | IMempoolInteractionTransactionObj + | IMempoolDeploymentTransactionObj; diff --git a/src/src/db/interfaces/ITransactionDocument.ts b/src/src/db/interfaces/ITransactionDocument.ts index e2e6d105c..3731c2140 100644 --- a/src/src/db/interfaces/ITransactionDocument.ts +++ b/src/src/db/interfaces/ITransactionDocument.ts @@ -28,19 +28,23 @@ export interface TransactionDocumentBasic { readonly OPNetType: T; } -export interface ITransactionDocumentBasic - extends TransactionDocumentBasic { +export interface ITransactionDocumentBasic< + T extends OPNetTransactionTypes, +> extends TransactionDocumentBasic { readonly blockHeight: Decimal128; } -export interface TransactionDocumentBase - extends TransactionDocumentBasic { +export interface TransactionDocumentBase< + T extends OPNetTransactionTypes, +> extends TransactionDocumentBasic { readonly burnedBitcoin: Decimal128 | string; readonly revert: Binary | undefined | string; } -export interface TransactionDocument - extends Omit, 'inputs' | 'outputs'> { +export interface TransactionDocument extends Omit< + TransactionDocumentBase, + 'inputs' | 'outputs' +> { readonly blockHeight: Decimal128; readonly burnedBitcoin: Decimal128; readonly reward: Long; @@ -90,8 +94,7 @@ interface InteractionBase { } export interface DeploymentTransactionDocument - extends ExtendedBaseInfo, - InteractionBase { + extends ExtendedBaseInfo, InteractionBase { readonly preimage: Binary; readonly calldata: Binary; } @@ -103,8 +106,7 @@ export interface NetEventDocument { } export interface InteractionTransactionDocument - extends ExtendedBaseInfo, - InteractionBase { + extends ExtendedBaseInfo, InteractionBase { readonly calldata: Binary; readonly preimage: Binary; readonly senderPubKeyHash: Binary; diff --git a/src/src/db/repositories/BlockchainInfoRepository.ts b/src/src/db/repositories/BlockchainInfoRepository.ts index 0c9d4099e..3e7b50251 100644 --- a/src/src/db/repositories/BlockchainInfoRepository.ts +++ b/src/src/db/repositories/BlockchainInfoRepository.ts @@ -18,8 +18,7 @@ type BlockChangeStream = | ChangeStream<{ inProgressBlock: number }, BlockChangeStreamDocument> | undefined; -interface UpdatedChangeStreamDocument - extends ChangeStreamUpdateDocument { +interface UpdatedChangeStreamDocument extends ChangeStreamUpdateDocument { readonly wallTime?: Date; } diff --git a/src/src/db/repositories/ContractRepository.ts b/src/src/db/repositories/ContractRepository.ts index c463f52c3..1e943634b 100644 --- a/src/src/db/repositories/ContractRepository.ts +++ b/src/src/db/repositories/ContractRepository.ts @@ -100,7 +100,11 @@ export class ContractRepository extends BaseRepository { return Address.fromString(contractAddress); } else { const contract = await this.getContractFromTweakedHybridPubKey( - Binary.createFromHexString(contractAddress.startsWith('0x') ? contractAddress.slice(2) : contractAddress), + Binary.createFromHexString( + contractAddress.startsWith('0x') + ? contractAddress.slice(2) + : contractAddress, + ), height, currentSession, ); @@ -160,7 +164,9 @@ export class ContractRepository extends BaseRepository { height?: bigint, currentSession?: ClientSession, ): Promise { - const key = Binary.createFromHexString(contractPublicKey.startsWith('0x') ? contractPublicKey.slice(2) : contractPublicKey); + const key = Binary.createFromHexString( + contractPublicKey.startsWith('0x') ? contractPublicKey.slice(2) : contractPublicKey, + ); if ((key.buffer[0] === 0x06 || key.buffer[0] === 0x07) && key.buffer.length === 65) { return await this.getContractFromTweakedHybridPubKey(key, height, currentSession); } diff --git a/src/src/db/repositories/MempoolRepository.ts b/src/src/db/repositories/MempoolRepository.ts index 9b9ff3470..c13bb0365 100644 --- a/src/src/db/repositories/MempoolRepository.ts +++ b/src/src/db/repositories/MempoolRepository.ts @@ -2,6 +2,7 @@ import { BaseRepository, DataConverter } from '@btc-vision/bsi-common'; import { AggregateOptions, Binary, Collection, Db, Document, Filter, Long } from 'mongodb'; import { OPNetCollections } from '../indexes/required/IndexedCollection.js'; import { IMempoolTransaction, IMempoolTransactionObj } from '../interfaces/IMempoolTransaction.js'; +import { OPNetTransactionTypes } from '../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; import { Config } from '../../config/Config.js'; import { MempoolTransactionAggregation, @@ -54,7 +55,13 @@ export class MempoolRepository extends BaseRepository { _id: null, count: { $sum: 1 }, opnetCount: { - $sum: { $cond: [{ $eq: ['$isOPNet', true] }, 1, 0] }, + $sum: { + $cond: [ + { $ne: ['$transactionType', OPNetTransactionTypes.Generic] }, + 1, + 0, + ], + }, }, size: { $sum: { $bsonSize: '$$ROOT' } }, }, @@ -665,12 +672,23 @@ export class MempoolRepository extends BaseRepository { private convertToDb(data: IMempoolTransactionObj): IMempoolTransaction { return { - ...data, + id: data.id, data: new Binary(data.data), + psbt: data.psbt, + previousPsbtId: data.previousPsbtId, blockHeight: DataConverter.toDecimal128(data.blockHeight), - theoreticalGasLimit: Long.fromBigInt(data.theoreticalGasLimit), - priorityFee: Long.fromBigInt(data.priorityFee), - isOPNet: data.isOPNet || false, + firstSeen: data.firstSeen, + transactionType: data.transactionType, + theoreticalGasLimit: + data.theoreticalGasLimit !== undefined + ? Long.fromBigInt(data.theoreticalGasLimit) + : undefined, + priorityFee: + data.priorityFee !== undefined ? Long.fromBigInt(data.priorityFee) : undefined, + from: data.from, + contractAddress: data.contractAddress, + calldata: data.calldata, + bytecode: data.bytecode, inputs: data.inputs.map((input) => { return { transactionId: input.transactionId, @@ -690,14 +708,28 @@ export class MempoolRepository extends BaseRepository { private convertToObj(data: IMempoolTransaction): IMempoolTransactionObj { return { - ...data, + id: data.id, data: new Uint8Array(data.data.buffer), + psbt: data.psbt, + previousPsbtId: data.previousPsbtId, blockHeight: DataConverter.fromDecimal128(data.blockHeight), - theoreticalGasLimit: Long.isLong(data.theoreticalGasLimit) - ? data.theoreticalGasLimit.toBigInt() - : BigInt(`${data.theoreticalGasLimit}`), - isOPNet: data.isOPNet || false, - priorityFee: Long.isLong(data.priorityFee) ? data.priorityFee.toBigInt() : BigInt(0), + firstSeen: data.firstSeen, + transactionType: (data.transactionType || + OPNetTransactionTypes.Generic) as OPNetTransactionTypes, + theoreticalGasLimit: data.theoreticalGasLimit + ? Long.isLong(data.theoreticalGasLimit) + ? data.theoreticalGasLimit.toBigInt() + : BigInt(`${data.theoreticalGasLimit}`) + : undefined, + priorityFee: data.priorityFee + ? Long.isLong(data.priorityFee) + ? data.priorityFee.toBigInt() + : BigInt(0) + : undefined, + from: data.from, + contractAddress: data.contractAddress, + calldata: data.calldata, + bytecode: data.bytecode, inputs: data.inputs.map((input) => { return { transactionId: input.transactionId, diff --git a/src/src/db/repositories/TransactionRepository.ts b/src/src/db/repositories/TransactionRepository.ts index 864d9334b..bc3261257 100644 --- a/src/src/db/repositories/TransactionRepository.ts +++ b/src/src/db/repositories/TransactionRepository.ts @@ -1,4 +1,9 @@ -import { BaseRepository, DataAccessError, DataAccessErrorType, DataConverter, } from '@btc-vision/bsi-common'; +import { + BaseRepository, + DataAccessError, + DataAccessErrorType, + DataConverter, +} from '@btc-vision/bsi-common'; import { AnyBulkWriteOperation, Binary, diff --git a/src/src/plugins/api/PluginBlockchainAPI.ts b/src/src/plugins/api/PluginBlockchainAPI.ts index c704c2419..c83d33b61 100644 --- a/src/src/plugins/api/PluginBlockchainAPI.ts +++ b/src/src/plugins/api/PluginBlockchainAPI.ts @@ -507,7 +507,8 @@ export class PluginBlockchainAPI implements IPluginBlockchainAPI { success: revertBytes.length === 0, gasUsed: gasUsed ?? 0n, events: [], - revertReason: revertBytes.length > 0 ? new TextDecoder().decode(revertBytes) : undefined, + revertReason: + revertBytes.length > 0 ? new TextDecoder().decode(revertBytes) : undefined, }; } diff --git a/src/src/plugins/loader/PluginLoader.ts b/src/src/plugins/loader/PluginLoader.ts index 8ea0aed63..3f44c6681 100644 --- a/src/src/plugins/loader/PluginLoader.ts +++ b/src/src/plugins/loader/PluginLoader.ts @@ -214,7 +214,9 @@ export class PluginLoader extends Logger { filePath, ); } - const rawMetadata = new TextDecoder().decode(buffer.subarray(offset, offset + metadataLength)); + const rawMetadata = new TextDecoder().decode( + buffer.subarray(offset, offset + metadataLength), + ); offset += metadataLength; let metadata: IPluginMetadata; @@ -430,7 +432,11 @@ export class PluginLoader extends Logger { /** * Compute SHA-256 checksum of metadata + bytecode + proto */ - private computeChecksum(rawMetadata: string, bytecode: Uint8Array, proto?: Uint8Array): Uint8Array { + private computeChecksum( + rawMetadata: string, + bytecode: Uint8Array, + proto?: Uint8Array, + ): Uint8Array { const hash = crypto.createHash('sha256'); hash.update(rawMetadata); hash.update(bytecode); diff --git a/src/src/poc/configurations/OPNetConsensus.ts b/src/src/poc/configurations/OPNetConsensus.ts index 96ff17699..3125c5f0b 100644 --- a/src/src/poc/configurations/OPNetConsensus.ts +++ b/src/src/poc/configurations/OPNetConsensus.ts @@ -1,4 +1,8 @@ -import { IOPNetConsensus, IOPNetConsensusObj, OPNetEnabledConfigs, } from './types/IOPNetConsensus.js'; +import { + IOPNetConsensus, + IOPNetConsensusObj, + OPNetEnabledConfigs, +} from './types/IOPNetConsensus.js'; import { Consensus } from './consensus/Consensus.js'; import { RoswellConsensus } from './consensus/RoswellConsensus.js'; import { Logger } from '@btc-vision/bsi-common'; diff --git a/src/src/poc/configurations/manager/TrustedAuthority.ts b/src/src/poc/configurations/manager/TrustedAuthority.ts index ae5477bcc..483efeb7d 100644 --- a/src/src/poc/configurations/manager/TrustedAuthority.ts +++ b/src/src/poc/configurations/manager/TrustedAuthority.ts @@ -159,8 +159,16 @@ export class TrustedAuthority extends Logger { opnet: fromBase64(key.opnet), signature: fromBase64(key.signature), wallet: new Address( - fromHex(key.mldsaPublicKey.startsWith('0x') ? key.mldsaPublicKey.slice(2) : key.mldsaPublicKey), - fromHex(key.walletPubKey.startsWith('0x') ? key.walletPubKey.slice(2) : key.walletPubKey), + fromHex( + key.mldsaPublicKey.startsWith('0x') + ? key.mldsaPublicKey.slice(2) + : key.mldsaPublicKey, + ), + fromHex( + key.walletPubKey.startsWith('0x') + ? key.walletPubKey.slice(2) + : key.walletPubKey, + ), ), }; }) diff --git a/src/src/poc/epoch/EpochValidator.ts b/src/src/poc/epoch/EpochValidator.ts index e4c62f5f5..89db7022b 100644 --- a/src/src/poc/epoch/EpochValidator.ts +++ b/src/src/poc/epoch/EpochValidator.ts @@ -2,7 +2,10 @@ import { DataConverter, Logger } from '@btc-vision/bsi-common'; import { equals, toHex } from '@btc-vision/bitcoin'; import { Binary } from 'mongodb'; import crypto from 'crypto'; -import { ITargetEpochDocument, PendingTargetEpoch, } from '../../db/documents/interfaces/ITargetEpochDocument.js'; +import { + ITargetEpochDocument, + PendingTargetEpoch, +} from '../../db/documents/interfaces/ITargetEpochDocument.js'; import { VMStorage } from '../../vm/storage/VMStorage.js'; import { OPNetConsensus } from '../configurations/OPNetConsensus.js'; import { SHA1 } from '../../utils/SHA1.js'; diff --git a/src/src/poc/mempool/bitcoin-mempool/MempoolManager.ts b/src/src/poc/mempool/bitcoin-mempool/MempoolManager.ts index d6e19cc4a..33d7ccd78 100644 --- a/src/src/poc/mempool/bitcoin-mempool/MempoolManager.ts +++ b/src/src/poc/mempool/bitcoin-mempool/MempoolManager.ts @@ -23,6 +23,7 @@ import { BitcoinRPCThreadMessageType } from '../../../blockchain-indexer/rpc/thr import { TransactionVerifierManager } from '../transaction/TransactionVerifierManager.js'; import { fromHex, Network } from '@btc-vision/bitcoin'; import { NetworkConverter } from '../../../config/network/NetworkConverter.js'; +import { OPNetTransactionTypes } from '../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; import { getMongodbMajorVersion } from '../../../vm/storage/databases/MongoUtils.js'; export class MempoolManager extends Logger { @@ -217,13 +218,11 @@ export class MempoolManager extends Logger { id: txData.txid, psbt: false, data: data, - isOPNet: false, + transactionType: OPNetTransactionTypes.Generic, firstSeen: new Date(), blockHeight: this.currentBlockHeight, inputs: [], outputs: [], - theoreticalGasLimit: 0n, - priorityFee: 0n, }; parseAndStoreInputOutputs(data, resp); diff --git a/src/src/poc/mempool/manager/Mempool.ts b/src/src/poc/mempool/manager/Mempool.ts index 78d73f147..f30233162 100644 --- a/src/src/poc/mempool/manager/Mempool.ts +++ b/src/src/poc/mempool/manager/Mempool.ts @@ -18,8 +18,9 @@ import { BitcoinRPC, FeeEstimation, SmartFeeEstimation } from '@btc-vision/bitco import { Config } from '../../../config/Config.js'; import { MempoolRepository } from '../../../db/repositories/MempoolRepository.js'; import { NetworkConverter } from '../../../config/network/NetworkConverter.js'; -import { concat, Network, toBase64, toHex } from '@btc-vision/bitcoin'; +import { Network, toHex } from '@btc-vision/bitcoin'; import { IMempoolTransactionObj } from '../../../db/interfaces/IMempoolTransaction.js'; +import { OPNetTransactionTypes } from '../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; import { OPNetConsensus } from '../../configurations/OPNetConsensus.js'; import { BlockchainInfoRepository } from '../../../db/repositories/BlockchainInfoRepository.js'; import { TransactionSizeValidator } from '../data-validator/TransactionSizeValidator.js'; @@ -348,9 +349,7 @@ export class Mempool extends Logger { const transaction: IMempoolTransactionObj = { id: id, psbt: psbt, - theoreticalGasLimit: 0n, - isOPNet: false, - priorityFee: 0n, + transactionType: OPNetTransactionTypes.Generic, data: raw, firstSeen: new Date(), blockHeight: OPNetConsensus.getBlockHeight(), @@ -410,12 +409,14 @@ export class Mempool extends Logger { await this.cleanupEvictedTransactions(transaction); } - return ( - broadcast || { - success: false, - result: 'Could not broadcast transaction to the network.', - } - ); + const response: BroadcastResponse = broadcast || { + success: false, + result: 'Could not broadcast transaction to the network.', + }; + + response.transactionType = transaction.transactionType; + + return response; } private async cleanupEvictedTransactions(transaction: IMempoolTransactionObj): Promise { diff --git a/src/src/poc/mempool/transaction/TransactionVerifierManager.ts b/src/src/poc/mempool/transaction/TransactionVerifierManager.ts index 0d5916aa6..87e36d27a 100644 --- a/src/src/poc/mempool/transaction/TransactionVerifierManager.ts +++ b/src/src/poc/mempool/transaction/TransactionVerifierManager.ts @@ -1,5 +1,11 @@ import { TransactionTypes } from './TransactionTypes.js'; -import { Network, networks, Psbt, toBase64, Transaction as BitcoinTransaction } from '@btc-vision/bitcoin'; +import { + Network, + networks, + Psbt, + toBase64, + Transaction as BitcoinTransaction, +} from '@btc-vision/bitcoin'; import { ConfigurableDBManager, Logger } from '@btc-vision/bsi-common'; import { TransactionVerifier } from '../verificator/TransactionVerifier.js'; import { Consensus } from '../../configurations/consensus/Consensus.js'; diff --git a/src/src/poc/mempool/verificator/bitcoin/v2/BitcoinTransactionVerificatorV2.ts b/src/src/poc/mempool/verificator/bitcoin/v2/BitcoinTransactionVerificatorV2.ts index e1ecc380f..c7f6ff860 100644 --- a/src/src/poc/mempool/verificator/bitcoin/v2/BitcoinTransactionVerificatorV2.ts +++ b/src/src/poc/mempool/verificator/bitcoin/v2/BitcoinTransactionVerificatorV2.ts @@ -11,10 +11,13 @@ import { BitcoinRPC } from '@btc-vision/bitcoin-rpc'; import { scriptToAddress } from '../../../../../utils/AddressDecoder.js'; import BigNumber from 'bignumber.js'; import { OPNetConsensus } from '../../../../configurations/OPNetConsensus.js'; -import { OPNetTransactionTypes } from '../../../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; import { ChallengeSolution } from '../../../../../blockchain-indexer/processor/interfaces/TransactionPreimage.js'; import { AddressMap } from '@btc-vision/transaction'; import { EpochRepository } from '../../../../../db/repositories/EpochRepository.js'; +import { OPNetTransactionTypes } from '../../../../../blockchain-indexer/processor/transaction/enums/OPNetTransactionTypes.js'; +import { Transaction as OPNetDecodedTransaction } from '../../../../../blockchain-indexer/processor/transaction/Transaction.js'; +import { InteractionTransaction } from '../../../../../blockchain-indexer/processor/transaction/transactions/InteractionTransaction.js'; +import { DeploymentTransaction } from '../../../../../blockchain-indexer/processor/transaction/transactions/DeploymentTransaction.js'; const EMPTY_BLOCK_HASH = toHex(new Uint8Array(32)); @@ -78,7 +81,6 @@ export class BitcoinTransactionVerificatorV2 extends TransactionVerifier, + ): void { + transaction.transactionType = decoded.transactionType; + transaction.theoreticalGasLimit = decoded.gasSatFee; + transaction.priorityFee = decoded.priorityFee; + + try { + transaction.from = decoded.from.p2tr(this.network); + } catch { + // from may not be set for all transaction types + } + } + + private insertInteractionProperty( + transaction: IMempoolTransactionObj, + decoded: InteractionTransaction, + ): void { + try { + transaction.contractAddress = decoded.contractAddress; + } catch { + // contractAddress may not be set + } + + transaction.calldata = toHex(decoded.calldata); + } + + private insertDeploymentProperty( + transaction: IMempoolTransactionObj, + decoded: DeploymentTransaction, + ): void { + try { + transaction.contractAddress = decoded.contractAddress; + } catch { + // contractAddress may not be set + } + + transaction.calldata = toHex(decoded.calldata); + + if (decoded.bytecode) { + transaction.bytecode = toHex(decoded.bytecode); + } + } + private toRawTransactionData(data: Transaction): TransactionData { const outputs: VOut[] = []; for (let i = 0; i < data.outs.length; i++) { diff --git a/src/src/poc/networking/encryptem/EncryptemClient.ts b/src/src/poc/networking/encryptem/EncryptemClient.ts index 9d907d579..f92bb9d45 100644 --- a/src/src/poc/networking/encryptem/EncryptemClient.ts +++ b/src/src/poc/networking/encryptem/EncryptemClient.ts @@ -277,7 +277,11 @@ export class EncryptemClient extends Logger { return { publicKey: Buffer.from(publicKey.buffer, publicKey.byteOffset, publicKey.byteLength), - privateKey: Buffer.from(privateKey.buffer, privateKey.byteOffset, privateKey.byteLength), + privateKey: Buffer.from( + privateKey.buffer, + privateKey.byteOffset, + privateKey.byteLength, + ), }; } } diff --git a/src/src/poc/networking/encryptem/EncryptemServer.ts b/src/src/poc/networking/encryptem/EncryptemServer.ts index 2e94d7b79..72a585ad5 100644 --- a/src/src/poc/networking/encryptem/EncryptemServer.ts +++ b/src/src/poc/networking/encryptem/EncryptemServer.ts @@ -74,7 +74,11 @@ export class EncryptemServer extends Logger { throw new Error('Encryption failed. Client public key or server private key is null.'); } - return this.#encrypt(Buffer.from(msg.buffer, msg.byteOffset, msg.byteLength), this.#clientPublicKey, this.#serverPrivateKey); + return this.#encrypt( + Buffer.from(msg.buffer, msg.byteOffset, msg.byteLength), + this.#clientPublicKey, + this.#serverPrivateKey, + ); } public verifyAuth(out: Uint8Array, input: Uint8Array): boolean { @@ -96,11 +100,23 @@ export class EncryptemServer extends Logger { } const authSlice = msg.slice(0, this.sodium.crypto_auth_BYTES); - const auth: Buffer = Buffer.from(authSlice.buffer, authSlice.byteOffset, authSlice.byteLength); + const auth: Buffer = Buffer.from( + authSlice.buffer, + authSlice.byteOffset, + authSlice.byteLength, + ); const sigSlice = msg.slice(auth.length, auth.length + 64); - const signature: Buffer = Buffer.from(sigSlice.buffer, sigSlice.byteOffset, sigSlice.byteLength); + const signature: Buffer = Buffer.from( + sigSlice.buffer, + sigSlice.byteOffset, + sigSlice.byteLength, + ); const dataSlice = msg.slice(auth.length + 64, msg.length); - const data: Buffer = Buffer.from(dataSlice.buffer, dataSlice.byteOffset, dataSlice.byteLength); + const data: Buffer = Buffer.from( + dataSlice.buffer, + dataSlice.byteOffset, + dataSlice.byteLength, + ); if (!this.verifyAuth(auth, signature)) { throw new Error('[Server] Bad AHEAD authentication.'); diff --git a/src/src/poc/networking/p2p/BlockWitnessManager.ts b/src/src/poc/networking/p2p/BlockWitnessManager.ts index 40f957d04..ec6535ba2 100644 --- a/src/src/poc/networking/p2p/BlockWitnessManager.ts +++ b/src/src/poc/networking/p2p/BlockWitnessManager.ts @@ -671,8 +671,14 @@ export class BlockWitnessManager extends Logger { const generatedChecksum = concat([ fromHex(data.blockHash), fromHex(data.previousBlockHash || ''), // Will generate empty buffer if genesis block - fromHex(data.checksumHash.startsWith('0x') ? data.checksumHash.slice(2) : data.checksumHash), - fromHex(data.previousBlockChecksum.startsWith('0x') ? data.previousBlockChecksum.slice(2) : data.previousBlockChecksum), + fromHex( + data.checksumHash.startsWith('0x') ? data.checksumHash.slice(2) : data.checksumHash, + ), + fromHex( + data.previousBlockChecksum.startsWith('0x') + ? data.previousBlockChecksum.slice(2) + : data.previousBlockChecksum, + ), ]); return this.identity.hash(generatedChecksum); diff --git a/src/src/poc/networking/server/managers/AuthenticationManager.ts b/src/src/poc/networking/server/managers/AuthenticationManager.ts index 1ceccad1c..b614536c5 100644 --- a/src/src/poc/networking/server/managers/AuthenticationManager.ts +++ b/src/src/poc/networking/server/managers/AuthenticationManager.ts @@ -490,7 +490,9 @@ export abstract class AuthenticationManager extends SharedAuthenticationManager await this.verifyNetwork(); } - this.encryptem.setClientSignaturePublicKey(new Uint8Array(unpackedAuthData.clientAuthCipher)); + this.encryptem.setClientSignaturePublicKey( + new Uint8Array(unpackedAuthData.clientAuthCipher), + ); await this.onPassedVersionCheck(); } } diff --git a/src/src/ssh/client/SSHClient.ts b/src/src/ssh/client/SSHClient.ts index ecf4491a9..5572e819e 100644 --- a/src/src/ssh/client/SSHClient.ts +++ b/src/src/ssh/client/SSHClient.ts @@ -215,7 +215,9 @@ export class SSHClient extends Logger { return; } - const allowedKey = matchingKeys.find((k) => this.verifySafeBuffer(key.data, k.getPublicSSH())); + const allowedKey = matchingKeys.find((k) => + this.verifySafeBuffer(key.data, k.getPublicSSH()), + ); if (!allowedKey) { return this.rejectAuth(ctx); } diff --git a/src/src/threading/interfaces/thread-messages/messages/LinkThreadMessage.ts b/src/src/threading/interfaces/thread-messages/messages/LinkThreadMessage.ts index 0dfbcebfb..a89047f50 100644 --- a/src/src/threading/interfaces/thread-messages/messages/LinkThreadMessage.ts +++ b/src/src/threading/interfaces/thread-messages/messages/LinkThreadMessage.ts @@ -23,8 +23,9 @@ export interface LinkData { readonly port: MessagePort; } -export interface LinkThreadMessage - extends ThreadMessageBase { +export interface LinkThreadMessage< + T extends LinkType, +> extends ThreadMessageBase { readonly type: MessageType.LINK_THREAD; readonly data: LinkData; diff --git a/src/src/threading/interfaces/thread-messages/messages/LinkThreadRequestMessage.ts b/src/src/threading/interfaces/thread-messages/messages/LinkThreadRequestMessage.ts index b8456df19..b102ec06a 100644 --- a/src/src/threading/interfaces/thread-messages/messages/LinkThreadRequestMessage.ts +++ b/src/src/threading/interfaces/thread-messages/messages/LinkThreadRequestMessage.ts @@ -12,8 +12,7 @@ export interface LinkThreadRequestData { mainTargetThreadId: number | null; } -export interface LinkThreadRequestMessage - extends ThreadMessageBase { +export interface LinkThreadRequestMessage extends ThreadMessageBase { readonly type: MessageType.LINK_THREAD_REQUEST; readonly data: LinkThreadRequestData; diff --git a/src/src/threading/interfaces/thread-messages/messages/api/BroadcastRequest.ts b/src/src/threading/interfaces/thread-messages/messages/api/BroadcastRequest.ts index 5c030a826..ffb0a3a90 100644 --- a/src/src/threading/interfaces/thread-messages/messages/api/BroadcastRequest.ts +++ b/src/src/threading/interfaces/thread-messages/messages/api/BroadcastRequest.ts @@ -5,8 +5,7 @@ import { BroadcastTransactionResult } from '../../../../../api/json-rpc/types/in export type BroadcastResponse = ThreadData & BroadcastTransactionResult; -export interface BroadcastRequest - extends RPCMessageData { +export interface BroadcastRequest extends RPCMessageData { readonly rpcMethod: BitcoinRPCThreadMessageType.BROADCAST_TRANSACTION_BITCOIN_CORE; readonly data: { readonly rawTransaction: string; diff --git a/src/src/threading/interfaces/thread-messages/messages/api/BroadcastTransactionOPNet.ts b/src/src/threading/interfaces/thread-messages/messages/api/BroadcastTransactionOPNet.ts index 32c5ef540..f9343bab9 100644 --- a/src/src/threading/interfaces/thread-messages/messages/api/BroadcastTransactionOPNet.ts +++ b/src/src/threading/interfaces/thread-messages/messages/api/BroadcastTransactionOPNet.ts @@ -12,8 +12,7 @@ export type OPNetBroadcastResponse = ThreadData & { readonly peers: number; }; -export interface BroadcastOPNetRequest - extends RPCMessageData { +export interface BroadcastOPNetRequest extends RPCMessageData { readonly rpcMethod: BitcoinRPCThreadMessageType.BROADCAST_TRANSACTION_OPNET; readonly data: OPNetBroadcastData; } diff --git a/src/src/threading/interfaces/thread-messages/messages/api/FeeRequest.ts b/src/src/threading/interfaces/thread-messages/messages/api/FeeRequest.ts index 8d26e56f8..bbf151778 100644 --- a/src/src/threading/interfaces/thread-messages/messages/api/FeeRequest.ts +++ b/src/src/threading/interfaces/thread-messages/messages/api/FeeRequest.ts @@ -17,7 +17,6 @@ export type FeeMessageResponse = ThreadData & { readonly bitcoinFees: BitcoinFees; }; -export interface FeeRequestMessageData - extends RPCMessageData { +export interface FeeRequestMessageData extends RPCMessageData { readonly rpcMethod: BitcoinRPCThreadMessageType.GET_MEMPOOL_FEES; } diff --git a/src/src/threading/interfaces/thread-messages/messages/api/RPCMessage.ts b/src/src/threading/interfaces/thread-messages/messages/api/RPCMessage.ts index e9c5c36ad..1e772063b 100644 --- a/src/src/threading/interfaces/thread-messages/messages/api/RPCMessage.ts +++ b/src/src/threading/interfaces/thread-messages/messages/api/RPCMessage.ts @@ -9,8 +9,9 @@ export interface RPCMessageData { readonly data?: ThreadData | PromiseLike; } -export interface RPCMessage - extends ThreadMessageBase { +export interface RPCMessage< + T extends BitcoinRPCThreadMessageType, +> extends ThreadMessageBase { readonly type: MessageType.RPC_METHOD; readonly data: RPCMessageData; diff --git a/src/src/threading/interfaces/thread-messages/messages/api/ValidateBlockHeaders.ts b/src/src/threading/interfaces/thread-messages/messages/api/ValidateBlockHeaders.ts index 8b20e2fdd..bfe053143 100644 --- a/src/src/threading/interfaces/thread-messages/messages/api/ValidateBlockHeaders.ts +++ b/src/src/threading/interfaces/thread-messages/messages/api/ValidateBlockHeaders.ts @@ -13,8 +13,7 @@ export interface ValidatedBlockHeader { readonly storedBlockHeader: BlockHeaderDocument | null; } -export interface ValidateBlockHeaders - extends RPCMessageData { +export interface ValidateBlockHeaders extends RPCMessageData { readonly rpcMethod: BitcoinRPCThreadMessageType.VALIDATE_BLOCK_HEADERS; readonly data: BlockDataAtHeightData; } diff --git a/src/src/threading/interfaces/thread-messages/messages/indexer/CurrentIndexerBlock.ts b/src/src/threading/interfaces/thread-messages/messages/indexer/CurrentIndexerBlock.ts index e9e926e59..31d5afdd2 100644 --- a/src/src/threading/interfaces/thread-messages/messages/indexer/CurrentIndexerBlock.ts +++ b/src/src/threading/interfaces/thread-messages/messages/indexer/CurrentIndexerBlock.ts @@ -5,8 +5,7 @@ export interface CurrentIndexerBlockResponseData { readonly blockNumber: bigint; } -export interface BlockProcessedMessage - extends ThreadMessageBase { +export interface BlockProcessedMessage extends ThreadMessageBase { readonly type: MessageType.CURRENT_INDEXER_BLOCK; readonly data: object; diff --git a/src/src/utils/AddressDecoder.ts b/src/src/utils/AddressDecoder.ts index 9945c277f..2848fef57 100644 --- a/src/src/utils/AddressDecoder.ts +++ b/src/src/utils/AddressDecoder.ts @@ -42,11 +42,17 @@ export function scriptToAddress(output: Uint8Array, network: Network): ScriptAdd } try { - return { address: payments.p2pkh({ output: outputScript, network }).address, type: 'pubkeyhash' }; + return { + address: payments.p2pkh({ output: outputScript, network }).address, + type: 'pubkeyhash', + }; } catch {} try { - return { address: payments.p2sh({ output: outputScript, network }).address, type: 'scripthash' }; + return { + address: payments.p2sh({ output: outputScript, network }).address, + type: 'scripthash', + }; } catch {} if ((output.length === 35 || output.length === 67) && output.at(-1) === opcodes.OP_CHECKSIG) { @@ -68,7 +74,10 @@ export function scriptToAddress(output: Uint8Array, network: Network): ScriptAdd } catch {} try { - return { address: payments.p2tr({ output: outputScript, network }).address, type: 'witness_v1_taproot' }; + return { + address: payments.p2tr({ output: outputScript, network }).address, + type: 'witness_v1_taproot', + }; } catch {} try { diff --git a/src/src/utils/RPCSubWorker.ts b/src/src/utils/RPCSubWorker.ts index 9c6878ce4..16771dfd8 100644 --- a/src/src/utils/RPCSubWorker.ts +++ b/src/src/utils/RPCSubWorker.ts @@ -179,9 +179,7 @@ class RPCManager extends Logger { for (const [key, value] of storage) { const innerArray: string[] = []; for (const innerKey of value.keys()) { - innerArray.push( - toBase64(BufferHelper.pointerToUint8Array(innerKey)), - ); + innerArray.push(toBase64(BufferHelper.pointerToUint8Array(innerKey))); } array[key.toHex()] = innerArray; @@ -262,9 +260,7 @@ class RPCManager extends Logger { txId: fromBase64(input.txId), outputIndex: input.outputIndex, scriptSig: fromBase64(input.scriptSig), - witnesses: input.witnesses - ? input.witnesses.map((w) => fromBase64(w)) - : [], + witnesses: input.witnesses ? input.witnesses.map((w) => fromBase64(w)) : [], coinbase: input.coinbase ? fromBase64(input.coinbase) : undefined, flags: input.flags || 0, }; diff --git a/src/src/utils/TransactionMempoolUtils.ts b/src/src/utils/TransactionMempoolUtils.ts index 9fc17b9d4..de0bee4af 100644 --- a/src/src/utils/TransactionMempoolUtils.ts +++ b/src/src/utils/TransactionMempoolUtils.ts @@ -23,7 +23,10 @@ export function getOutputAddressForScript(script: Uint8Array): string | null { } } -export function parseAndStoreInputOutputs(data: Uint8Array, transaction: IMempoolTransactionObj): void { +export function parseAndStoreInputOutputs( + data: Uint8Array, + transaction: IMempoolTransactionObj, +): void { try { const decoded = Transaction.fromBuffer(data); diff --git a/src/src/vm/BlockHeaderValidator.ts b/src/src/vm/BlockHeaderValidator.ts index 56be65510..7b6ceb8c4 100644 --- a/src/src/vm/BlockHeaderValidator.ts +++ b/src/src/vm/BlockHeaderValidator.ts @@ -89,7 +89,9 @@ export class BlockHeaderValidator extends Logger { const blockHash: string | undefined = blockHeader.hash; const blockMerkelRoot: string | undefined = blockHeader.merkleRoot; const checksumRoot: Uint8Array | undefined = fromHex( - blockHeader.checksumRoot.startsWith('0x') ? blockHeader.checksumRoot.slice(2) : blockHeader.checksumRoot, + blockHeader.checksumRoot.startsWith('0x') + ? blockHeader.checksumRoot.slice(2) + : blockHeader.checksumRoot, ); const proofs: BlockHeaderChecksumProof | undefined = blockHeader.checksumProofs; diff --git a/src/src/vm/VMManager.ts b/src/src/vm/VMManager.ts index f1bb48e0d..1ac067f08 100644 --- a/src/src/vm/VMManager.ts +++ b/src/src/vm/VMManager.ts @@ -1176,7 +1176,9 @@ export class VMManager extends Logger { ); if (lastChecksum && lastChecksum !== ZERO_HASH) { - const checksumBuffer = fromHex(lastChecksum.startsWith('0x') ? lastChecksum.slice(2) : lastChecksum); + const checksumBuffer = fromHex( + lastChecksum.startsWith('0x') ? lastChecksum.slice(2) : lastChecksum, + ); if (checksumBuffer.length !== 32) { throw new Error('Invalid checksum length retrieved from block header validator.'); } diff --git a/src/src/vm/rust/RustContract.ts b/src/src/vm/rust/RustContract.ts index 9aeb88c8d..99c334625 100644 --- a/src/src/vm/rust/RustContract.ts +++ b/src/src/vm/rust/RustContract.ts @@ -234,13 +234,17 @@ export class RustContract { txId: Uint8Array.from(environmentVariables.txId), txHash: Uint8Array.from(environmentVariables.txHash), contractAddress: Uint8Array.from(environmentVariables.contractAddress), - contractDeployer: Uint8Array.from(environmentVariables.contractDeployer), + contractDeployer: Uint8Array.from( + environmentVariables.contractDeployer, + ), caller: Uint8Array.from(environmentVariables.caller), origin: Uint8Array.from(environmentVariables.origin), chainId: getChainId(this.params.network), protocolId: OPNetConsensus.consensus.PROTOCOL_ID, consensusFlags: BigInt(environmentVariables.consensusFlags.toString()), - originTweakedPublicKey: Uint8Array.from(environmentVariables.originTweakedPublicKey), + originTweakedPublicKey: Uint8Array.from( + environmentVariables.originTweakedPublicKey, + ), }), ), ), diff --git a/src/src/vm/storage/VMStorage.ts b/src/src/vm/storage/VMStorage.ts index b5fc79df2..b4671e393 100644 --- a/src/src/vm/storage/VMStorage.ts +++ b/src/src/vm/storage/VMStorage.ts @@ -120,9 +120,7 @@ export abstract class VMStorage extends Logger { size: number; }>; - public abstract getMempoolTransaction( - id: string, - ): Promise; + public abstract getMempoolTransaction(id: string): Promise; public abstract getLatestPendingTransactions( addresses?: string[], @@ -196,7 +194,9 @@ export abstract class VMStorage extends Logger { /** * Get epoch by epoch hash */ - public abstract getEpochByHash(epochHash: Uint8Array | Binary): Promise; + public abstract getEpochByHash( + epochHash: Uint8Array | Binary, + ): Promise; /** * Get epoch by block height (find which epoch contains this block) @@ -218,7 +218,9 @@ export abstract class VMStorage extends Logger { /** * Get epochs by target hash */ - public abstract getEpochsByTargetHash(targetHash: Uint8Array | Binary): Promise; + public abstract getEpochsByTargetHash( + targetHash: Uint8Array | Binary, + ): Promise; /** * Save or update an epoch diff --git a/src/src/vm/storage/databases/VMMongoStorage.ts b/src/src/vm/storage/databases/VMMongoStorage.ts index d98757ba1..a14f7d04b 100644 --- a/src/src/vm/storage/databases/VMMongoStorage.ts +++ b/src/src/vm/storage/databases/VMMongoStorage.ts @@ -530,9 +530,7 @@ export class VMMongoStorage extends VMStorage { return await this.mempoolRepository.getMempoolInfo(); } - public async getMempoolTransaction( - id: string, - ): Promise { + public async getMempoolTransaction(id: string): Promise { if (!this.mempoolRepository) { throw new Error('Mempool repository not initialized'); } diff --git a/tests/config/btc.unit.test.conf b/tests/config/btc.unit.test.conf index 55b6dbaff..192d2b86b 100644 --- a/tests/config/btc.unit.test.conf +++ b/tests/config/btc.unit.test.conf @@ -38,7 +38,6 @@ UTXO_SAVE_INTERVAL = 120000 [OP_NET] MODE = "ARCHIVE" LIGHT_MODE_FROM_BLOCK = 10000 -ENABLED_AT_BLOCK = 0 REINDEX = false REINDEX_FROM_BLOCK = 1 ENABLE_BATCH_PROCESSING = true diff --git a/tools/autoconfig.sh b/tools/autoconfig.sh index bc6a09f2d..bc0e052c6 100644 --- a/tools/autoconfig.sh +++ b/tools/autoconfig.sh @@ -1082,7 +1082,6 @@ PURGE_SPENT_UTXO_OLDER_THAN_BLOCKS = 1000 [OP_NET] MODE = "$MODE" -ENABLED_AT_BLOCK = 0 REINDEX = false REINDEX_FROM_BLOCK = 0