import ServiceVersionModel from '../common/models/ServiceVersionModel'; import TransactionModel from '../common/models/TransactionModel'; import { IBitcoinConfig } from './IBitcoinConfig'; /** * Object representing a blockchain time and hash */ export interface IBlockchainTime { /** The logical blockchain time */ time: number; /** The hash associated with the blockchain time */ hash: string; } /** * Data structure containing block height and hash. */ export interface IBlockInfo { /** Block height. */ height: number; /** Block hash. */ hash: string; } /** * Processor for Bitcoin REST API calls */ export default class BitcoinProcessor { /** URI for the bitcoin peer's RPC endpoint */ readonly bitcoinPeerUri: string; /** Bitcoin peer's RPC basic authorization credentials */ readonly bitcoinAuthorization?: string; /** Prefix used to identify Sidetree transactions in Bitcoin's blockchain. */ readonly sidetreePrefix: string; /** Bitcoin transaction fee amount */ readonly bitcoinFee: number; /** The first Sidetree block in Bitcoin's blockchain. */ readonly genesisBlockNumber: number; /** Store for the state of sidetree transactions. */ private readonly transactionStore; /** Wallet private key */ private readonly privateKey; /** Number of items to return per page */ pageSize: number; /** request timeout in milliseconds */ requestTimeout: number; /** maximum number of request retries */ maxRetries: number; /** Number of seconds between transaction queries */ pollPeriod: number; /** Days of notice before the wallet is depeleted of all funds */ lowBalanceNoticeDays: number; /** Last seen block */ private lastSeenBlock; /** Poll timeout identifier */ private pollTimeoutId; private serviceInfo; constructor(config: IBitcoinConfig); /** * generates a private key in WIF format * @param network Which bitcoin network to generate this key for */ static generatePrivateKey(network: 'mainnet' | 'livenet' | 'testnet' | undefined): string; /** * Initializes the Bitcoin processor */ initialize(): Promise; /** * Gets the blockchain time of the given time hash. * Gets the latest logical blockchain time if time hash is not given. * @param hash Blockchain time hash. * @returns the current or associated blockchain time of the given time hash. */ time(hash?: string): Promise; /** * Fetches Sidetree transactions in chronological order from since or genesis. * @param since A transaction number * @param hash The associated transaction time hash * @returns Transactions since given transaction number. */ transactions(since?: number, hash?: string): Promise<{ moreTransactions: boolean; transactions: TransactionModel[]; }>; /** * Given an ordered list of Sidetree transactions, returns the first transaction in the list that is valid. * @param transactions List of transactions to check * @returns The first valid transaction, or undefined if none are valid */ firstValidTransaction(transactions: TransactionModel[]): Promise; /** * Writes a Sidetree transaction to the underlying Bitcoin's blockchain. * @param anchorString The string to be written as part of the transaction. */ writeTransaction(anchorString: string): Promise; /** * Handles the get version operation. */ getServiceVersion(): Promise; /** * Gets the block hash for a given block height * @param height The height to get a hash for * @returns the block hash */ private getBlockHash; /** * Gets all unspent coins of a given address * @param address Bitcoin address to get coins for */ private getUnspentCoins; /** * Broadcasts a transaction to the bitcoin network * @param transaction Transaction to broadcast */ private broadcastTransaction; /** * Will process transactions every interval seconds. * @param interval Number of seconds between each query */ private periodicPoll; /** * Processes transactions from startBlock (or genesis) to endBlockHeight (or tip) * @param startBlock The block to begin from (inclusive) * @param endBlockHeight The blockheight to stop on (inclusive) * @returns The block height and hash it processed to */ private processTransactions; /** * Begins to revert the blockchain cache until consistent, returns last good height * @returns last valid block height before the fork */ private revertBlockchainCache; /** * Gets the current Bitcoin block height * @returns the latest block number */ private getCurrentBlockHeight; /** * Given a Bitcoin block height and hash, verifies against the blockchain * @param height Block height to verify * @param hash Block hash to verify * @returns true if valid, false otherwise */ private verifyBlock; /** * Given a Bitcoin block height, processes that block for Sidetree transactions * @param block Block height to process * @returns the block hash processed */ private processBlock; private addValidSidetreeTransactionsFromVOutsToTransactionStore; /** * Checks if the bitcoin peer has a wallet open for a given address * @param address The bitcoin address to check * @returns true if a wallet exists, false otherwise. */ private walletExists; /** * performs an RPC call given a request * @param request RPC request parameters as an object * @param path optional path extension * @returns response as an object */ private rpcCall; /** * Calls `nodeFetch` and retries with exponential back-off on `request-timeout` FetchError`. * @param uri URI to fetch * @param requestParameters Request parameters to use * @param setTimeout True to set a timeout on the request, and retry if times out, false to wait indefinitely. * @returns Response of the fetch */ private fetchWithRetry; /** * Async timeout * @param milliseconds Timeout in milliseconds */ private waitFor; }