mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 10:46:42 +01:00
Implement bitcoind RPC 26.x
(#5550)
* Get build started for 26.1 * Start introducing v26 data structures * Switch BitcoindVersion.newest = V26 * Fix GetTxOutSetInfoResult to use hash_serialized_3 * Fix WalletRpcTest * Refactor PeerInfoResponse to add transport_protocol_type and session_id fields in v25 * Add ServiceIdentifier.NODE_P2P_V2, add support for v2transport to addnode, add default config setting for bitcoind to have v2transport=1 in test framework, add unit test to make sure we can establish a v2 connection * Remove V20AssortedRpc * Add loadtxoutset * Implement getchainstates * Add getprioritisedtransactions * Add getaddrmaninfo * Add importmempool * Cleanup println
This commit is contained in:
parent
5dc5cca9cf
commit
7ef6086673
28 changed files with 357 additions and 182 deletions
|
@ -27,9 +27,18 @@ case class DumpTxOutSetResult(
|
|||
coins_written: Int,
|
||||
base_hash: DoubleSha256DigestBE,
|
||||
base_height: Int,
|
||||
path: Path
|
||||
path: Path,
|
||||
txoutset_hash: DoubleSha256DigestBE,
|
||||
nchaintx: Long
|
||||
) extends BlockchainResult
|
||||
|
||||
case class LoadTxOutSetResult(
|
||||
coins_loaded: Long,
|
||||
tip_hash: DoubleSha256DigestBE,
|
||||
base_height: Long,
|
||||
path: Path)
|
||||
extends BlockchainResult
|
||||
|
||||
case class GetBlockResult(
|
||||
hash: DoubleSha256DigestBE,
|
||||
confirmations: Int,
|
||||
|
@ -357,7 +366,7 @@ case class GetTxOutSetInfoResult(
|
|||
transactions: Int,
|
||||
txouts: Int,
|
||||
bogosize: Int,
|
||||
hash_serialized_2: DoubleSha256DigestBE,
|
||||
hash_serialized_3: DoubleSha256DigestBE,
|
||||
disk_size: Int,
|
||||
total_amount: Bitcoins
|
||||
) extends BlockchainResult
|
||||
|
@ -420,3 +429,13 @@ case class ScanInProgress(progress: BigDecimal, current_height: Int)
|
|||
extends StatusScanBlocksResult
|
||||
|
||||
case class ScanBlocksAbortResult(aborted: Boolean) extends ScanBlocksResult
|
||||
|
||||
case class ChainState(
|
||||
blocks: Int,
|
||||
bestblockhash: DoubleSha256DigestBE,
|
||||
difficulty: BigDecimal,
|
||||
verificationprogress: BigDecimal,
|
||||
coins_db_cache_bytes: Long,
|
||||
coins_tip_cache_bytes: Long,
|
||||
validated: Boolean)
|
||||
case class ChainStateResult(headers: Int, chainstates: Vector[ChainState])
|
||||
|
|
|
@ -98,12 +98,13 @@ case class Network(
|
|||
case class NetworkAddress(address: String, port: Int, score: Int)
|
||||
extends NetworkResult
|
||||
|
||||
sealed trait Peer extends NetworkResult {
|
||||
sealed trait PeerInfoResponse extends NetworkResult {
|
||||
def id: Int
|
||||
def networkInfo: PeerNetworkInfo
|
||||
def version: Int
|
||||
def subver: String
|
||||
def inbound: Boolean
|
||||
def connection_type: String
|
||||
def addnode: Boolean
|
||||
def startingheight: Int
|
||||
def synced_headers: Int
|
||||
|
@ -114,25 +115,7 @@ sealed trait Peer extends NetworkResult {
|
|||
def minfeefilter: Option[SatoshisPerKiloByte]
|
||||
}
|
||||
|
||||
case class PeerPostV21(
|
||||
id: Int,
|
||||
networkInfo: PeerNetworkInfoPostV21,
|
||||
version: Int,
|
||||
subver: String,
|
||||
inbound: Boolean,
|
||||
connection_type: String,
|
||||
startingheight: Int,
|
||||
synced_headers: Int,
|
||||
synced_blocks: Int,
|
||||
inflight: Vector[Int],
|
||||
bytessent_per_msg: Map[String, Int],
|
||||
bytesrecv_per_msg: Map[String, Int],
|
||||
minfeefilter: Option[SatoshisPerKiloByte]
|
||||
) extends Peer {
|
||||
override val addnode: Boolean = connection_type == "manual"
|
||||
}
|
||||
|
||||
case class PeerV22(
|
||||
case class PeerInfoResponseV25(
|
||||
id: Int,
|
||||
networkInfo: PeerNetworkInfoPostV21,
|
||||
version: Int,
|
||||
|
@ -148,8 +131,10 @@ case class PeerV22(
|
|||
minfeefilter: Option[SatoshisPerKiloByte],
|
||||
bip152_hb_to: Boolean,
|
||||
bip152_hb_from: Boolean,
|
||||
permissions: Vector[String]
|
||||
) extends Peer {
|
||||
permissions: Vector[String],
|
||||
transport_protocol_type: String,
|
||||
session_id: String
|
||||
) extends PeerInfoResponse {
|
||||
override val addnode: Boolean = connection_type == "manual"
|
||||
}
|
||||
|
||||
|
@ -246,3 +231,12 @@ case class GetNodeAddressesResultPostV22(
|
|||
port: Int,
|
||||
network: String
|
||||
) extends GetNodeAddressesResult
|
||||
|
||||
case class AddrManInfo(`new`: Int, tried: Int, total: Int)
|
||||
case class GetAddrmanInfoResponse(
|
||||
ipv4: AddrManInfo,
|
||||
ipv6: AddrManInfo,
|
||||
onion: AddrManInfo,
|
||||
cjdns: AddrManInfo,
|
||||
all_networks: AddrManInfo)
|
||||
extends NetworkResult
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
package org.bitcoins.commons.jsonmodels.bitcoind
|
||||
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LabelPurpose
|
||||
import org.bitcoins.core.currency.Bitcoins
|
||||
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
||||
import org.bitcoins.core.hd.BIP32Path
|
||||
import org.bitcoins.core.number.UInt32
|
||||
import org.bitcoins.core.protocol.BitcoinAddress
|
||||
|
@ -391,3 +391,5 @@ case class ImportDescriptorResult(
|
|||
success: Boolean,
|
||||
warnings: Option[Vector[String]]
|
||||
) extends WalletResult
|
||||
|
||||
case class PrioritisedTransaction(fee_delta: Satoshis, in_mempool: Boolean)
|
||||
|
|
|
@ -232,19 +232,25 @@ object JsonSerializers {
|
|||
implicit val peerNetworkInfoPostV21Reads: Reads[PeerNetworkInfoPostV21] =
|
||||
Json.reads[PeerNetworkInfoPostV21]
|
||||
|
||||
implicit val peerPostV21Reads: Reads[PeerPostV21] = ((__ \ "id").read[Int] and
|
||||
__.read[PeerNetworkInfoPostV21] and
|
||||
(__ \ "version").read[Int] and
|
||||
(__ \ "subver").read[String] and
|
||||
(__ \ "inbound").read[Boolean] and
|
||||
(__ \ "connection_type").read[String] and
|
||||
(__ \ "startingheight").read[Int] and
|
||||
(__ \ "synced_headers").read[Int] and
|
||||
(__ \ "synced_blocks").read[Int] and
|
||||
(__ \ "inflight").read[Vector[Int]] and
|
||||
(__ \ "bytessent_per_msg").read[Map[String, Int]] and
|
||||
(__ \ "bytesrecv_per_msg").read[Map[String, Int]] and
|
||||
(__ \ "minfeefilter").readNullable[SatoshisPerKiloByte])(PeerPostV21)
|
||||
implicit val peerPostV25Reads: Reads[PeerInfoResponseV25] =
|
||||
((__ \ "id").read[Int] and
|
||||
__.read[PeerNetworkInfoPostV21] and
|
||||
(__ \ "version").read[Int] and
|
||||
(__ \ "subver").read[String] and
|
||||
(__ \ "inbound").read[Boolean] and
|
||||
(__ \ "connection_type").read[String] and
|
||||
(__ \ "startingheight").read[Int] and
|
||||
(__ \ "synced_headers").read[Int] and
|
||||
(__ \ "synced_blocks").read[Int] and
|
||||
(__ \ "inflight").read[Vector[Int]] and
|
||||
(__ \ "bytessent_per_msg").read[Map[String, Int]] and
|
||||
(__ \ "bytesrecv_per_msg").read[Map[String, Int]] and
|
||||
(__ \ "minfeefilter").readNullable[SatoshisPerKiloByte] and
|
||||
(__ \ "bip152_hb_to").read[Boolean] and
|
||||
(__ \ "bip152_hb_from").read[Boolean] and
|
||||
(__ \ "permissions").read[Vector[String]] and
|
||||
(__ \ "transport_protocol_type").read[String] and
|
||||
(__ \ "session_id").read[String])(PeerInfoResponseV25)
|
||||
|
||||
implicit val nodeBanPostV22Reads: Reads[NodeBanPostV22] =
|
||||
Json.reads[NodeBanPostV22]
|
||||
|
@ -256,6 +262,10 @@ object JsonSerializers {
|
|||
implicit val dumpTxOutSetResultReads: Reads[DumpTxOutSetResult] =
|
||||
Json.reads[DumpTxOutSetResult]
|
||||
|
||||
implicit val loadTxOutSetResultReads: Reads[LoadTxOutSetResult] = {
|
||||
Json.reads[LoadTxOutSetResult]
|
||||
}
|
||||
|
||||
implicit val getBlockResultReads: Reads[GetBlockResult] =
|
||||
Json.reads[GetBlockResult]
|
||||
|
||||
|
@ -885,4 +895,18 @@ object JsonSerializers {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
implicit val chainStateReads: Reads[ChainState] = Json.reads[ChainState]
|
||||
|
||||
implicit val chainStateResultReads: Reads[ChainStateResult] =
|
||||
Json.reads[ChainStateResult]
|
||||
|
||||
implicit val prioritisedTransactionReads: Reads[PrioritisedTransaction] = {
|
||||
Json.reads[PrioritisedTransaction]
|
||||
}
|
||||
|
||||
implicit val addrManInfoReads: Reads[AddrManInfo] = Json.reads[AddrManInfo]
|
||||
implicit val getAddrmanInfoResponseReads: Reads[GetAddrmanInfoResponse] = {
|
||||
Json.reads[GetAddrmanInfoResponse]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,8 @@ class BitcoindVersionTest extends BitcoindRpcTest {
|
|||
behavior of "BitcoindVersion"
|
||||
|
||||
it should "return version 25" in {
|
||||
val version = BitcoindVersion.fromNetworkVersion(250100)
|
||||
assert(version.equals(BitcoindVersion.V25))
|
||||
val version = BitcoindVersion.fromNetworkVersion(260100)
|
||||
assert(version.equals(BitcoindVersion.V26))
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -291,4 +291,19 @@ class BlockchainRpcTest extends BitcoindFixturesCachedPairNewest {
|
|||
assert(!response2.asInstanceOf[ScanBlocksAbortResult].aborted)
|
||||
}
|
||||
}
|
||||
|
||||
it must "be able to getchainstates" in { case nodePair =>
|
||||
val client = nodePair.node1
|
||||
val bestBlockHashF = client.getBestBlockHash()
|
||||
val blockCountF = client.getBlockCount()
|
||||
for {
|
||||
bestBlockHash <- bestBlockHashF
|
||||
blockCount <- blockCountF
|
||||
chainStateResult <- client.getChainStates()
|
||||
} yield {
|
||||
assert(chainStateResult.headers == blockCount)
|
||||
assert(chainStateResult.chainstates.size == 1)
|
||||
assert(chainStateResult.chainstates.head.bestblockhash == bestBlockHash)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -138,4 +138,20 @@ class DisconnectedPeersRpcTest
|
|||
|
||||
} yield assert(newBestHash == bestHash1)
|
||||
}
|
||||
|
||||
it must "connect to a peer with v2transport" in { nodePair =>
|
||||
val freshClient = nodePair.node1
|
||||
val otherFreshClient = nodePair.node2
|
||||
val uri = otherFreshClient.getDaemon.uri
|
||||
for {
|
||||
_ <- freshClient.addNode(uri, AddNodeArgument.OneTry, v2transport = true)
|
||||
_ <- BitcoindRpcTestUtil.awaitConnection(from = freshClient,
|
||||
to = otherFreshClient,
|
||||
interval = 1.second)
|
||||
|
||||
info <- freshClient.getPeerInfo
|
||||
} yield {
|
||||
assert(info.exists(_.transport_protocol_type == "v2"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,9 +121,14 @@ class MempoolRpcTest extends BitcoindFixturesCachedPairNewest {
|
|||
txid <-
|
||||
BitcoindRpcTestUtil
|
||||
.fundMemPoolTransaction(client, address, Bitcoins(3.2))
|
||||
tt <- client.prioritiseTransaction(txid, Bitcoins(1).satoshis)
|
||||
tt <- client.prioritiseTransaction(txid, Bitcoins.one.satoshis)
|
||||
txs <- client.getPrioritisedTransactions()
|
||||
} yield {
|
||||
assert(tt)
|
||||
assert(txs.exists(_._1 == txid))
|
||||
val p = txs(txid)
|
||||
assert(p.in_mempool)
|
||||
assert(p.fee_delta == Bitcoins.one)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -192,6 +197,8 @@ class MempoolRpcTest extends BitcoindFixturesCachedPairNewest {
|
|||
assert(!regTest.list().contains("mempool.dat"))
|
||||
for {
|
||||
_ <- client.saveMemPool()
|
||||
mempoolPath = regTest.toPath.resolve("mempool.dat")
|
||||
_ <- client.importMempool(mempoolPath)
|
||||
} yield assert(regTest.list().contains("mempool.dat"))
|
||||
}
|
||||
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
package org.bitcoins.rpc.common
|
||||
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.AddressType
|
||||
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
|
||||
import org.bitcoins.core.number.UInt32
|
||||
import org.bitcoins.core.protocol.P2PKHAddress
|
||||
import org.bitcoins.core.protocol.transaction._
|
||||
import org.bitcoins.core.wallet.fee.SatoshisPerByte
|
||||
import org.bitcoins.crypto.ECPrivateKey
|
||||
import org.bitcoins.rpc._
|
||||
import org.bitcoins.rpc.client.common._
|
||||
import org.bitcoins.rpc.config.{BitcoindInstanceLocal, BitcoindInstanceRemote}
|
||||
|
@ -196,16 +192,6 @@ class MultiWalletRpcTest extends BitcoindFixturesCachedPairNewest {
|
|||
}
|
||||
}
|
||||
|
||||
it should "be able to refill the keypool" in { nodePair =>
|
||||
val client = nodePair.node2
|
||||
for {
|
||||
_ <- client.walletPassphrase(password, 1000, walletName)
|
||||
info <- client.getWalletInfo(walletName)
|
||||
_ <- client.keyPoolRefill(info.keypoolsize + 1, walletName)
|
||||
newInfo <- client.getWalletInfo(walletName)
|
||||
} yield assert(newInfo.keypoolsize == info.keypoolsize + 1)
|
||||
}
|
||||
|
||||
it should "be able to change the wallet password" in { nodePair =>
|
||||
val walletClient = nodePair.node2
|
||||
val newPass = "new_password"
|
||||
|
@ -284,49 +270,6 @@ class MultiWalletRpcTest extends BitcoindFixturesCachedPairNewest {
|
|||
}
|
||||
}
|
||||
|
||||
it should "be able to import multiple addresses with importMulti" in {
|
||||
nodePair =>
|
||||
val client = nodePair.node2
|
||||
val privKey = ECPrivateKey.freshPrivateKey
|
||||
val address1 = P2PKHAddress(privKey.publicKey, networkParam)
|
||||
|
||||
val privKey1 = ECPrivateKey.freshPrivateKey
|
||||
val privKey2 = ECPrivateKey.freshPrivateKey
|
||||
|
||||
for {
|
||||
firstResult <-
|
||||
client
|
||||
.createMultiSig(
|
||||
2,
|
||||
Vector(privKey1.publicKey, privKey2.publicKey),
|
||||
AddressType.Bech32,
|
||||
walletNameOpt = Some(walletName)
|
||||
)
|
||||
address2 = firstResult.address
|
||||
|
||||
secondResult <-
|
||||
client
|
||||
.importMulti(
|
||||
Vector(
|
||||
RpcOpts.ImportMultiRequest(
|
||||
RpcOpts.ImportMultiAddress(address1),
|
||||
UInt32(0)
|
||||
),
|
||||
RpcOpts.ImportMultiRequest(
|
||||
RpcOpts.ImportMultiAddress(address2),
|
||||
UInt32(0)
|
||||
)
|
||||
),
|
||||
rescan = false,
|
||||
walletName = walletName
|
||||
)
|
||||
} yield {
|
||||
assert(secondResult.length == 2)
|
||||
assert(secondResult(0).success)
|
||||
assert(secondResult(1).success)
|
||||
}
|
||||
}
|
||||
|
||||
it should "be able to set the tx fee" in { nodePair =>
|
||||
val client = nodePair.node2
|
||||
for {
|
||||
|
|
|
@ -13,12 +13,15 @@ class NodeRpcTest extends BitcoindFixturesFundedCachedNewest {
|
|||
it should "be able to abort a rescan of the blockchain" in { case client =>
|
||||
// generate some extra blocks so rescan isn't too quick
|
||||
client.getNewAddress
|
||||
.flatMap(client.generateToAddress(3000, _))
|
||||
.flatMap(client.generateToAddress(500, _))
|
||||
.flatMap { _ =>
|
||||
val rescanFailedF =
|
||||
recoverToSucceededIf[MiscError](client.rescanBlockChain())
|
||||
system.scheduler.scheduleOnce(100.millis) {
|
||||
client.abortRescan()
|
||||
client
|
||||
.abortRescan()
|
||||
.failed
|
||||
.foreach(err => logger.error(s"NodeRpc.err abort rescan", err))
|
||||
()
|
||||
}
|
||||
rescanFailedF
|
||||
|
|
|
@ -116,4 +116,17 @@ class P2PRpcTest extends BitcoindFixturesCachedPairNewest {
|
|||
succeed
|
||||
}
|
||||
}
|
||||
|
||||
it should "getaddrmaninfo" in { case nodePair =>
|
||||
val client = nodePair.node1
|
||||
for {
|
||||
result <- client.getAddrManInfo()
|
||||
} yield {
|
||||
assert(result.ipv4.total == 0)
|
||||
assert(result.ipv6.total == 0)
|
||||
assert(result.onion.total == 0)
|
||||
assert(result.cjdns.total == 0)
|
||||
assert(result.all_networks.total == 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -70,19 +70,33 @@ class UTXORpcTest extends BitcoindFixturesFundedCachedNewest {
|
|||
}
|
||||
}
|
||||
|
||||
it should "correctly dump tx out set" in { case client =>
|
||||
it should "correctly dump tx out set and then load it" in { case client =>
|
||||
val path = new File("utxo.dat").toPath
|
||||
for {
|
||||
hash <- client.getBestBlockHash()
|
||||
height <- client.getBestHashBlockHeight()
|
||||
result <- client.dumpTxOutSet(new File("utxo.dat").toPath)
|
||||
result <- client.dumpTxOutSet(path)
|
||||
// now attempt to load it
|
||||
// unfortunately it seems this cannot be properly tested
|
||||
// we end up with this error:
|
||||
// Unable to load UTXO snapshot, assumeutxo block hash in snapshot metadata not recognized
|
||||
// see: https://bitcoin.stackexchange.com/questions/121006/anyone-tried-assumeutxo-yet
|
||||
// loadResult <- client.loadTxOutSet(path)
|
||||
} yield {
|
||||
assert(Files.exists(result.path))
|
||||
// Mild clean up
|
||||
Files.delete(result.path)
|
||||
|
||||
assert(result.base_hash == hash)
|
||||
assert(result.base_height == height)
|
||||
assert(result.coins_written > 0)
|
||||
|
||||
// assert(loadResult.path == path)
|
||||
// assert(loadResult.tip_hash == hash)
|
||||
// assert(loadResult.base_height == height)
|
||||
// assert(loadResult.coins_loaded > 0)
|
||||
|
||||
// Mild clean up
|
||||
Files.delete(result.path)
|
||||
succeed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,7 @@ TaskKeys.downloadBitcoind := {
|
|||
}
|
||||
|
||||
val versions =
|
||||
List("25.2")
|
||||
List("26.1", "25.2")
|
||||
|
||||
logger.debug(
|
||||
s"(Maybe) downloading Bitcoin Core binaries for versions: ${versions.mkString(",")}")
|
||||
|
@ -94,18 +94,24 @@ TaskKeys.downloadBitcoind := {
|
|||
val expectedHash =
|
||||
if (Properties.isLinux)
|
||||
Map(
|
||||
"25.2" -> "8d8c387e597e0edfc256f0bbace1dac3ad1ebf4a3c06da3e2975fda333817dea"
|
||||
"25.2" -> "8d8c387e597e0edfc256f0bbace1dac3ad1ebf4a3c06da3e2975fda333817dea",
|
||||
"26.1" -> "a5b7d206384a8100058d3f2e2f02123a8e49e83f523499e70e86e121a4897d5b"
|
||||
)
|
||||
else if (Properties.isMac)
|
||||
Map(
|
||||
"25.2" -> (if (System.getProperty("os.arch") == "aarch64")
|
||||
"f55b394eebaa11d4b717d68aad9f75b824aaf3a7841dac7c26b1ef3d6d2915f5"
|
||||
else
|
||||
"e06ba379f6039ca99bc32d3e7974d420a31363498936f88aac7bab6f239de0f5")
|
||||
"e06ba379f6039ca99bc32d3e7974d420a31363498936f88aac7bab6f239de0f5"),
|
||||
"26.1" -> (if (System.getProperty("os.arch") == "aarch64")
|
||||
"8a8e415763b7ffd5988153cf03967d812eca629016dd3b0ddf6da3ab6f4a3621"
|
||||
else
|
||||
"")
|
||||
)
|
||||
else if (Properties.isWin)
|
||||
Map(
|
||||
"25.2" -> "c2ac84f55ee879caefd4414868d318a741c52a7286da190bf7233d86a2ffca69"
|
||||
"25.2" -> "c2ac84f55ee879caefd4414868d318a741c52a7286da190bf7233d86a2ffca69",
|
||||
"26.1" -> "7bd0849e47472aeff99a0ea2c0cefd98f5be829e5a2d3b0168b5a54456cc638a"
|
||||
)
|
||||
else sys.error(s"Unsupported OS: ${Properties.osName}")
|
||||
|
||||
|
|
|
@ -15,8 +15,9 @@ import org.bitcoins.core.util.{FutureUtil, NetworkUtil}
|
|||
import org.bitcoins.core.wallet.fee.FeeUnit
|
||||
import org.bitcoins.crypto.{DoubleSha256DigestBE, StringFactory}
|
||||
import org.bitcoins.rpc.client.v18.V18AssortedRpc
|
||||
import org.bitcoins.rpc.client.v20.{V20AssortedRpc, V20MultisigRpc}
|
||||
import org.bitcoins.rpc.client.v20.V20MultisigRpc
|
||||
import org.bitcoins.rpc.client.v25.BitcoindV25RpcClient
|
||||
import org.bitcoins.rpc.client.v26.BitcoindV26RpcClient
|
||||
import org.bitcoins.rpc.config._
|
||||
|
||||
import java.io.File
|
||||
|
@ -53,8 +54,7 @@ class BitcoindRpcClient(override val instance: BitcoindInstance)(implicit
|
|||
with UtilRpc
|
||||
with V18AssortedRpc
|
||||
with DescriptorRpc
|
||||
with V20MultisigRpc
|
||||
with V20AssortedRpc {
|
||||
with V20MultisigRpc {
|
||||
|
||||
private val syncing = new AtomicBoolean(false)
|
||||
|
||||
|
@ -344,6 +344,7 @@ object BitcoindRpcClient {
|
|||
): BitcoindRpcClient = {
|
||||
val bitcoind = version match {
|
||||
case BitcoindVersion.V25 => BitcoindV25RpcClient.withActorSystem(instance)
|
||||
case BitcoindVersion.V26 => BitcoindV26RpcClient.withActorSystem(instance)
|
||||
case BitcoindVersion.Unknown =>
|
||||
sys.error(
|
||||
s"Cannot create a Bitcoin Core RPC client: unsupported version"
|
||||
|
@ -367,7 +368,7 @@ object BitcoindVersion
|
|||
with BitcoinSLogger {
|
||||
|
||||
/** The newest version of `bitcoind` we support */
|
||||
val newest: BitcoindVersion = V25
|
||||
val newest: BitcoindVersion = V26
|
||||
|
||||
val standard: Vector[BitcoindVersion] =
|
||||
Vector(V25)
|
||||
|
@ -378,6 +379,10 @@ object BitcoindVersion
|
|||
override def toString: String = "v25"
|
||||
}
|
||||
|
||||
case object V26 extends BitcoindVersion {
|
||||
override def toString: String = "v26"
|
||||
}
|
||||
|
||||
case object Unknown extends BitcoindVersion {
|
||||
override def toString: String = "Unknown"
|
||||
}
|
||||
|
|
|
@ -436,4 +436,8 @@ trait BlockchainRpc extends ChainApi { self: Client =>
|
|||
bitcoindCall("scanblocks", request.params)(
|
||||
JsonSerializers.ScanBlocksResultReads)
|
||||
}
|
||||
|
||||
def getChainStates(): Future[ChainStateResult] = {
|
||||
bitcoindCall("getchainstates")(JsonSerializers.chainStateResultReads)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
|
|||
import org.bitcoins.rpc.BitcoindException
|
||||
import play.api.libs.json.{JsArray, JsBoolean, JsString, Json}
|
||||
|
||||
import java.nio.file.Path
|
||||
import scala.concurrent.Future
|
||||
|
||||
/** This trait defines RPC calls related to the mempool of a Bitcoin Core node.
|
||||
|
@ -129,6 +130,10 @@ trait MempoolRpc { self: Client =>
|
|||
bitcoindCall[Unit]("savemempool")
|
||||
}
|
||||
|
||||
def importMempool(path: Path): Future[Unit] = {
|
||||
bitcoindCall[Unit]("importmempool", List(JsString(path.toString)))
|
||||
}
|
||||
|
||||
def testMempoolAccept(
|
||||
transaction: Vector[Transaction],
|
||||
maxFeeRate: Double = 0.10
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bitcoins.commons.jsonmodels.bitcoind.{
|
|||
GenerateBlockResult,
|
||||
GetBlockTemplateResult,
|
||||
GetMiningInfoResult,
|
||||
PrioritisedTransaction,
|
||||
RpcOpts
|
||||
}
|
||||
import org.bitcoins.commons.serializers.JsonReaders._
|
||||
|
@ -93,4 +94,21 @@ trait MiningRpc { self: Client with BlockchainRpc =>
|
|||
): Future[Boolean] = {
|
||||
prioritiseTransaction(txid.flip, feeDelta)
|
||||
}
|
||||
|
||||
def getPrioritisedTransactions()
|
||||
: Future[Map[DoubleSha256DigestBE, PrioritisedTransaction]] = {
|
||||
bitcoindCall[Map[DoubleSha256DigestBE, PrioritisedTransaction]](
|
||||
"getprioritisedtransactions")
|
||||
}
|
||||
|
||||
def generateToDescriptor(
|
||||
numBlocks: Int,
|
||||
descriptor: String,
|
||||
maxTries: Long = 1000000
|
||||
): Future[Vector[DoubleSha256DigestBE]] = {
|
||||
bitcoindCall[Vector[DoubleSha256DigestBE]](
|
||||
"generatetodescriptor",
|
||||
List(JsNumber(numBlocks), JsString(descriptor), JsNumber(maxTries))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,7 +27,7 @@ trait MultisigRpc { self: Client =>
|
|||
keys: Vector[Either[ECPublicKey, P2PKHAddress]],
|
||||
account: String = "",
|
||||
addressType: Option[AddressType],
|
||||
walletNameOpt: Option[String] = None
|
||||
walletName: String = BitcoindRpcClient.DEFAULT_WALLET_NAME
|
||||
): Future[MultiSigResult] = {
|
||||
def keyToString(key: Either[ECPublicKey, P2PKHAddress]): JsString =
|
||||
key match {
|
||||
|
@ -45,7 +45,7 @@ trait MultisigRpc { self: Client =>
|
|||
bitcoindCall[MultiSigResultPostV20](
|
||||
"addmultisigaddress",
|
||||
params,
|
||||
uriExtensionOpt = walletNameOpt.map(walletExtension)
|
||||
uriExtensionOpt = Some(walletExtension(walletName))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -81,7 +81,7 @@ trait MultisigRpc { self: Client =>
|
|||
minSignatures: Int,
|
||||
keys: Vector[ECPublicKey],
|
||||
addressType: AddressType,
|
||||
walletNameOpt: Option[String] = None
|
||||
walletName: String = BitcoindRpcClient.DEFAULT_WALLET_NAME
|
||||
): Future[MultiSigResult] = {
|
||||
bitcoindCall[MultiSigResultPostV20](
|
||||
"createmultisig",
|
||||
|
@ -90,7 +90,7 @@ trait MultisigRpc { self: Client =>
|
|||
Json.toJson(keys.map(_.hex)),
|
||||
Json.toJson(addressType)
|
||||
),
|
||||
uriExtensionOpt = walletNameOpt.map(walletExtension)
|
||||
uriExtensionOpt = Some(walletExtension(walletName))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.{
|
|||
SetBanCommand
|
||||
}
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind._
|
||||
import org.bitcoins.commons.serializers.JsonSerializers
|
||||
import org.bitcoins.commons.serializers.JsonSerializers._
|
||||
import org.bitcoins.core.protocol.blockchain.Block
|
||||
import play.api.libs.json.{JsBoolean, JsNumber, JsString}
|
||||
|
@ -17,10 +18,15 @@ import scala.concurrent.Future
|
|||
*/
|
||||
trait P2PRpc { self: Client =>
|
||||
|
||||
def addNode(address: URI, command: AddNodeArgument): Future[Unit] = {
|
||||
def addNode(
|
||||
address: URI,
|
||||
command: AddNodeArgument,
|
||||
v2transport: Boolean = true): Future[Unit] = {
|
||||
bitcoindCall[Unit](
|
||||
"addnode",
|
||||
List(JsString(address.getAuthority), JsString(command.toString))
|
||||
List(JsString(address.getAuthority),
|
||||
JsString(command.toString),
|
||||
JsBoolean(v2transport))
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -62,8 +68,8 @@ trait P2PRpc { self: Client =>
|
|||
}
|
||||
}
|
||||
|
||||
def getPeerInfo: Future[Vector[Peer]] = {
|
||||
bitcoindCall[Vector[PeerPostV21]]("getpeerinfo")
|
||||
def getPeerInfo: Future[Vector[PeerInfoResponseV25]] = {
|
||||
bitcoindCall[Vector[PeerInfoResponseV25]]("getpeerinfo")
|
||||
}
|
||||
|
||||
def listBanned: Future[Vector[NodeBan]] = {
|
||||
|
@ -93,6 +99,10 @@ trait P2PRpc { self: Client =>
|
|||
|
||||
def submitBlock(block: Block): Future[Unit] = {
|
||||
bitcoindCall[Unit]("submitblock", List(JsString(block.hex)))
|
||||
}
|
||||
|
||||
def getAddrManInfo(): Future[GetAddrmanInfoResponse] = {
|
||||
bitcoindCall[GetAddrmanInfoResponse]("getaddrmaninfo")(
|
||||
JsonSerializers.getAddrmanInfoResponseReads)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
package org.bitcoins.rpc.client.common
|
||||
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind.{RpcOpts, UnspentOutput}
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind.{
|
||||
DumpTxOutSetResult,
|
||||
LoadTxOutSetResult,
|
||||
RpcOpts,
|
||||
UnspentOutput
|
||||
}
|
||||
import org.bitcoins.commons.serializers.JsonSerializers
|
||||
import org.bitcoins.commons.serializers.JsonSerializers._
|
||||
import org.bitcoins.core.protocol.BitcoinAddress
|
||||
import org.bitcoins.core.protocol.transaction.TransactionOutPoint
|
||||
import play.api.libs.json._
|
||||
|
||||
import java.nio.file.Path
|
||||
import scala.concurrent.Future
|
||||
|
||||
/** This trait defines functionality related to UTXOs (unspent transaction
|
||||
|
@ -70,4 +77,18 @@ trait UTXORpc { self: Client =>
|
|||
)
|
||||
}
|
||||
|
||||
def dumpTxOutSet(path: Path): Future[DumpTxOutSetResult] = {
|
||||
bitcoindCall[DumpTxOutSetResult](
|
||||
"dumptxoutset",
|
||||
List(Json.toJson(path.toString))
|
||||
)
|
||||
}
|
||||
|
||||
def loadTxOutSet(path: Path): Future[LoadTxOutSetResult] = {
|
||||
bitcoindCall[LoadTxOutSetResult](
|
||||
"loadtxoutset",
|
||||
List(Json.toJson(path.toString))
|
||||
)(JsonSerializers.loadTxOutSetResultReads)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ trait UtilRpc { self: Client =>
|
|||
}
|
||||
|
||||
def decodeScript(script: ScriptPubKey): Future[DecodeScriptResult] = {
|
||||
self.version.flatMap { case V25 | Unknown =>
|
||||
self.version.flatMap { case V25 | V26 | Unknown =>
|
||||
bitcoindCall[DecodeScriptResultV22](
|
||||
"decodescript",
|
||||
List(Json.toJson(script))
|
||||
|
@ -34,13 +34,13 @@ trait UtilRpc { self: Client =>
|
|||
}
|
||||
|
||||
def getIndexInfo: Future[Map[String, IndexInfoResult]] = {
|
||||
version.flatMap { case V25 | Unknown =>
|
||||
version.flatMap { case V25 | V26 | Unknown =>
|
||||
bitcoindCall[Map[String, IndexInfoResult]]("getindexinfo")
|
||||
}
|
||||
}
|
||||
|
||||
def getIndexInfo(indexName: String): Future[IndexInfoResult] = {
|
||||
version.flatMap { case V25 | Unknown =>
|
||||
version.flatMap { case V25 | V26 | Unknown =>
|
||||
bitcoindCall[Map[String, IndexInfoResult]](
|
||||
"getindexinfo",
|
||||
List(JsString(indexName))
|
||||
|
|
|
@ -160,11 +160,13 @@ trait WalletRpc { self: Client =>
|
|||
def getWalletInfo(
|
||||
walletName: String
|
||||
): Future[GetWalletInfoResult] = {
|
||||
self.version.flatMap { case BitcoindVersion.V25 | BitcoindVersion.Unknown =>
|
||||
bitcoindCall[GetWalletInfoResultPostV22](
|
||||
"getwalletinfo",
|
||||
uriExtensionOpt = Some(walletExtension(walletName))
|
||||
)
|
||||
self.version.flatMap {
|
||||
case BitcoindVersion.V25 | BitcoindVersion.V26 |
|
||||
BitcoindVersion.Unknown =>
|
||||
bitcoindCall[GetWalletInfoResultPostV22](
|
||||
"getwalletinfo",
|
||||
uriExtensionOpt = Some(walletExtension(walletName))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -378,10 +380,10 @@ trait WalletRpc { self: Client =>
|
|||
blank: Boolean = false,
|
||||
passphrase: String = "",
|
||||
avoidReuse: Boolean = false,
|
||||
descriptors: Boolean = false
|
||||
descriptors: Boolean = true
|
||||
): Future[CreateWalletResult] =
|
||||
self.version.flatMap {
|
||||
case V25 =>
|
||||
case V25 | V26 =>
|
||||
bitcoindCall[CreateWalletResult](
|
||||
"createwallet",
|
||||
List(
|
||||
|
@ -410,13 +412,11 @@ trait WalletRpc { self: Client =>
|
|||
address: BitcoinAddress,
|
||||
walletName: String = DEFAULT_WALLET
|
||||
): Future[AddressInfoResult] = {
|
||||
self.version.flatMap { case V25 | Unknown =>
|
||||
bitcoindCall[AddressInfoResultPostV21](
|
||||
"getaddressinfo",
|
||||
List(JsString(address.value)),
|
||||
uriExtensionOpt = Some(walletExtension(walletName))
|
||||
)
|
||||
}
|
||||
bitcoindCall[AddressInfoResultPostV21](
|
||||
"getaddressinfo",
|
||||
List(JsString(address.value)),
|
||||
uriExtensionOpt = Some(walletExtension(walletName))
|
||||
)
|
||||
}
|
||||
|
||||
def sendMany(
|
||||
|
|
|
@ -1,34 +0,0 @@
|
|||
package org.bitcoins.rpc.client.v20
|
||||
|
||||
import java.nio.file.Path
|
||||
|
||||
import org.bitcoins.commons.jsonmodels.bitcoind.DumpTxOutSetResult
|
||||
import org.bitcoins.commons.serializers.JsonSerializers._
|
||||
import org.bitcoins.crypto.DoubleSha256DigestBE
|
||||
import org.bitcoins.rpc.client.common.Client
|
||||
import play.api.libs.json.{JsNumber, JsString, Json}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
||||
/** Assorted Rpc calls for Bitcoin V20
|
||||
*/
|
||||
trait V20AssortedRpc { self: Client =>
|
||||
|
||||
def dumpTxOutSet(path: Path): Future[DumpTxOutSetResult] = {
|
||||
bitcoindCall[DumpTxOutSetResult](
|
||||
"dumptxoutset",
|
||||
List(Json.toJson(path.toString))
|
||||
)
|
||||
}
|
||||
|
||||
def generateToDescriptor(
|
||||
numBlocks: Int,
|
||||
descriptor: String,
|
||||
maxTries: Long = 1000000
|
||||
): Future[Vector[DoubleSha256DigestBE]] = {
|
||||
bitcoindCall[Vector[DoubleSha256DigestBE]](
|
||||
"generatetodescriptor",
|
||||
List(JsNumber(numBlocks), JsString(descriptor), JsNumber(maxTries))
|
||||
)
|
||||
}
|
||||
}
|
|
@ -6,7 +6,7 @@ import org.bitcoins.commons.serializers.JsonSerializers._
|
|||
import org.bitcoins.commons.serializers.JsonWriters._
|
||||
import org.bitcoins.core.protocol.P2PKHAddress
|
||||
import org.bitcoins.crypto.ECPublicKey
|
||||
import org.bitcoins.rpc.client.common.{Client, MultisigRpc}
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, Client, MultisigRpc}
|
||||
import play.api.libs.json.{JsArray, JsNumber, JsString, Json}
|
||||
|
||||
import scala.concurrent.Future
|
||||
|
@ -74,7 +74,7 @@ trait V20MultisigRpc extends MultisigRpc { self: Client =>
|
|||
minSignatures: Int,
|
||||
keys: Vector[ECPublicKey],
|
||||
addressType: AddressType,
|
||||
walletNameOpt: Option[String] = None
|
||||
walletName: String = BitcoindRpcClient.DEFAULT_WALLET_NAME
|
||||
): Future[MultiSigResultPostV20] = {
|
||||
bitcoindCall[MultiSigResultPostV20](
|
||||
"createmultisig",
|
||||
|
@ -83,7 +83,7 @@ trait V20MultisigRpc extends MultisigRpc { self: Client =>
|
|||
Json.toJson(keys.map(_.hex)),
|
||||
Json.toJson(addressType)
|
||||
),
|
||||
uriExtensionOpt = walletNameOpt.map(walletExtension)
|
||||
uriExtensionOpt = Some(walletExtension(walletName))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,48 @@
|
|||
package org.bitcoins.rpc.client.v26
|
||||
|
||||
import org.apache.pekko.actor.ActorSystem
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.config.BitcoindInstance
|
||||
|
||||
import scala.concurrent.Future
|
||||
import scala.util.Try
|
||||
|
||||
class BitcoindV26RpcClient(override val instance: BitcoindInstance)(implicit
|
||||
actorSystem: ActorSystem
|
||||
) extends BitcoindRpcClient(instance) {
|
||||
|
||||
override lazy val version: Future[BitcoindVersion] =
|
||||
Future.successful(BitcoindVersion.V26)
|
||||
}
|
||||
|
||||
object BitcoindV26RpcClient {
|
||||
|
||||
/** Creates an RPC client from the given instance.
|
||||
*
|
||||
* Behind the scenes, we create an actor system for you. You can use
|
||||
* `withActorSystem` if you want to manually specify an actor system for the
|
||||
* RPC client.
|
||||
*/
|
||||
def apply(instance: BitcoindInstance): BitcoindV26RpcClient = {
|
||||
implicit val system: ActorSystem =
|
||||
ActorSystem.create(BitcoindRpcClient.ActorSystemName)
|
||||
withActorSystem(instance)
|
||||
}
|
||||
|
||||
/** Creates an RPC client from the given instance, together with the given
|
||||
* actor system. This is for advanced users, where you need fine grained
|
||||
* control over the RPC client.
|
||||
*/
|
||||
def withActorSystem(instance: BitcoindInstance)(implicit
|
||||
system: ActorSystem
|
||||
): BitcoindV26RpcClient =
|
||||
new BitcoindV26RpcClient(instance)(system)
|
||||
|
||||
def fromUnknownVersion(
|
||||
rpcClient: BitcoindRpcClient
|
||||
): Try[BitcoindV26RpcClient] =
|
||||
Try {
|
||||
new BitcoindV26RpcClient(rpcClient.instance)(rpcClient.system)
|
||||
}
|
||||
|
||||
}
|
|
@ -38,6 +38,10 @@ class ServiceIdentifierTest extends BitcoinSUnitTest {
|
|||
assert(ServiceIdentifier.NODE_NETWORK_LIMITED.nodeNetworkLimited)
|
||||
}
|
||||
|
||||
it must "parse P2P_V2" in {
|
||||
assert(ServiceIdentifier.NODE_P2P_V2.nodeP2PV2)
|
||||
}
|
||||
|
||||
it must "correctly get a ServiceIdentifier from string" in {
|
||||
assert(
|
||||
ServiceIdentifier.fromString("NETWORK") == ServiceIdentifier.NODE_NETWORK
|
||||
|
@ -63,6 +67,10 @@ class ServiceIdentifierTest extends BitcoinSUnitTest {
|
|||
assert(
|
||||
ServiceIdentifier.fromString("XTHIN") == ServiceIdentifier.NODE_XTHIN
|
||||
)
|
||||
|
||||
assert(
|
||||
ServiceIdentifier.fromString("P2P_V2") == ServiceIdentifier.NODE_P2P_V2
|
||||
)
|
||||
assertThrows[IllegalArgumentException](
|
||||
ServiceIdentifier.fromString("this is invalid")
|
||||
)
|
||||
|
|
|
@ -86,11 +86,14 @@ sealed abstract class ServiceIdentifier extends NetworkElement {
|
|||
*/
|
||||
lazy val nodeNetworkLimited: Boolean = reversedBits(10) // 1 << 10
|
||||
|
||||
lazy val nodeP2PV2: Boolean = reversedBits(11) // 1 << 1
|
||||
|
||||
override def toString: String = {
|
||||
val innerText =
|
||||
if (nodeNone) "none"
|
||||
else
|
||||
s"network=$nodeNetwork,compactFilters=$nodeCompactFilters,getUtxo=$nodeGetUtxo,bloom=$nodeBloom,witness=$nodeWitness,xthin=$nodeXthin,networkLimited=$nodeNetworkLimited"
|
||||
s"network=$nodeNetwork,compactFilters=$nodeCompactFilters,getUtxo=$nodeGetUtxo,bloom=$nodeBloom," +
|
||||
s"witness=$nodeWitness,xthin=$nodeXthin,networkLimited=$nodeNetworkLimited,v2transport=$nodeP2PV2"
|
||||
s"ServiceIdentifier($innerText)"
|
||||
}
|
||||
|
||||
|
@ -165,13 +168,15 @@ object ServiceIdentifier
|
|||
*/
|
||||
val NODE_NETWORK_LIMITED: ServiceIdentifier = ServiceIdentifier(1 << 10)
|
||||
|
||||
val NODE_P2P_V2: ServiceIdentifier = ServiceIdentifier(1 << 11)
|
||||
|
||||
private case class ServiceIdentifierImpl(num: UInt64)
|
||||
extends ServiceIdentifier
|
||||
|
||||
def fromBytes(bytes: ByteVector): ServiceIdentifier =
|
||||
RawServiceIdentifierSerializer.read(bytes)
|
||||
|
||||
override def fromString(string: String): ServiceIdentifier =
|
||||
override def fromString(string: String): ServiceIdentifier = {
|
||||
string match {
|
||||
case "NETWORK" => NODE_NETWORK
|
||||
case "NETWORK_LIMITED" => NODE_NETWORK_LIMITED
|
||||
|
@ -180,11 +185,13 @@ object ServiceIdentifier
|
|||
case "GETUTXO" => NODE_GET_UTXO
|
||||
case "COMPACT_FILTERS" => NODE_COMPACT_FILTERS
|
||||
case "XTHIN" => NODE_XTHIN
|
||||
case "P2P_V2" => NODE_P2P_V2
|
||||
case _: String =>
|
||||
throw new IllegalArgumentException(
|
||||
s""""$string" does not represent a ServiceIdentifier"""
|
||||
s"$string does not represent a ServiceIdentifier"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
def apply(num: BigInt): ServiceIdentifier = ServiceIdentifier(UInt64(num))
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.bitcoins.rpc.BitcoindException
|
|||
import org.bitcoins.rpc.client.common.BitcoindVersion._
|
||||
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
|
||||
import org.bitcoins.rpc.client.v25.BitcoindV25RpcClient
|
||||
import org.bitcoins.rpc.client.v26.BitcoindV26RpcClient
|
||||
import org.bitcoins.rpc.config._
|
||||
import org.bitcoins.rpc.util.{NodePair, RpcUtil}
|
||||
import org.bitcoins.testkit.util.{BitcoindRpcTestClient, FileUtil, TorUtil}
|
||||
|
@ -102,6 +103,7 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
|regtest=1
|
||||
|server=1
|
||||
|daemon=$isDaemon
|
||||
|v2transport=1
|
||||
|[regtest]
|
||||
|rpcuser=$username
|
||||
|rpcpassword=$pass
|
||||
|
@ -176,7 +178,7 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
version match {
|
||||
// default to newest version
|
||||
case Unknown => getBinary(BitcoindVersion.newest, binaryDirectory)
|
||||
case known @ (V25) =>
|
||||
case known @ (V25 | V26) =>
|
||||
val fileList = Files
|
||||
.list(binaryDirectory)
|
||||
.iterator()
|
||||
|
@ -256,6 +258,22 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
binaryDirectory = binaryDirectory
|
||||
)
|
||||
|
||||
def v26Instance(
|
||||
port: Int = RpcUtil.randomPort,
|
||||
rpcPort: Int = RpcUtil.randomPort,
|
||||
zmqConfig: ZmqConfig = RpcUtil.zmqConfig,
|
||||
pruneMode: Boolean = false,
|
||||
binaryDirectory: Path = BitcoindRpcTestClient.sbtBinaryDirectory
|
||||
)(implicit system: ActorSystem): BitcoindInstanceLocal =
|
||||
instance(
|
||||
port = port,
|
||||
rpcPort = rpcPort,
|
||||
zmqConfig = zmqConfig,
|
||||
pruneMode = pruneMode,
|
||||
versionOpt = Some(BitcoindVersion.V26),
|
||||
binaryDirectory = binaryDirectory
|
||||
)
|
||||
|
||||
/** Gets an instance of bitcoind with the given version */
|
||||
def getInstance(
|
||||
bitcoindVersion: BitcoindVersion,
|
||||
|
@ -274,6 +292,14 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
pruneMode,
|
||||
binaryDirectory = binaryDirectory
|
||||
)
|
||||
case BitcoindVersion.V26 =>
|
||||
BitcoindRpcTestUtil.v26Instance(
|
||||
port,
|
||||
rpcPort,
|
||||
zmqConfig,
|
||||
pruneMode,
|
||||
binaryDirectory = binaryDirectory
|
||||
)
|
||||
case BitcoindVersion.Unknown =>
|
||||
sys.error(
|
||||
s"Could not create a bitcoind version with version=${BitcoindVersion.Unknown}"
|
||||
|
@ -286,10 +312,8 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
)(implicit ec: ExecutionContext): Future[Unit] = {
|
||||
val startedServersF = Future.traverse(servers) { server =>
|
||||
server.start().flatMap { res =>
|
||||
val descriptors = true
|
||||
val createWalletF = for {
|
||||
_ <- res.createWallet(BitcoindRpcClient.DEFAULT_WALLET_NAME,
|
||||
descriptors = descriptors)
|
||||
_ <- res.createWallet(BitcoindRpcClient.DEFAULT_WALLET_NAME)
|
||||
} yield res
|
||||
|
||||
createWalletF
|
||||
|
@ -615,6 +639,9 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
|
|||
case BitcoindVersion.V25 =>
|
||||
BitcoindV25RpcClient.withActorSystem(
|
||||
BitcoindRpcTestUtil.v25Instance())
|
||||
case BitcoindVersion.V26 =>
|
||||
BitcoindV26RpcClient.withActorSystem(
|
||||
BitcoindRpcTestUtil.v26Instance())
|
||||
}
|
||||
|
||||
// this is safe as long as this method is never
|
||||
|
|
Loading…
Add table
Reference in a new issue