Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement bitcoind v23 rpc #4368

Merged
merged 1 commit into from
Jun 21, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
package org.bitcoins.commons.jsonmodels.bitcoind

import java.nio.file.Path

import org.bitcoins.core.api.chain.db.{
BlockHeaderDb,
BlockHeaderDbHelper,
Expand All @@ -17,6 +15,8 @@ import org.bitcoins.core.wallet.fee.BitcoinFeeUnit
import org.bitcoins.crypto.DoubleSha256DigestBE
import scodec.bits.ByteVector

import java.nio.file.Path

sealed abstract class BlockchainResult

case class DumpTxOutSetResult(
Expand Down Expand Up @@ -119,6 +119,24 @@ case class GetBlockChainInfoResultPostV19(
warnings: String)
extends GetBlockChainInfoResult

// adds time field removes softforks field
case class GetBlockChainInfoResultPostV23(
chain: NetworkParameters,
blocks: Int,
headers: Int,
bestblockhash: DoubleSha256DigestBE,
difficulty: BigDecimal,
time: Int,
mediantime: Int,
verificationprogress: BigDecimal,
initialblockdownload: Boolean,
chainwork: String, // How should this be handled?
size_on_disk: Long,
pruned: Boolean,
pruneheight: Option[Int],
warnings: String)
extends GetBlockChainInfoResult

case class SoftforkPreV19(
id: String,
version: Int,
Expand Down Expand Up @@ -219,16 +237,12 @@ case class GetChainTxStatsResult(

sealed trait GetMemPoolResult extends BlockchainResult {
def size: Int
def fee: Option[Bitcoins]
def modifiedfee: Option[Bitcoins]
def time: UInt32
def height: Int
def descendantcount: Int
def descendantsize: Int
def descendantfees: Option[Bitcoins]
def ancestorcount: Int
def ancestorsize: Int
def ancestorfees: Option[Bitcoins]
def wtxid: DoubleSha256DigestBE
def fees: FeeInfo
def depends: Vector[DoubleSha256DigestBE]
Expand Down Expand Up @@ -270,6 +284,22 @@ case class GetMemPoolResultPostV19(
override def size: Int = vsize
}

// v23 removes 'fee', 'modifiedfee', 'descendantfees', 'ancestorfees'
case class GetMemPoolResultPostV23(
vsize: Int,
time: UInt32,
height: Int,
descendantcount: Int,
descendantsize: Int,
ancestorcount: Int,
ancestorsize: Int,
wtxid: DoubleSha256DigestBE,
fees: FeeInfo,
depends: Vector[DoubleSha256DigestBE])
extends GetMemPoolResult {
override def size: Int = vsize
}

case class FeeInfo(
base: BitcoinFeeUnit,
modified: BitcoinFeeUnit,
Expand All @@ -279,16 +309,12 @@ case class FeeInfo(

sealed trait GetMemPoolEntryResult extends BlockchainResult {
def size: Int
def fee: Bitcoins
def modifiedfee: Bitcoins
def time: UInt32
def height: Int
def descendantcount: Int
def descendantsize: Int
def descendantfees: BitcoinFeeUnit
def ancestorcount: Int
def ancestorsize: Int
def ancestorfees: BitcoinFeeUnit
def wtxid: DoubleSha256DigestBE
def fees: FeeInfo
def depends: Option[Vector[DoubleSha256DigestBE]]
Expand Down Expand Up @@ -331,6 +357,22 @@ case class GetMemPoolEntryResultPostV19(
override def size: Int = vsize
}

case class GetMemPoolEntryResultPostV23(
vsize: Int,
weight: Int,
time: UInt32,
height: Int,
descendantcount: Int,
descendantsize: Int,
ancestorcount: Int,
ancestorsize: Int,
wtxid: DoubleSha256DigestBE,
fees: FeeInfo,
depends: Option[Vector[DoubleSha256DigestBE]])
extends GetMemPoolEntryResult {
override def size: Int = vsize
}

case class GetMemPoolInfoResult(
size: Int,
bytes: Int,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ trait ValidateAddressResult {
def isvalid: Boolean
def address: Option[BitcoinAddress]
def scriptPubKey: Option[ScriptPubKey]
def error_locations: Option[Vector[Int]]

@deprecated("Use 'getaddressinfo' instead", since = "0.16")
def ismine: Option[Boolean]
Expand Down Expand Up @@ -131,6 +132,7 @@ case class ValidateAddressResultImpl(
isvalid: Boolean,
address: Option[BitcoinAddress],
scriptPubKey: Option[ScriptPubKey],
error_locations: Option[Vector[Int]],
ismine: Option[Boolean],
iswatchonly: Option[Boolean],
isscript: Option[Boolean],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,8 @@ case class MultiSigResultPreV20(
case class MultiSigResultPostV20(
address: BitcoinAddress,
redeemScript: ScriptPubKey,
descriptor: String)
descriptor: String,
warnings: Option[String]) //available in v23
extends MultiSigResult

case class BumpFeeResult(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ object JsonSerializers {
implicit val getBlockChainInfoResultPostV19Reads: Reads[
GetBlockChainInfoResultPostV19] = Json.reads[GetBlockChainInfoResultPostV19]

implicit val getBlockChainInfoResultPostV23Reads: Reads[
GetBlockChainInfoResultPostV23] = Json.reads[GetBlockChainInfoResultPostV23]

implicit val blockHeaderFormattedReads: Reads[GetBlockHeaderResult] =
Json.reads[GetBlockHeaderResult]

Expand All @@ -311,6 +314,9 @@ object JsonSerializers {
implicit val getMemPoolResultPostV19Reads: Reads[GetMemPoolResultPostV19] =
Json.reads[GetMemPoolResultPostV19]

implicit val getMemPoolResultPostV23Reads: Reads[GetMemPoolResultPostV23] =
Json.reads[GetMemPoolResultPostV23]

implicit val getMemPoolEntryResultPreV19Reads: Reads[
GetMemPoolEntryResultPreV19] =
Json.reads[GetMemPoolEntryResultPreV19]
Expand All @@ -319,6 +325,10 @@ object JsonSerializers {
GetMemPoolEntryResultPostV19] =
Json.reads[GetMemPoolEntryResultPostV19]

implicit val getMemPoolEntryResultPostV23Reads: Reads[
GetMemPoolEntryResultPostV23] =
Json.reads[GetMemPoolEntryResultPostV23]

implicit val getMemPoolInfoResultReads: Reads[GetMemPoolInfoResult] =
Json.reads[GetMemPoolInfoResult]

Expand Down Expand Up @@ -775,6 +785,11 @@ object JsonSerializers {
Reads.mapReads[DoubleSha256Digest, GetMemPoolResultPostV19](s =>
JsSuccess(DoubleSha256Digest.fromHex(s)))

implicit def mapDoubleSha256DigestReadsPostV23: Reads[
Map[DoubleSha256Digest, GetMemPoolResultPostV23]] =
Reads.mapReads[DoubleSha256Digest, GetMemPoolResultPostV23](s =>
JsSuccess(DoubleSha256Digest.fromHex(s)))

implicit def mapDoubleSha256DigestBEReadsPreV19: Reads[
Map[DoubleSha256DigestBE, GetMemPoolResultPreV19]] =
Reads.mapReads[DoubleSha256DigestBE, GetMemPoolResultPreV19](s =>
Expand All @@ -785,6 +800,11 @@ object JsonSerializers {
Reads.mapReads[DoubleSha256DigestBE, GetMemPoolResultPostV19](s =>
JsSuccess(DoubleSha256DigestBE.fromHex(s)))

implicit def mapDoubleSha256DigestBEReadsPostV23: Reads[
Map[DoubleSha256DigestBE, GetMemPoolResultPostV23]] =
Reads.mapReads[DoubleSha256DigestBE, GetMemPoolResultPostV23](s =>
JsSuccess(DoubleSha256DigestBE.fromHex(s)))

implicit def mapAddressesByLabelReads: Reads[
Map[BitcoinAddress, LabelResult]] =
Reads.mapReads[BitcoinAddress, LabelResult](s =>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package org.bitcoins.rpc.common

import org.bitcoins.commons.jsonmodels.bitcoind.GetMemPoolEntryResultPostV19
import org.bitcoins.core.currency.Bitcoins
import org.bitcoins.core.number.UInt32
import org.bitcoins.core.protocol.script.ScriptSignature
Expand Down Expand Up @@ -120,9 +121,13 @@ class MempoolRpcTest extends BitcoindFixturesCachedPairV21 {
txid <-
BitcoindRpcTestUtil
.fundMemPoolTransaction(client, address, Bitcoins(3.2))
entry <- client.getMemPoolEntry(txid)
entry <- client
.getMemPoolEntry(txid)
.map(_.asInstanceOf[GetMemPoolEntryResultPostV19])
tt <- client.prioritiseTransaction(txid, Bitcoins(1).satoshis)
newEntry <- client.getMemPoolEntry(txid)
newEntry <- client
.getMemPoolEntry(txid)
.map(_.asInstanceOf[GetMemPoolEntryResultPostV19])
} yield {
assert(entry.fee == entry.modifiedfee)
assert(tt)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package org.bitcoins.rpc.v23

import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.AddressType
import org.bitcoins.core.protocol.P2PKHAddress
import org.bitcoins.core.script.ScriptType
import org.bitcoins.crypto.ECPrivateKey
import org.bitcoins.rpc.client.common.BitcoindVersion
import org.bitcoins.rpc.client.v23.BitcoindV23RpcClient
import org.bitcoins.testkit.rpc.BitcoindFixturesFundedCachedV23

class BitcoindV23RpcClientTest extends BitcoindFixturesFundedCachedV23 {

behavior of "BitcoindV23RpcClient"

it should "be able to start a V23 bitcoind instance" in {
client: BitcoindV23RpcClient =>
for {
v <- client.version
} yield assert(v == BitcoindVersion.V23)
}

it should "be able to get network info" in {
freshClient: BitcoindV23RpcClient =>
for {
info <- freshClient.getNetworkInfo
} yield {
assert(info.networkactive)
assert(info.localrelay)
}
}

it should "be able to decode a reedem script" in {
client: BitcoindV23RpcClient =>
val ecPrivKey1 = ECPrivateKey.freshPrivateKey
val pubKey1 = ecPrivKey1.publicKey
for {
address <- client.getNewAddress(addressType = AddressType.Legacy)
multisig <-
client
.addMultiSigAddress(
2,
Vector(Left(pubKey1), Right(address.asInstanceOf[P2PKHAddress])))
decoded <- client.decodeScript(multisig.redeemScript)
} yield {
assert(decoded.typeOfScript.contains(ScriptType.MULTISIG))
// these fields are no longer returned since v23
// assert(decoded.reqSigs.isEmpty)
// assert(decoded.addresses.isEmpty)
}
}

}
16 changes: 13 additions & 3 deletions bitcoind-rpc/bitcoind-rpc.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ TaskKeys.downloadBitcoind := {
"0.18.99" // TODO: change this when new version compiled on suredbits server

val versions =
List("22.0",
List("23.0",
"22.0",
"0.21.1",
"0.20.1",
"0.19.0.1",
Expand All @@ -38,14 +39,20 @@ TaskKeys.downloadBitcoind := {
logger.debug(
s"(Maybe) downloading Bitcoin Core binaries for versions: ${versions.mkString(",")}")

val (platform, suffix) =
def getPlatformAndSuffix(version: String): (String, String) = {
if (Properties.isLinux) ("x86_64-linux-gnu", "tar.gz")
else if (Properties.isMac) ("osx64", "tar.gz")
else if (Properties.isMac)
version match {
case "23.0" => ("x86_64-apple-darwin", "tar.gz")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎉

case _ => ("osx64", "tar.gz")
}
else if (Properties.isWin) ("win64", "zip")
else sys.error(s"Unsupported OS: ${Properties.osName}")
}

implicit val ec = scala.concurrent.ExecutionContext.global
val downloads = versions.map { version =>
val (platform, suffix) = getPlatformAndSuffix(version)
val archiveLocation = binaryDir resolve s"$version.$suffix"
val location =
if (version == experimentalVersion)
Expand Down Expand Up @@ -99,6 +106,7 @@ TaskKeys.downloadBitcoind := {
val expectedHash =
if (Properties.isLinux)
Map(
"23.0" -> "2cca490c1f2842884a3c5b0606f179f9f937177da4eadd628e3f7fd7e25d26d0",
"22.0" -> "59ebd25dd82a51638b7a6bb914586201e67db67b919b2a1ff08925a7936d1b16",
"0.21.1" -> "366eb44a7a0aa5bd342deea215ec19a184a11f2ca22220304ebb20b9c8917e2b",
"0.20.1" -> "376194f06596ecfa40331167c39bc70c355f960280bd2a645fdbf18f66527397",
Expand All @@ -110,6 +118,7 @@ TaskKeys.downloadBitcoind := {
)
else if (Properties.isMac)
Map(
"23.0" -> "c816780583009a9dad426dc0c183c89be9da98906e1e2c7ebae91041c1aaaaf3",
"22.0" -> "2744d199c3343b2d94faffdfb2c94d75a630ba27301a70e47b0ad30a7e0155e9",
"0.21.1" -> "1ea5cedb64318e9868a66d3ab65de14516f9ada53143e460d50af428b5aec3c7",
"0.20.1" -> "b9024dde373ea7dad707363e07ec7e265383204127539ae0c234bff3a61da0d1",
Expand All @@ -121,6 +130,7 @@ TaskKeys.downloadBitcoind := {
)
else if (Properties.isWin)
Map(
"23.0" -> "004b2e25b21e0f14cbcce6acec37f221447abbb3ea7931c689e508054bfc6cf6",
"22.0" -> "9485e4b52ed6cebfe474ab4d7d0c1be6d0bb879ba7246a8239326b2230a77eb1",
"0.21.1" -> "94c80f90184cdc7e7e75988a55b38384de262336abd80b1b30121c6e965dc74e",
"0.20.1" -> "e59fba67afce011d32b5d723a3a0be12da1b8a34f5d7966e504520c48d64716d",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import org.bitcoins.rpc.client.v19.BitcoindV19RpcClient
import org.bitcoins.rpc.client.v20.BitcoindV20RpcClient
import org.bitcoins.rpc.client.v21.BitcoindV21RpcClient
import org.bitcoins.rpc.client.v22.BitcoindV22RpcClient
import org.bitcoins.rpc.client.v23.BitcoindV23RpcClient
import org.bitcoins.rpc.config._

import java.io.File
Expand Down Expand Up @@ -328,6 +329,7 @@ object BitcoindRpcClient {
case BitcoindVersion.V20 => BitcoindV20RpcClient.withActorSystem(instance)
case BitcoindVersion.V21 => BitcoindV21RpcClient.withActorSystem(instance)
case BitcoindVersion.V22 => BitcoindV22RpcClient.withActorSystem(instance)
case BitcoindVersion.V23 => BitcoindV23RpcClient.withActorSystem(instance)
case BitcoindVersion.Experimental =>
BitcoindV18RpcClient.withActorSystem(instance)
case BitcoindVersion.Unknown =>
Expand All @@ -350,10 +352,10 @@ sealed trait BitcoindVersion
object BitcoindVersion extends StringFactory[BitcoindVersion] {

/** The newest version of `bitcoind` we support */
val newest: BitcoindVersion = V22
val newest: BitcoindVersion = V23
Christewart marked this conversation as resolved.
Show resolved Hide resolved

val standard: Vector[BitcoindVersion] =
Vector(V16, V17, V18, V19, V20, V21, V22)
Vector(V16, V17, V18, V19, V20, V21, V22, V23)

val known: Vector[BitcoindVersion] = standard :+ Experimental

Expand Down Expand Up @@ -385,6 +387,10 @@ object BitcoindVersion extends StringFactory[BitcoindVersion] {
override def toString: String = "v22"
}

case object V23 extends BitcoindVersion {
override def toString: String = "v23"
}

case object Experimental extends BitcoindVersion {
override def toString: String = "v0.18.99"
}
Expand Down Expand Up @@ -418,6 +424,7 @@ object BitcoindVersion extends StringFactory[BitcoindVersion] {
case "20" => V20
case "21" => V21
case "22" => V22
case "23" => V23
case _ => Unknown
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,10 @@ trait BlockchainRpc { self: Client =>
self.version.flatMap {
case V16 | V17 | V18 =>
bitcoindCall[GetBlockChainInfoResultPreV19]("getblockchaininfo")
case V22 | V21 | V20 | V19 | Experimental | Unknown =>
case V22 | V21 | V20 | V19 =>
bitcoindCall[GetBlockChainInfoResultPostV19]("getblockchaininfo")
case V23 | Experimental | Unknown =>
bitcoindCall[GetBlockChainInfoResultPostV23]("getblockchaininfo")
}
}

Expand Down