mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 18:47:38 +01:00
Create Util functions for wallets with a bitcoind backend (#2076)
* Create Util functions for wallets with a bitcoind backend * Move function, delete reduant function * Fix imports
This commit is contained in:
parent
108ffa0716
commit
ad6c2563bd
5 changed files with 95 additions and 55 deletions
|
@ -0,0 +1,89 @@
|
|||
package org.bitcoins.server
|
||||
|
||||
import org.bitcoins.core.api.node.NodeApi
|
||||
import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.core.util.{BitcoinSLogger, FutureUtil}
|
||||
import org.bitcoins.crypto.DoubleSha256Digest
|
||||
import org.bitcoins.rpc.client.common.BitcoindRpcClient
|
||||
import org.bitcoins.wallet.Wallet
|
||||
|
||||
import scala.concurrent.{ExecutionContext, Future, Promise}
|
||||
|
||||
/** Useful utilities to use in the wallet project for syncing things against bitcoind */
|
||||
object BitcoindRpcBackendUtil extends BitcoinSLogger {
|
||||
|
||||
def createWalletWithBitcoindCallbacks(
|
||||
bitcoind: BitcoindRpcClient,
|
||||
wallet: Wallet)(implicit ec: ExecutionContext): Wallet = {
|
||||
// Kill the old wallet
|
||||
wallet.stopWalletThread()
|
||||
|
||||
// We need to create a promise so we can inject the wallet with the callback
|
||||
// after we have created it into SyncUtil.getNodeApiWalletCallback
|
||||
// so we don't lose the internal state of the wallet
|
||||
val walletCallbackP = Promise[Wallet]()
|
||||
|
||||
val pairedWallet = Wallet(
|
||||
keyManager = wallet.keyManager,
|
||||
nodeApi =
|
||||
BitcoindRpcBackendUtil.getNodeApiWalletCallback(bitcoind,
|
||||
walletCallbackP.future),
|
||||
chainQueryApi = bitcoind,
|
||||
feeRateApi = wallet.feeRateApi,
|
||||
creationTime = wallet.keyManager.creationTime
|
||||
)(wallet.walletConfig, wallet.ec)
|
||||
|
||||
walletCallbackP.success(pairedWallet)
|
||||
|
||||
pairedWallet
|
||||
}
|
||||
|
||||
def getNodeApiWalletCallback(
|
||||
bitcoindRpcClient: BitcoindRpcClient,
|
||||
walletF: Future[Wallet])(implicit ec: ExecutionContext): NodeApi = {
|
||||
new NodeApi {
|
||||
|
||||
override def downloadBlocks(
|
||||
blockHashes: Vector[DoubleSha256Digest]): Future[Unit] = {
|
||||
logger.info(s"Fetching ${blockHashes.length} hashes from bitcoind")
|
||||
val f: Vector[DoubleSha256Digest] => Future[Wallet] = { hashes =>
|
||||
val blocksF =
|
||||
FutureUtil.sequentially(hashes)(bitcoindRpcClient.getBlockRaw)
|
||||
|
||||
val updatedWalletF = for {
|
||||
blocks <- blocksF
|
||||
wallet <- walletF
|
||||
processedWallet <- {
|
||||
FutureUtil.foldLeftAsync(wallet, blocks) {
|
||||
case (wallet, block) =>
|
||||
wallet.processBlock(block)
|
||||
}
|
||||
}
|
||||
} yield processedWallet
|
||||
|
||||
updatedWalletF
|
||||
}
|
||||
|
||||
val batchSize = 25
|
||||
val batchedExecutedF = FutureUtil.batchExecute(elements = blockHashes,
|
||||
f = f,
|
||||
init = Vector.empty,
|
||||
batchSize = batchSize)
|
||||
|
||||
batchedExecutedF.map { _ =>
|
||||
logger.info(
|
||||
s"Done fetching ${blockHashes.length} hashes from bitcoind")
|
||||
()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts the given transaction over the P2P network
|
||||
*/
|
||||
override def broadcastTransaction(
|
||||
transaction: Transaction): Future[Unit] = {
|
||||
bitcoindRpcClient.sendRawTransaction(transaction).map(_ => ())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -15,13 +15,7 @@ import org.bitcoins.chain.models.{
|
|||
}
|
||||
import org.bitcoins.core.Core
|
||||
import org.bitcoins.core.api.chain.ChainApi
|
||||
import org.bitcoins.core.config.{
|
||||
BitcoinNetworks,
|
||||
MainNet,
|
||||
RegTest,
|
||||
SigNet,
|
||||
TestNet3
|
||||
}
|
||||
import org.bitcoins.core.config._
|
||||
import org.bitcoins.core.util.{FutureUtil, NetworkUtil}
|
||||
import org.bitcoins.db._
|
||||
import org.bitcoins.feeprovider.BitcoinerLiveFeeRateProvider
|
||||
|
|
|
@ -103,9 +103,7 @@ class BitcoindRpcClient(val instance: BitcoindInstance)(implicit
|
|||
|
||||
/** Gets the block height of the closest block to the given time */
|
||||
override def epochSecondToBlockHeight(time: Long): Future[Int] =
|
||||
Future.failed(
|
||||
new UnsupportedOperationException(
|
||||
"epochSecondToBlockHeight is not supported by bitcoind"))
|
||||
Future.successful(0)
|
||||
|
||||
// Node Api
|
||||
|
||||
|
|
|
@ -2,12 +2,9 @@ package org.bitcoins.testkit.chain
|
|||
|
||||
import org.bitcoins.chain.blockchain.sync.FilterWithHeaderHash
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind.GetBlockFilterResult
|
||||
import org.bitcoins.core.api.chain.ChainQueryApi.FilterResponse
|
||||
import org.bitcoins.core.api.node.{NodeApi, NodeChainQueryApi}
|
||||
import org.bitcoins.core.api.chain.ChainQueryApi
|
||||
import org.bitcoins.core.api.node
|
||||
import org.bitcoins.core.api.node.{NodeApi, NodeChainQueryApi}
|
||||
import org.bitcoins.core.gcs.FilterType
|
||||
import org.bitcoins.core.protocol.BlockStamp
|
||||
import org.bitcoins.core.protocol.blockchain.BlockHeader
|
||||
import org.bitcoins.core.protocol.transaction.Transaction
|
||||
import org.bitcoins.core.util.{BitcoinSLogger, FutureUtil}
|
||||
|
@ -48,44 +45,6 @@ abstract class SyncUtil extends BitcoinSLogger {
|
|||
}
|
||||
}
|
||||
|
||||
def getTestChainQueryApi(bitcoind: BitcoindRpcClient): ChainQueryApi = {
|
||||
new ChainQueryApi {
|
||||
|
||||
/** Gets the height of the given block */
|
||||
override def getBlockHeight(
|
||||
blockHash: DoubleSha256DigestBE): Future[Option[Int]] =
|
||||
bitcoind.getBlockHeight(blockHash)
|
||||
|
||||
/** Gets the hash of the block that is what we consider "best" */
|
||||
override def getBestBlockHash(): Future[DoubleSha256DigestBE] = {
|
||||
bitcoind.getBestBlockHash
|
||||
}
|
||||
|
||||
/** Gets number of confirmations for the given block hash */
|
||||
override def getNumberOfConfirmations(
|
||||
blockHashOpt: DoubleSha256DigestBE): Future[Option[Int]] = {
|
||||
bitcoind.getNumberOfConfirmations(blockHashOpt)
|
||||
}
|
||||
|
||||
/** Gets the number of compact filters in the database */
|
||||
override def getFilterCount: Future[Int] = {
|
||||
bitcoind.getFilterCount
|
||||
}
|
||||
|
||||
/** Returns the block height of the given block stamp */
|
||||
override def getHeightByBlockStamp(blockStamp: BlockStamp): Future[Int] =
|
||||
bitcoind.getHeightByBlockStamp(blockStamp)
|
||||
|
||||
override def epochSecondToBlockHeight(time: Long): Future[Int] =
|
||||
Future.successful(0)
|
||||
|
||||
override def getFiltersBetweenHeights(
|
||||
startHeight: Int,
|
||||
endHeight: Int): Future[Vector[FilterResponse]] =
|
||||
bitcoind.getFiltersBetweenHeights(startHeight, endHeight)
|
||||
}
|
||||
}
|
||||
|
||||
def getNodeApi(bitcoindRpcClient: BitcoindRpcClient)(implicit
|
||||
ec: ExecutionContext): NodeApi = {
|
||||
new NodeApi {
|
||||
|
@ -180,7 +139,7 @@ abstract class SyncUtil extends BitcoinSLogger {
|
|||
|
||||
def getNodeChainQueryApi(bitcoind: BitcoindRpcClient)(implicit
|
||||
ec: ExecutionContext): NodeChainQueryApi = {
|
||||
val chainQuery = SyncUtil.getTestChainQueryApi(bitcoind)
|
||||
val chainQuery = bitcoind
|
||||
val nodeApi = SyncUtil.getNodeApi(bitcoind)
|
||||
node.NodeChainQueryApi(nodeApi, chainQuery)
|
||||
}
|
||||
|
@ -189,7 +148,7 @@ abstract class SyncUtil extends BitcoinSLogger {
|
|||
bitcoind: BitcoindRpcClient,
|
||||
walletF: Future[Wallet])(implicit
|
||||
ec: ExecutionContext): NodeChainQueryApi = {
|
||||
val chainQuery = SyncUtil.getTestChainQueryApi(bitcoind)
|
||||
val chainQuery = bitcoind
|
||||
val nodeApi =
|
||||
SyncUtil.getNodeApiWalletCallback(bitcoind, walletF)
|
||||
node.NodeChainQueryApi(nodeApi, chainQuery)
|
||||
|
|
|
@ -474,7 +474,7 @@ object BitcoinSWalletTest extends WalletLogger {
|
|||
keyManager = wallet.keyManager,
|
||||
nodeApi =
|
||||
SyncUtil.getNodeApiWalletCallback(bitcoind, walletCallbackP.future),
|
||||
chainQueryApi = SyncUtil.getTestChainQueryApi(bitcoind),
|
||||
chainQueryApi = bitcoind,
|
||||
feeRateApi = new RandomFeeProvider,
|
||||
creationTime = wallet.keyManager.creationTime
|
||||
)(wallet.walletConfig, wallet.ec)
|
||||
|
|
Loading…
Add table
Reference in a new issue