2024 04 24 rm v24 (#5549)

* WIP

* Fix simulaterawtransaction test

* Remove unneeded AdressInfoResult data strutures for versions of bitcoind pre-v21

* Remove v24

* Remove support for v24 bitcoind from bitcoind-rpc.sbt

* Fix tests

* Fix UtilRpcTest

* Fix teardown of bitcoind

* scalafmt
This commit is contained in:
Chris Stewart 2024-04-26 11:58:55 -05:00 committed by GitHub
parent d23d7851b8
commit 5dc5cca9cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
22 changed files with 337 additions and 821 deletions

View File

@ -256,120 +256,6 @@ sealed trait AddressInfoResult extends WalletResult {
def hdseedid: Option[RipeMd160Digest]
}
case class AddressInfoResultPreV18(
address: BitcoinAddress,
scriptPubKey: ScriptPubKey,
ismine: Boolean,
iswatchonly: Boolean,
isscript: Boolean,
iswitness: Boolean,
iscompressed: Option[Boolean],
witness_version: Option[WitnessVersion],
witness_program: Option[String],
script: Option[ScriptType],
hex: Option[ScriptPubKey],
pubkeys: Option[Vector[ECPublicKey]],
sigsrequired: Option[Int],
pubkey: Option[ECPublicKey],
embedded: Option[EmbeddedResult],
label: String,
timestamp: Option[ZonedDateTime],
hdkeypath: Option[BIP32Path],
hdseedid: Option[RipeMd160Digest],
hdmasterkeyid: Option[RipeMd160Digest],
labels: Vector[LabelResult]
) extends AddressInfoResult
// The split into two case classes is to deal with the 22 param limit for case classes
case class AddressInfoResultPostV18(
address: BitcoinAddress,
scriptPubKey: ScriptPubKey,
isProps: AddressInfoResultPostV18.AddressInfoIsProps,
desc: String,
witness_version: Option[WitnessVersion],
witness_program: Option[String],
script: Option[ScriptType],
hex: Option[ScriptPubKey],
pubkeys: Option[Vector[ECPublicKey]],
sigsrequired: Option[Int],
pubkey: Option[ECPublicKey],
embedded: Option[EmbeddedResult],
label: String,
ischange: Boolean,
timestamp: Option[ZonedDateTime],
hdkeypath: Option[BIP32Path],
hdseedid: Option[RipeMd160Digest],
hdmasterfingerprint: Option[String],
labels: Vector[LabelResult]
) extends AddressInfoResult {
override def ismine: Boolean = isProps.ismine
def solvable: Boolean = isProps.solvable
override def iswatchonly: Boolean = isProps.iswatchonly
override def isscript: Boolean = isProps.isscript
override def iswitness: Boolean = isProps.iswitness
override def iscompressed: Option[Boolean] = isProps.iscompressed
}
object AddressInfoResultPostV18 {
case class AddressInfoIsProps(
ismine: Boolean,
solvable: Boolean,
iswatchonly: Boolean,
isscript: Boolean,
iswitness: Boolean,
iscompressed: Option[Boolean]
)
case class AddressInfoResultPostV18WithoutIsProps(
address: BitcoinAddress,
scriptPubKey: ScriptPubKey,
desc: String,
witness_version: Option[WitnessVersion],
witness_program: Option[String],
script: Option[ScriptType],
hex: Option[ScriptPubKey],
pubkeys: Option[Vector[ECPublicKey]],
sigsrequired: Option[Int],
pubkey: Option[ECPublicKey],
embedded: Option[EmbeddedResult],
label: String,
ischange: Boolean,
timestamp: Option[ZonedDateTime],
hdkeypath: Option[BIP32Path],
hdseedid: Option[RipeMd160Digest],
hdmasterfingerprint: Option[String],
labels: Vector[LabelResult]
)
def apply(
info: AddressInfoResultPostV18WithoutIsProps,
isProps: AddressInfoIsProps
): AddressInfoResultPostV18 = {
AddressInfoResultPostV18(
address = info.address,
scriptPubKey = info.scriptPubKey,
isProps = isProps,
desc = info.desc,
witness_version = info.witness_version,
witness_program = info.witness_program,
script = info.script,
hex = info.hex,
pubkeys = info.pubkeys,
sigsrequired = info.sigsrequired,
pubkey = info.pubkey,
embedded = info.embedded,
label = info.label,
ischange = info.ischange,
timestamp = info.timestamp,
hdkeypath = info.hdkeypath,
hdseedid = info.hdseedid,
hdmasterfingerprint = info.hdmasterfingerprint,
labels = info.labels
)
}
}
case class AddressInfoResultPostV21(
address: BitcoinAddress,
scriptPubKey: ScriptPubKey,

View File

@ -515,27 +515,6 @@ object JsonSerializers {
implicit val embeddedResultReads: Reads[EmbeddedResult] =
Json.reads[EmbeddedResult]
implicit val addressInfoResultPreV18Reads: Reads[AddressInfoResultPreV18] =
Json.reads[AddressInfoResultPreV18]
implicit val addressInfoResultPostV18Reads
: Reads[AddressInfoResultPostV18] = {
Reads[AddressInfoResultPostV18] { json =>
for {
isProps <-
Json.reads[AddressInfoResultPostV18.AddressInfoIsProps].reads(json)
infoWithoutProps <-
Json
.reads[
AddressInfoResultPostV18.AddressInfoResultPostV18WithoutIsProps
]
.reads(json)
} yield {
AddressInfoResultPostV18(infoWithoutProps, isProps)
}
}
}
implicit val addressInfoResultPostV21Reads
: Reads[AddressInfoResultPostV21] = {
Reads[AddressInfoResultPostV21] { json =>

View File

@ -6,9 +6,9 @@ import org.bitcoins.testkit.util.BitcoindRpcTest
class BitcoindVersionTest extends BitcoindRpcTest {
behavior of "BitcoindVersion"
it should "return version 24" in {
val version = BitcoindVersion.fromNetworkVersion(240100)
assert(version.equals(BitcoindVersion.V24))
it should "return version 25" in {
val version = BitcoindVersion.fromNetworkVersion(250100)
assert(version.equals(BitcoindVersion.V25))
}
}

View File

@ -2,6 +2,7 @@ package org.bitcoins.rpc.common
import org.bitcoins.core.currency.Bitcoins
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.BitcoinAddress
import org.bitcoins.core.protocol.script.ScriptSignature
import org.bitcoins.core.protocol.transaction.{
TransactionInput,
@ -193,4 +194,15 @@ class MempoolRpcTest extends BitcoindFixturesCachedPairNewest {
_ <- client.saveMemPool()
} yield assert(regTest.list().contains("mempool.dat"))
}
it should "get tx spending prev out" in { nodePair =>
val client = nodePair.node1
val junkAddress: BitcoinAddress =
BitcoinAddress("2NFyxovf6MyxfHqtVjstGzs6HeLqv92Nq4U")
for {
txid <- client.sendToAddress(junkAddress, Bitcoins.one)
tx <- client.getRawTransaction(txid).map(_.hex)
spending <- client.getTxSpendingPrevOut(tx.inputs.head.previousOutput)
} yield assert(spending.spendingtxid.contains(txid))
}
}

View File

@ -1,42 +0,0 @@
package org.bitcoins.rpc.common
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.AddressType
import org.bitcoins.core.protocol.P2PKHAddress
import org.bitcoins.crypto.ECPrivateKey
import org.bitcoins.testkit.rpc.BitcoindFixturesCachedPairNewest
class MessageRpcTest extends BitcoindFixturesCachedPairNewest {
behavior of "MessageRpc"
it should "be able to sign a message and verify that signature" in {
nodePair =>
val client = nodePair.node1
val message = "Never gonna give you up\nNever gonna let you down\n..."
for {
address <- client.getNewAddress(addressType = AddressType.Legacy)
signature <-
client.signMessage(address.asInstanceOf[P2PKHAddress], message)
validity <-
client
.verifyMessage(address.asInstanceOf[P2PKHAddress],
signature,
message)
} yield assert(validity)
}
it should "be able to sign a message with a private key and verify that signature" in {
nodePair =>
val message = "Never gonna give you up\nNever gonna let you down\n..."
val privKey = ECPrivateKey.freshPrivateKey
val address = P2PKHAddress(privKey.publicKey, networkParam)
val client = nodePair.node1
for {
signature <- client.signMessageWithPrivKey(
privKey.toPrivateKeyBytes(),
message
)
validity <- client.verifyMessage(address, signature, message)
} yield assert(validity)
}
}

View File

@ -4,11 +4,14 @@ import org.bitcoins.commons.jsonmodels.bitcoind.{
GetBlockWithTransactionsResultV22,
RpcOpts
}
import org.bitcoins.core.api.chain.db.BlockHeaderDbHelper
import org.bitcoins.core.currency.Bitcoins
import org.bitcoins.core.number._
import org.bitcoins.core.protocol.blockchain.RegTestNetChainParams
import org.bitcoins.core.protocol.script.ScriptSignature
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.crypto.DoubleSha256DigestBE
import org.bitcoins.testkit.chain.BlockHeaderHelper
import org.bitcoins.testkit.rpc.{
BitcoindFixturesCachedPairNewest,
BitcoindRpcTestUtil
@ -135,4 +138,13 @@ class MiningRpcTest extends BitcoindFixturesCachedPairNewest {
hps <- client.getNetworkHashPS()
} yield assert(hps > 0)
}
it should "successfully submit a header" in { case nodePair =>
val client = nodePair.node1
val genesisHeader = RegTestNetChainParams.genesisBlock.blockHeader
val genesisHeaderDb =
BlockHeaderDbHelper.fromBlockHeader(height = 1, BigInt(0), genesisHeader)
val nextHeader = BlockHeaderHelper.buildNextHeader(genesisHeaderDb)
client.submitHeader(nextHeader.blockHeader).map(_ => succeed)
}
}

View File

@ -70,4 +70,21 @@ class NodeRpcTest extends BitcoindFixturesFundedCachedNewest {
assert(!helpHelp.isEmpty)
}
}
it should "be able to get network info" in { freshClient =>
for {
info <- freshClient.getNetworkInfo
} yield {
assert(info.networkactive)
assert(info.localrelay)
}
}
it should "get node address given a null parameter" in { client =>
val nodeF = client.getNodeAddresses()
nodeF.map { result =>
assert(result.isEmpty)
}
}
}

View File

@ -0,0 +1,126 @@
package org.bitcoins.rpc.common
import org.bitcoins.asyncutil.AsyncUtil
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.AddressType
import org.bitcoins.core.protocol.{BitcoinAddress, P2PKHAddress}
import org.bitcoins.core.protocol.script.descriptor.Descriptor
import org.bitcoins.crypto.ECPrivateKey
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.testkit.rpc.BitcoindFixturesCachedPairNewest
import scala.concurrent.Future
class UtilRpcTest extends BitcoindFixturesCachedPairNewest {
behavior of "UtilRpc"
it should "be able to sign a message and verify that signature" in {
nodePair =>
val client = nodePair.node1
val message = "Never gonna give you up\nNever gonna let you down\n..."
for {
address <- client.getNewAddress(addressType = AddressType.Legacy)
signature <-
client.signMessage(address.asInstanceOf[P2PKHAddress], message)
validity <-
client
.verifyMessage(address.asInstanceOf[P2PKHAddress],
signature,
message)
} yield assert(validity)
}
it should "be able to sign a message with a private key and verify that signature" in {
nodePair =>
val message = "Never gonna give you up\nNever gonna let you down\n..."
val privKey = ECPrivateKey.freshPrivateKey
val address = P2PKHAddress(privKey.publicKey, networkParam)
val client = nodePair.node1
for {
signature <- client.signMessageWithPrivKey(
privKey.toPrivateKeyBytes(),
message
)
validity <- client.verifyMessage(address, signature, message)
} yield assert(validity)
}
it should "get index info" in { nodePair =>
val client = nodePair.node1
def indexSynced(client: BitcoindRpcClient): Future[Boolean] = {
for {
blockCount <- client.getBlockCount()
indexes <- client.getIndexInfo
} yield {
indexes("txindex").best_block_height == blockCount && indexes(
"basic block filter index"
).best_block_height == blockCount
}
}
for {
_ <- AsyncUtil.retryUntilSatisfiedF(() => indexSynced(client))
indexes <- client.getIndexInfo
blockCount <- client.getBlockCount()
} yield {
val txIndexInfo = indexes("txindex")
assert(txIndexInfo.synced)
assert(txIndexInfo.best_block_height == blockCount)
val blockFilterIndexInfo = indexes("basic block filter index")
assert(blockFilterIndexInfo.synced)
assert(blockFilterIndexInfo.best_block_height == blockCount)
}
}
it should "return active rpc commands" in { nodePair =>
val client = nodePair.node1
val generatedF =
client.getNewAddress.flatMap(addr => client.generateToAddress(100, addr))
val rpcinfoF =
generatedF.flatMap(_ => client.getRpcInfo())
rpcinfoF.map { result =>
assert(result.active_commands.length == 1)
}
}
it should "derive addresses from a descriptor" in { case nodePair =>
val client = nodePair.node1
val str0 =
"wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)#t6wfjs64"
val descriptor0 = Descriptor.fromString(str0)
assert(descriptor0.toString == str0)
val addresses0F =
client.deriveAddresses(descriptor0, None).map(_.addresses)
val expected0 =
Vector("bcrt1qjqmxmkpmxt80xz4y3746zgt0q3u3ferr34acd5").map(
BitcoinAddress.fromString
)
val assert0 = addresses0F.map { addresses =>
assert(addresses == expected0)
}
val str1 =
"wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)#kft60nuy"
val descriptor1 = Descriptor.fromString(str1)
assert(descriptor1.toString == str1)
val addresses1F =
client.deriveAddresses(descriptor1, Some(Vector(0, 2))).map(_.addresses)
val expected1 =
Vector(
"bcrt1qjqmxmkpmxt80xz4y3746zgt0q3u3ferr34acd5",
"bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy",
"bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"
)
.map(BitcoinAddress.fromString)
val assert1 = assert0.flatMap(_ =>
addresses1F.map { addresses =>
assert(addresses == expected1)
})
assert1
}
}

View File

@ -6,6 +6,7 @@ import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.{
WalletFlag
}
import org.bitcoins.commons.jsonmodels.bitcoind.{
AddressInfoResultPostV21,
DecodeScriptResultV22,
DescriptorsResult,
GetWalletInfoResultPostV22
@ -15,6 +16,7 @@ import org.bitcoins.core.currency.{Bitcoins, CurrencyUnit, Satoshis}
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.script.descriptor.{
Descriptor,
P2SHDescriptor,
P2WPKHDescriptor
}
@ -726,7 +728,7 @@ class WalletRpcTest extends BitcoindFixturesCachedPairNewest {
for {
_ <- client.unloadWallet(BitcoindRpcClient.DEFAULT_WALLET_NAME)
_ <- client.createWallet(walletName, descriptors = true)
_ <- client.importDescriptor(imp, Some(walletName))
_ <- client.importDescriptor(imp, walletName)
decoded <- client.decodeScript(p2wpkh)
_ <- client.unloadWallet(walletName)
_ <- client.loadWallet(BitcoindRpcClient.DEFAULT_WALLET_NAME)
@ -738,6 +740,96 @@ class WalletRpcTest extends BitcoindFixturesCachedPairNewest {
}
}
it should "simulate a transaction" in { nodePair =>
val client = nodePair.node1
val junkAddress: BitcoinAddress =
BitcoinAddress("2NFyxovf6MyxfHqtVjstGzs6HeLqv92Nq4U")
for {
txid <- client.sendToAddress(junkAddress, Bitcoins.one)
tx <- client.getRawTransaction(txid).map(_.hex)
change <- client.simulateRawTransaction(tx)
} yield {
assert(change <= -Bitcoins.one)
} // 1 bitcoin + fees
}
it should "be able to validate a bitcoin address" in { case nodePair =>
val client = nodePair.node1
for {
address <- client.getNewAddress
validation <- client.validateAddress(address)
} yield assert(validation.isvalid)
}
it should "have extra address information" in { case nodePair =>
val client = nodePair.node1
for {
address <- client.getNewAddress
info <- client.getAddressInfo(address)
} yield {
info match {
case postV21Info: AddressInfoResultPostV21 =>
assert(postV21Info.address == address)
}
}
}
it should "analyze a descriptor" in { case nodePair =>
val client = nodePair.node1
val descriptor =
Descriptor.fromString(
"pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)#gn28ywm7"
)
val descriptorF = client.getDescriptorInfo(descriptor)
descriptorF.map { result =>
assert(result.descriptor == descriptor)
assert(result.isrange.==(false))
assert(result.issolvable.==(true))
assert(result.hasprivatekeys.==(false))
}
}
it must "importdescriptors" in { nodePair =>
val client = nodePair.node1
val str1 =
"wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)#kft60nuy"
val descriptor = Descriptor.fromString(str1)
val imp = DescriptorsResult(
desc = descriptor,
timestamp = Instant.now().getEpochSecond,
active = true,
internal = None,
range = Some(Vector(0, 2)),
next = None
)
val resultF =
client.importDescriptors(imports = Vector(imp))
for {
result <- resultF
_ = assert(result.forall(_.success))
firstAddress <- client.getNewAddress
secondAddress <- client.getNewAddress
// check it by deriving addresses externally
deriveAddresses <- client
.deriveAddresses(descriptor, Some(Vector(0, 1)))
.map(_.addresses)
} yield {
assert(Vector(firstAddress, secondAddress) == deriveAddresses)
}
}
it should "be able to get the address info for a given address" in {
case nodePair =>
val client = nodePair.node1
for {
addr <- client.getNewAddress
info <- client.getAddressInfo(addr)
} yield assert(info.address == addr)
}
def startClient(client: BitcoindRpcClient): Future[Unit] = {
BitcoindRpcTestUtil.startServers(Vector(client))
}

View File

@ -1,410 +0,0 @@
package org.bitcoins.rpc.v24
import org.bitcoins.asyncutil.AsyncUtil
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.{
AddressType,
WalletFlag
}
import org.bitcoins.commons.jsonmodels.bitcoind._
import org.bitcoins.core.api.chain.db.BlockHeaderDbHelper
import org.bitcoins.core.config.RegTest
import org.bitcoins.core.currency._
import org.bitcoins.core.gcs.{BlockFilter, FilterType}
import org.bitcoins.core.protocol.{Bech32mAddress, BitcoinAddress}
import org.bitcoins.core.protocol.blockchain.RegTestNetChainParams
import org.bitcoins.core.protocol.script.descriptor.Descriptor
import org.bitcoins.core.psbt.PSBT
import org.bitcoins.crypto.ECPublicKey
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
import org.bitcoins.rpc.client.v24.BitcoindV24RpcClient
import org.bitcoins.testkit.chain.BlockHeaderHelper
import org.bitcoins.testkit.rpc.{
BitcoindFixturesFundedCachedV24,
BitcoindRpcTestUtil
}
import java.io.File
import java.nio.file.Files
import java.time.Instant
import scala.concurrent.Future
class BitcoindV24RpcClientTest extends BitcoindFixturesFundedCachedV24 {
val junkAddress: BitcoinAddress =
BitcoinAddress("2NFyxovf6MyxfHqtVjstGzs6HeLqv92Nq4U")
behavior of "BitcoindV24RpcClient"
it should "get index info" in { client: BitcoindV24RpcClient =>
def indexSynced(client: BitcoindRpcClient): Future[Boolean] = {
client.getIndexInfo.map { indexes =>
indexes("txindex").best_block_height == 101 && indexes(
"basic block filter index"
).best_block_height == 101
}
}
for {
_ <- AsyncUtil.retryUntilSatisfiedF(() => indexSynced(client))
indexes <- client.getIndexInfo
} yield {
val txIndexInfo = indexes("txindex")
assert(txIndexInfo.synced)
assert(txIndexInfo.best_block_height == 101)
val blockFilterIndexInfo = indexes("basic block filter index")
assert(blockFilterIndexInfo.synced)
assert(blockFilterIndexInfo.best_block_height == 101)
}
}
it should "be able to start a V24 bitcoind instance" in {
client: BitcoindV24RpcClient =>
for {
v <- client.version
} yield assert(v == BitcoindVersion.V24)
}
it should "be able to get network info" in {
freshClient: BitcoindV24RpcClient =>
for {
info <- freshClient.getNetworkInfo
} yield {
assert(info.networkactive)
assert(info.localrelay)
}
}
it should "generate a bech32m address" in { client: BitcoindV24RpcClient =>
for {
address <- client.getNewAddress(addressType = AddressType.Bech32m)
} yield {
assert(address.isInstanceOf[Bech32mAddress])
}
}
it should "be able to validate a bitcoin address" in { case client =>
for {
address <- client.getNewAddress
validation <- client.validateAddress(address)
} yield assert(validation.isvalid)
}
it should "have extra address information" in { client =>
for {
address <- client.getNewAddress
info <- client.getAddressInfo(address)
} yield {
info match {
case _: AddressInfoResultPreV18 | _: AddressInfoResultPostV18 =>
fail("Was expecting AddressInfoResultPostV21")
case postV21Info: AddressInfoResultPostV21 =>
assert(postV21Info.address == address)
}
}
}
it should "return active rpc commands" in { client =>
val generatedF =
client.getNewAddress.flatMap(addr => client.generateToAddress(100, addr))
val rpcinfoF =
generatedF.flatMap(_ => client.getRpcInfo())
rpcinfoF.map { result =>
assert(result.active_commands.length == 1)
}
}
it should "analyze a descriptor" in { client =>
val descriptor =
Descriptor.fromString(
"pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)#gn28ywm7"
)
val descriptorF = client.getDescriptorInfo(descriptor)
descriptorF.map { result =>
assert(result.descriptor == descriptor)
assert(result.isrange.==(false))
assert(result.issolvable.==(true))
assert(result.hasprivatekeys.==(false))
}
}
it should "get node address given a null parameter" in { client =>
val nodeF = client.getNodeAddresses()
nodeF.map { result =>
assert(result.isEmpty)
}
}
it should "successfully submit a header" in { client =>
val genesisHeader = RegTestNetChainParams.genesisBlock.blockHeader
val genesisHeaderDb =
BlockHeaderDbHelper.fromBlockHeader(height = 1, BigInt(0), genesisHeader)
val nextHeader = BlockHeaderHelper.buildNextHeader(genesisHeaderDb)
client.submitHeader(nextHeader.blockHeader).map(_ => succeed)
}
it should "simulate a transaction" in { client =>
for {
txid <- client.sendToAddress(junkAddress, Bitcoins.one)
tx <- client.getRawTransaction(txid).map(_.hex)
change <- client.simulateRawTransaction(tx)
} yield assert(change <= -Bitcoins.one) // 1 bitcoin + fees
}
it should "get tx spending prev out" in { client =>
for {
txid <- client.sendToAddress(junkAddress, Bitcoins.one)
tx <- client.getRawTransaction(txid).map(_.hex)
spending <- client.getTxSpendingPrevOut(tx.inputs.head.previousOutput)
} yield assert(spending.spendingtxid.contains(txid))
}
it should "derive addresses from a descriptor" in { client =>
val str0 =
"wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/0)#t6wfjs64"
val descriptor0 = Descriptor.fromString(str0)
assert(descriptor0.toString == str0)
val addresses0F =
client.deriveAddresses(descriptor0, None).map(_.addresses)
val expected0 =
Vector("bcrt1qjqmxmkpmxt80xz4y3746zgt0q3u3ferr34acd5").map(
BitcoinAddress.fromString
)
val assert0 = addresses0F.map { addresses =>
assert(addresses == expected0)
}
val str1 =
"wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)#kft60nuy"
val descriptor1 = Descriptor.fromString(str1)
assert(descriptor1.toString == str1)
val addresses1F =
client.deriveAddresses(descriptor1, Some(Vector(0, 2))).map(_.addresses)
val expected1 =
Vector(
"bcrt1qjqmxmkpmxt80xz4y3746zgt0q3u3ferr34acd5",
"bcrt1qhku5rq7jz8ulufe2y6fkcpnlvpsta7rq4442dy",
"bcrt1qpgptk2gvshyl0s9lqshsmx932l9ccsv265tvaq"
)
.map(BitcoinAddress.fromString)
val assert1 = assert0.flatMap(_ =>
addresses1F.map { addresses =>
assert(addresses == expected1)
})
assert1
}
it must "importdescriptors" in { client =>
val str1 =
"wpkh(tprv8ZgxMBicQKsPd7Uf69XL1XwhmjHopUGep8GuEiJDZmbQz6o58LninorQAfcKZWARbtRtfnLcJ5MQ2AtHcQJCCRUcMRvmDUjyEmNUWwx8UbK/1/1/*)#kft60nuy"
val descriptor = Descriptor.fromString(str1)
val imp = DescriptorsResult(
desc = descriptor,
timestamp = Instant.now().getEpochSecond,
active = true,
internal = None,
range = Some(Vector(0, 2)),
next = None
)
val resultF =
client.importDescriptors(imports = Vector(imp), walletNameOpt = None)
for {
result <- resultF
_ = assert(result.forall(_.success))
firstAddress <- client.getNewAddress
secondAddress <- client.getNewAddress
// check it by deriving addresses externally
deriveAddresses <- client
.deriveAddresses(descriptor, Some(Vector(0, 1)))
.map(_.addresses)
} yield {
assert(Vector(firstAddress, secondAddress) == deriveAddresses)
}
}
it should "be able to get the address info for a given address" in {
client: BitcoindV24RpcClient =>
for {
addr <- client.getNewAddress
info <- client.getAddressInfo(addr)
} yield assert(info.address == addr)
}
it should "get a block filter given a block hash" in {
client: BitcoindV24RpcClient =>
for {
blocks <- client.generate(1)
blockHashBE = blocks.head
blockFilter <- client.getBlockFilter(blockHashBE, FilterType.Basic)
block <- client.getBlockRaw(blockHashBE)
prevOuts = block.transactions
.filterNot(_.isCoinbase)
.flatMap(_.inputs.map(_.previousOutput))
fundingOutputs <- Future.traverse(prevOuts) { outpoint =>
client
.getTransaction(outpoint.txIdBE)
.map(_.hex.outputs(outpoint.idx))
}
prevFilter <- client.getBlockFilter(
block.blockHeader.previousBlockHashBE,
FilterType.Basic
)
} yield {
val pubKeys = fundingOutputs.map(_.scriptPubKey).toVector
val filter = BlockFilter(block, pubKeys)
assert(filter.hash == blockFilter.filter.hash)
assert(
blockFilter.header == filter
.getHeader(prevFilter.header.flip)
.hashBE
)
}
}
it should "be able to get the balances" in { client: BitcoindV24RpcClient =>
for {
immatureBalance <- client.getBalances
_ <- client.generate(1)
newImmatureBalance <- client.getBalances
} yield {
val blockReward = 50
assert(immatureBalance.mine.immature.toBigDecimal >= 0)
assert(
immatureBalance.mine.trusted.toBigDecimal + blockReward == newImmatureBalance.mine.trusted.toBigDecimal
)
}
}
it should "be able to get blockchain info" in {
client: BitcoindV24RpcClient =>
for {
info <- client.getBlockChainInfo
bestHash <- client.getBestBlockHash()
} yield {
assert(info.isInstanceOf[GetBlockChainInfoResultPostV23])
val postV23Info = info.asInstanceOf[GetBlockChainInfoResultPostV23]
assert(postV23Info.chain == RegTest)
assert(postV23Info.bestblockhash == bestHash)
}
}
it should "be able to get a block with verbose transactions" in {
client: BitcoindRpcClient =>
for {
blocks <- client.generate(2)
block <- client.getBlockWithTransactions(blocks(1))
} yield {
assert(block.hash == blocks(1))
assert(block.tx.length == 1)
val tx = block.tx.head
assert(tx.vout.head.n == 0)
}
}
it should "be able to set the wallet flag 'avoid_reuse'" in {
client: BitcoindV24RpcClient =>
for {
unspentPre <- client.listUnspent
result <- client.setWalletFlag(WalletFlag.AvoidReuse, value = true)
unspentPost <- client.listUnspent
} yield {
assert(result.flag_name == "avoid_reuse")
assert(result.flag_state)
assert(unspentPre.forall(utxo => utxo.reused.isEmpty))
assert(unspentPost.forall(utxo => utxo.reused.isDefined))
}
}
it should "create a wallet with a passphrase" in {
client: BitcoindV24RpcClient =>
for {
_ <- client.createWallet("suredbits", passphrase = "stackingsats")
wallets <- client.listWallets
} yield {
assert(wallets.contains("suredbits"))
}
}
it should "check to see if the utxoUpdate input has been updated" in {
client: BitcoindV24RpcClient =>
val descriptor =
"pk(0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798)"
val psbt =
PSBT.fromBase64(
"cHNidP8BACoCAAAAAAFAQg8AAAAAABepFG6Rty1Vk+fUOR4v9E6R6YXDFkHwhwAAAAAAAA=="
)
for {
result <- client.utxoUpdatePsbt(psbt, Seq(descriptor))
} yield {
assert(result == psbt)
}
}
it should "correct create multisig and get its descriptor" in {
client: BitcoindV24RpcClient =>
val pubKey1 = ECPublicKey.freshPublicKey
val pubKey2 = ECPublicKey.freshPublicKey
for {
multiSigResult <- client.createMultiSig(
2,
Vector(pubKey1, pubKey2),
AddressType.Bech32
)
} yield {
// just validate we are able to receive a sane descriptor
// no need to check checksum
assert(
multiSigResult.descriptor.startsWith(
s"wsh(multi(2,${pubKey1.hex},${pubKey2.hex}))#"
)
)
}
}
it should "correctly dump tx out set" in { client: BitcoindV24RpcClient =>
for {
hash <- client.getBestBlockHash()
height <- client.getBestHashBlockHeight()
result <- client.dumpTxOutSet(new File("utxo.dat").toPath)
} 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)
}
}
it should "correct generate to a descriptor" in {
client: BitcoindV24RpcClient =>
// 2-of-2 multisig descriptor
val descriptor =
"sh(sortedmulti(2,023f720438186fbdfde0c0a403e770a0f32a2d198623a8a982c47b621f8b307640,03ed261094d609d5e02ba6553c2d91e4fd056006ce2fe64aace72b69cb5be3ab9c))#nj9wx7up"
val numBlocks = 10
for {
hashes <- client.generateToDescriptor(numBlocks, descriptor)
} yield assert(hashes.size == numBlocks)
}
it should "be able to get utxo info" in { client: BitcoindRpcClient =>
for {
block <- BitcoindRpcTestUtil.getFirstBlock(client)
info1 <- client.getTxOut(block.tx.head.txid, 0)
} yield assert(info1.coinbase)
}
}

View File

@ -23,7 +23,7 @@ TaskKeys.downloadBitcoind := {
}
val versions =
List("25.2","24.2")
List("25.2")
logger.debug(
s"(Maybe) downloading Bitcoin Core binaries for versions: ${versions.mkString(",")}")
@ -94,24 +94,18 @@ TaskKeys.downloadBitcoind := {
val expectedHash =
if (Properties.isLinux)
Map(
"25.2" -> "8d8c387e597e0edfc256f0bbace1dac3ad1ebf4a3c06da3e2975fda333817dea",
"24.2" -> "7540d6e34c311e355af2fd76e5eee853b76c291978d6b5ebb555c7877e9de38d",
"25.2" -> "8d8c387e597e0edfc256f0bbace1dac3ad1ebf4a3c06da3e2975fda333817dea"
)
else if (Properties.isMac)
Map(
"25.2" -> (if (System.getProperty("os.arch") == "aarch64")
"f55b394eebaa11d4b717d68aad9f75b824aaf3a7841dac7c26b1ef3d6d2915f5"
else
"e06ba379f6039ca99bc32d3e7974d420a31363498936f88aac7bab6f239de0f5"),
"24.2" -> (if (System.getProperty("os.arch") == "aarch64")
"ae6f5f0cb4079005c32695711ef78b26a26c4c547ceb593b3626059626530a5d"
else
"b1b21455c339b2daf0998bfad17d0741d967c3c81db040bb5f73234168526d29")
"e06ba379f6039ca99bc32d3e7974d420a31363498936f88aac7bab6f239de0f5")
)
else if (Properties.isWin)
Map(
"25.2" -> "c2ac84f55ee879caefd4414868d318a741c52a7286da190bf7233d86a2ffca69",
"24.2" -> "544436bc9d5ce017e679bbccfe8a4928fbc840b414ee0240db8c3523ba54340a",
"25.2" -> "c2ac84f55ee879caefd4414868d318a741c52a7286da190bf7233d86a2ffca69"
)
else sys.error(s"Unsupported OS: ${Properties.osName}")

View File

@ -16,7 +16,6 @@ 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.v24.BitcoindV24RpcClient
import org.bitcoins.rpc.client.v25.BitcoindV25RpcClient
import org.bitcoins.rpc.config._
@ -344,7 +343,6 @@ object BitcoindRpcClient {
system: ActorSystem
): BitcoindRpcClient = {
val bitcoind = version match {
case BitcoindVersion.V24 => BitcoindV24RpcClient.withActorSystem(instance)
case BitcoindVersion.V25 => BitcoindV25RpcClient.withActorSystem(instance)
case BitcoindVersion.Unknown =>
sys.error(
@ -372,14 +370,10 @@ object BitcoindVersion
val newest: BitcoindVersion = V25
val standard: Vector[BitcoindVersion] =
Vector(V25, V24)
Vector(V25)
val known: Vector[BitcoindVersion] = standard
case object V24 extends BitcoindVersion {
override def toString: String = "v24"
}
case object V25 extends BitcoindVersion {
override def toString: String = "v25"
}
@ -402,7 +396,7 @@ object BitcoindVersion
def fromNetworkVersion(int: Int): BitcoindVersion = {
// need to translate the int 210100 (as an example) to a BitcoindVersion
int.toString.substring(0, 2) match {
case "24" => V24
case "25" => V25
case _ =>
logger.warn(
s"Unsupported Bitcoin Core version: $int. The latest supported version is ${BitcoindVersion.newest}"

View File

@ -49,20 +49,20 @@ trait DescriptorRpc {
*/
def importDescriptors(
imports: Vector[DescriptorsResult],
walletNameOpt: Option[String]
walletName: String = BitcoindRpcClient.DEFAULT_WALLET_NAME
): Future[Vector[ImportDescriptorResult]] = {
bitcoindCall[Vector[ImportDescriptorResult]](
"importdescriptors",
List(Json.toJson(imports)),
uriExtensionOpt = walletNameOpt.map(walletExtension)
uriExtensionOpt = Some(walletExtension(walletName))
)
}
def importDescriptor(
imp: DescriptorsResult,
walletNameOpt: Option[String]
walletName: String = BitcoindRpcClient.DEFAULT_WALLET_NAME
): Future[ImportDescriptorResult] = {
importDescriptors(Vector(imp), walletNameOpt).map(_.head)
importDescriptors(Vector(imp), walletName).map(_.head)
}
def listDescriptors(): Future[ListDescriptorsResult] = {

View File

@ -3,10 +3,10 @@ package org.bitcoins.rpc.client.common
import org.bitcoins.commons.jsonmodels.bitcoind._
import org.bitcoins.commons.serializers.JsonReaders._
import org.bitcoins.commons.serializers.JsonSerializers._
import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutPoint}
import org.bitcoins.crypto.{DoubleSha256Digest, DoubleSha256DigestBE}
import org.bitcoins.rpc.BitcoindException
import play.api.libs.json.{JsBoolean, JsString, Json}
import play.api.libs.json.{JsArray, JsBoolean, JsString, Json}
import scala.concurrent.Future
@ -138,4 +138,23 @@ trait MempoolRpc { self: Client =>
List(Json.toJson(transaction), Json.toJson(maxFeeRate))
)
}
def getTxSpendingPrevOut(
prevout: TransactionOutPoint
): Future[GetTxSpendingPrevOutResult] = {
getTxSpendingPrevOut(Vector(prevout)).map(_.head)
}
def getTxSpendingPrevOut(
prevouts: Vector[TransactionOutPoint]
): Future[Vector[GetTxSpendingPrevOutResult]] = {
val json = JsArray(prevouts.map { prev =>
Json.obj("txid" -> prev.txIdBE.hex, "vout" -> prev.vout.toLong)
})
bitcoindCall[Vector[GetTxSpendingPrevOutResult]](
"gettxspendingprevout",
List(json)
)
}
}

View File

@ -24,7 +24,7 @@ trait UtilRpc { self: Client =>
}
def decodeScript(script: ScriptPubKey): Future[DecodeScriptResult] = {
self.version.flatMap { case V25 | V24 | Unknown =>
self.version.flatMap { case V25 | Unknown =>
bitcoindCall[DecodeScriptResultV22](
"decodescript",
List(Json.toJson(script))
@ -34,18 +34,17 @@ trait UtilRpc { self: Client =>
}
def getIndexInfo: Future[Map[String, IndexInfoResult]] = {
version.flatMap { case V25 | V24 | Unknown =>
version.flatMap { case V25 | Unknown =>
bitcoindCall[Map[String, IndexInfoResult]]("getindexinfo")
}
}
def getIndexInfo(indexName: String): Future[IndexInfoResult] = {
version.flatMap { case V25 | V24 | Unknown =>
version.flatMap { case V25 | Unknown =>
bitcoindCall[Map[String, IndexInfoResult]](
"getindexinfo",
List(JsString(indexName))
).map(_.head._2)
}
}
}

View File

@ -160,13 +160,11 @@ trait WalletRpc { self: Client =>
def getWalletInfo(
walletName: String
): Future[GetWalletInfoResult] = {
self.version.flatMap {
case BitcoindVersion.V25 | BitcoindVersion.V24 |
BitcoindVersion.Unknown =>
bitcoindCall[GetWalletInfoResultPostV22](
"getwalletinfo",
uriExtensionOpt = Some(walletExtension(walletName))
)
self.version.flatMap { case BitcoindVersion.V25 | BitcoindVersion.Unknown =>
bitcoindCall[GetWalletInfoResultPostV22](
"getwalletinfo",
uriExtensionOpt = Some(walletExtension(walletName))
)
}
}
@ -294,7 +292,7 @@ trait WalletRpc { self: Client =>
}
def getBalances: Future[GetBalancesResult] = {
bitcoindCall[GetBalancesResult]("getbalances")
getBalances(BitcoindRpcClient.DEFAULT_WALLET_NAME)
}
def getBalances(walletName: String): Future[GetBalancesResult] = {
@ -383,7 +381,7 @@ trait WalletRpc { self: Client =>
descriptors: Boolean = false
): Future[CreateWalletResult] =
self.version.flatMap {
case V25 | V24 =>
case V25 =>
bitcoindCall[CreateWalletResult](
"createwallet",
List(
@ -412,19 +410,12 @@ trait WalletRpc { self: Client =>
address: BitcoinAddress,
walletName: String = DEFAULT_WALLET
): Future[AddressInfoResult] = {
self.version.flatMap {
case Unknown =>
bitcoindCall[AddressInfoResultPostV18](
"getaddressinfo",
List(JsString(address.value)),
uriExtensionOpt = Some(walletExtension(walletName))
)
case V25 | V24 =>
bitcoindCall[AddressInfoResultPostV21](
"getaddressinfo",
List(JsString(address.value)),
uriExtensionOpt = Some(walletExtension(walletName))
)
self.version.flatMap { case V25 | Unknown =>
bitcoindCall[AddressInfoResultPostV21](
"getaddressinfo",
List(JsString(address.value)),
uriExtensionOpt = Some(walletExtension(walletName))
)
}
}
@ -551,4 +542,27 @@ trait WalletRpc { self: Client =>
Json.toJson(sigHash)
)
)
def simulateRawTransaction(
tx: Transaction,
includeWatchOnly: Boolean = true,
walletName: String = BitcoindRpcClient.DEFAULT_WALLET_NAME
): Future[CurrencyUnit] = {
simulateRawTransactions(Vector(tx), includeWatchOnly, walletName)
}
def simulateRawTransactions(
txs: Vector[Transaction],
includeWatchOnly: Boolean = true,
walletName: String = BitcoindRpcClient.DEFAULT_WALLET_NAME
): Future[CurrencyUnit] = {
val txsJson = JsArray(txs.map(tx => JsString(tx.hex)))
val options = Json.obj("include_watchonly" -> includeWatchOnly)
bitcoindCall[SimulateRawTransactionResult](
"simulaterawtransaction",
List(txsJson, options),
uriExtensionOpt = Some(walletExtension(walletName))
).map(_.balance_change)
}
}

View File

@ -1,97 +0,0 @@
package org.bitcoins.rpc.client.v24
import org.apache.pekko.actor.ActorSystem
import org.bitcoins.commons.jsonmodels.bitcoind.{
GetTxSpendingPrevOutResult,
SimulateRawTransactionResult
}
import org.bitcoins.commons.serializers.JsonSerializers._
import org.bitcoins.core.currency.CurrencyUnit
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutPoint}
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
import org.bitcoins.rpc.config.BitcoindInstance
import play.api.libs.json._
import scala.concurrent.Future
import scala.util.Try
/** Class for creating a BitcoindV24 instance that can access RPCs
*/
class BitcoindV24RpcClient(override val instance: BitcoindInstance)(implicit
actorSystem: ActorSystem
) extends BitcoindRpcClient(instance) {
override lazy val version: Future[BitcoindVersion] =
Future.successful(BitcoindVersion.V24)
def getTxSpendingPrevOut(
prevout: TransactionOutPoint
): Future[GetTxSpendingPrevOutResult] = {
getTxSpendingPrevOut(Vector(prevout)).map(_.head)
}
def getTxSpendingPrevOut(
prevouts: Vector[TransactionOutPoint]
): Future[Vector[GetTxSpendingPrevOutResult]] = {
val json = JsArray(prevouts.map { prev =>
Json.obj("txid" -> prev.txIdBE.hex, "vout" -> prev.vout.toLong)
})
bitcoindCall[Vector[GetTxSpendingPrevOutResult]](
"gettxspendingprevout",
List(json)
)
}
def simulateRawTransaction(
tx: Transaction,
includeWatchOnly: Boolean = true
): Future[CurrencyUnit] = {
simulateRawTransactions(Vector(tx), includeWatchOnly)
}
def simulateRawTransactions(
txs: Vector[Transaction],
includeWatchOnly: Boolean = true
): Future[CurrencyUnit] = {
val txsJson = JsArray(txs.map(tx => JsString(tx.hex)))
val options = Json.obj("include_watchonly" -> includeWatchOnly)
bitcoindCall[SimulateRawTransactionResult](
"simulaterawtransaction",
List(txsJson, options)
).map(_.balance_change)
}
}
object BitcoindV24RpcClient {
/** 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): BitcoindV24RpcClient = {
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
): BitcoindV24RpcClient =
new BitcoindV24RpcClient(instance)(system)
def fromUnknownVersion(
rpcClient: BitcoindRpcClient
): Try[BitcoindV24RpcClient] =
Try {
new BitcoindV24RpcClient(rpcClient.instance)(rpcClient.system)
}
}

View File

@ -59,9 +59,6 @@ sealed trait BitcoindInstanceLocal extends BitcoindInstance {
.last
foundVersion match {
case _: String
if foundVersion.startsWith(BitcoindVersion.V24.toString) =>
BitcoindVersion.V24
case _: String
if foundVersion.startsWith(BitcoindVersion.V25.toString) =>
BitcoindVersion.V25

View File

@ -1090,5 +1090,5 @@ object EclairRpcClient {
* @see
* https://github.com/ACINQ/eclair/releases/tag/v0.8.0
*/
val bitcoindV: BitcoindVersion = BitcoindVersion.V24
val bitcoindV: BitcoindVersion = BitcoindVersion.V25
}

View File

@ -2,7 +2,6 @@ package org.bitcoins.testkit.rpc
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.AddNodeArgument
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
import org.bitcoins.rpc.client.v24.BitcoindV24RpcClient
import org.bitcoins.rpc.client.v25.BitcoindV25RpcClient
import org.bitcoins.rpc.util.{NodePair, NodeTriple}
import org.bitcoins.testkit.EmbeddedPg
@ -49,39 +48,6 @@ trait BitcoindFixturesFundedCached extends BitcoindFixtures {
}
}
trait BitcoindFixturesFundedCachedV24
extends BitcoinSAsyncFixtureTest
with BitcoindFixturesFundedCached
with CachedBitcoindV24 {
override type FixtureParam = BitcoindV24RpcClient
override def withFixture(test: OneArgAsyncTest): FutureOutcome = {
val f: Future[Outcome] = for {
bitcoind <- cachedBitcoindWithFundsF
futOutcome = withV24FundedBitcoindCached(test, bitcoind)
fut <- futOutcome.toFuture
} yield fut
new FutureOutcome(f)
}
def withV24FundedBitcoindCached(
test: OneArgAsyncTest,
bitcoind: BitcoindV24RpcClient
): FutureOutcome = {
makeDependentFixture[BitcoindV24RpcClient](
() => Future.successful(bitcoind),
{ _ =>
Future.unit // don't want to destroy anything since it is cached
}
)(test)
}
override def afterAll(): Unit = {
super[CachedBitcoindV24].afterAll()
super[BitcoinSAsyncFixtureTest].afterAll()
}
}
trait BitcoindFixturesFundedCachedNewest
extends BitcoinSAsyncFixtureTest
with BitcoindFixturesFundedCached

View File

@ -30,7 +30,6 @@ import org.bitcoins.crypto.{
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.v24.BitcoindV24RpcClient
import org.bitcoins.rpc.client.v25.BitcoindV25RpcClient
import org.bitcoins.rpc.config._
import org.bitcoins.rpc.util.{NodePair, RpcUtil}
@ -177,7 +176,7 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
version match {
// default to newest version
case Unknown => getBinary(BitcoindVersion.newest, binaryDirectory)
case known @ (V24 | V25) =>
case known @ (V25) =>
val fileList = Files
.list(binaryDirectory)
.iterator()
@ -241,22 +240,6 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
BitcoindInstanceLocal.fromConfig(conf, binary)
}
def v24Instance(
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.V24),
binaryDirectory = binaryDirectory
)
def v25Instance(
port: Int = RpcUtil.randomPort,
rpcPort: Int = RpcUtil.randomPort,
@ -283,14 +266,6 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
binaryDirectory: Path = BitcoindRpcTestClient.sbtBinaryDirectory
)(implicit system: ActorSystem): BitcoindInstanceLocal = {
bitcoindVersion match {
case BitcoindVersion.V24 =>
BitcoindRpcTestUtil.v24Instance(
port,
rpcPort,
zmqConfig,
pruneMode,
binaryDirectory = binaryDirectory
)
case BitcoindVersion.V25 =>
BitcoindRpcTestUtil.v25Instance(
port,
@ -311,9 +286,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 {
version <- server.version
descriptors = true
_ <- res.createWallet(BitcoindRpcClient.DEFAULT_WALLET_NAME,
descriptors = descriptors)
} yield res
@ -638,10 +612,6 @@ trait BitcoindRpcTestUtil extends BitcoinSLogger {
val rpc = version match {
case BitcoindVersion.Unknown =>
BitcoindRpcClient.withActorSystem(BitcoindRpcTestUtil.instance())
case BitcoindVersion.V24 =>
BitcoindV24RpcClient.withActorSystem(
BitcoindRpcTestUtil.v24Instance()
)
case BitcoindVersion.V25 =>
BitcoindV25RpcClient.withActorSystem(
BitcoindRpcTestUtil.v25Instance())

View File

@ -1,7 +1,6 @@
package org.bitcoins.testkit.rpc
import org.bitcoins.rpc.client.common.{BitcoindRpcClient, BitcoindVersion}
import org.bitcoins.rpc.client.v24.BitcoindV24RpcClient
import org.bitcoins.rpc.util.{NodePair, NodeTriple}
import org.bitcoins.testkit.fixtures.BitcoinSFixture
import org.bitcoins.testkit.util.BitcoinSPekkoAsyncTest
@ -80,6 +79,7 @@ trait CachedBitcoindFunded[T <: BitcoindRpcClient] extends CachedBitcoind[T] {
if (isBitcoindUsed.get()) {
// if it was used, shut down the cached bitcoind
val stoppedF = for {
_ <- Future.unit
cachedBitcoind <- cachedBitcoindWithFundsF
_ <- BitcoindRpcTestUtil.stopServer(cachedBitcoind)
} yield {
@ -128,18 +128,6 @@ trait CachedBitcoindBlockFilterRpcNewest
}
}
trait CachedBitcoindV24 extends CachedBitcoindFunded[BitcoindV24RpcClient] {
_: BitcoinSPekkoAsyncTest =>
override protected lazy val cachedBitcoindWithFundsF
: Future[BitcoindV24RpcClient] = {
val _ = isBitcoindUsed.set(true)
BitcoinSFixture
.createBitcoindWithFunds(Some(BitcoindVersion.V24))
.map(_.asInstanceOf[BitcoindV24RpcClient])
}
}
trait CachedBitcoindCollection[T <: BitcoindRpcClient]
extends CachedBitcoind[T] {
_: BitcoinSPekkoAsyncTest =>