Skip to content

Commit

Permalink
add bitcoind v23 rpc
Browse files Browse the repository at this point in the history
  • Loading branch information
solo1g committed Jun 5, 2022
1 parent 0a0fc92 commit fd175e2
Show file tree
Hide file tree
Showing 23 changed files with 345 additions and 48 deletions.
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 @@ -293,6 +293,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 @@ -309,6 +312,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 @@ -317,6 +323,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 @@ -773,6 +783,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 @@ -783,6 +798,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")
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

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

0 comments on commit fd175e2

Please sign in to comment.