Fixed getAddressInfo for versions 18 and 19 (#1679)

This commit is contained in:
Nadav Kohen 2020-07-17 13:20:36 -05:00 committed by GitHub
parent 4935b513c7
commit 714d5a06fd
4 changed files with 166 additions and 137 deletions

View file

@ -204,7 +204,30 @@ case class UnspentOutput(
reused: Option[Boolean])
extends WalletResult
case class AddressInfoResult(
sealed trait AddressInfoResult extends WalletResult {
def address: BitcoinAddress
def scriptPubKey: ScriptPubKey
def ismine: Boolean
def iswatchonly: Boolean
def isscript: Boolean
def iswitness: Boolean
def iscompressed: Option[Boolean]
def witness_version: Option[WitnessVersion]
def witness_program: Option[String] // todo what's the correct type here?
def script: Option[ScriptType]
def hex: Option[ScriptPubKey]
def pubkeys: Option[Vector[ECPublicKey]]
def sigsrequired: Option[Int]
def pubkey: Option[ECPublicKey]
def embedded: Option[EmbeddedResult]
def label: String
def timestamp: Option[ZonedDateTime]
def hdkeypath: Option[BIP32Path]
def hdseedid: Option[RipeMd160Digest]
def labels: Vector[LabelResult]
}
case class AddressInfoResultPreV18(
address: BitcoinAddress,
scriptPubKey: ScriptPubKey,
ismine: Boolean,
@ -213,7 +236,7 @@ case class AddressInfoResult(
iswitness: Boolean,
iscompressed: Option[Boolean],
witness_version: Option[WitnessVersion],
witness_program: Option[String], // todo what's the correct type here?
witness_program: Option[String],
script: Option[ScriptType],
hex: Option[ScriptPubKey],
pubkeys: Option[Vector[ECPublicKey]],
@ -226,7 +249,94 @@ case class AddressInfoResult(
hdseedid: Option[RipeMd160Digest],
hdmasterkeyid: Option[RipeMd160Digest],
labels: Vector[LabelResult])
extends WalletResult
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 EmbeddedResult(
isscript: Boolean,

View file

@ -8,142 +8,19 @@ import org.bitcoins.core.currency.{Bitcoins, Satoshis}
import org.bitcoins.core.hd.BIP32Path
import org.bitcoins.core.number.{Int32, UInt32, UInt64}
import org.bitcoins.core.protocol.blockchain.{Block, BlockHeader, MerkleBlock}
import org.bitcoins.core.protocol.script.{
ScriptPubKey,
ScriptSignature,
WitnessScriptPubKey
}
import org.bitcoins.core.protocol.transaction.{
Transaction,
TransactionInput,
TransactionOutPoint
}
import org.bitcoins.core.protocol.{
Address,
BitcoinAddress,
P2PKHAddress,
P2SHAddress
}
import org.bitcoins.core.protocol.script._
import org.bitcoins.core.protocol.transaction._
import org.bitcoins.core.protocol._
import org.bitcoins.core.script.ScriptType
import org.bitcoins.core.wallet.fee.{
BitcoinFeeUnit,
SatoshisPerKiloByte,
SatoshisPerVirtualByte
}
import org.bitcoins.core.wallet.fee._
import org.bitcoins.commons.serializers.JsonReaders._
import org.bitcoins.commons.serializers.JsonWriters._
import java.time.LocalDateTime
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.AddressType
import org.bitcoins.commons.jsonmodels.bitcoind.{
AddressInfoResult,
AnalyzePsbtInput,
AnalyzePsbtResult,
ArrayOfWalletsInput,
BalanceInfo,
Bip9Softfork,
BlockTransaction,
BumpFeeResult,
ChainTip,
CreateWalletResult,
DecodePsbtResult,
DecodeScriptResult,
DeriveAddressesResult,
DumpWalletResult,
EmbeddedResult,
EstimateSmartFeeResult,
FeeInfo,
FinalizePsbtResult,
FinalizedPsbt,
FundRawTransactionResult,
GetBalancesResult,
GetBlockChainInfoResult,
GetBlockHeaderResult,
GetBlockResult,
GetBlockTemplateResult,
GetBlockWithTransactionsResult,
GetChainTxStatsResult,
GetDescriptorInfoResult,
GetMemPoolEntryResultPostV19,
GetMemPoolEntryResultPreV19,
GetMemPoolInfoResult,
GetMemPoolResultPostV19,
GetMemPoolResultPreV19,
GetMemoryInfoResult,
GetMiningInfoResult,
GetNetTotalsResult,
GetNetworkInfoResult,
GetNodeAddressesResult,
GetRawTransactionResult,
GetRawTransactionScriptSig,
GetRawTransactionVin,
GetRpcInfoResult,
GetTransactionResult,
GetTxOutResult,
GetTxOutSetInfoResult,
GetWalletInfoResult,
ImportMultiError,
ImportMultiResult,
LabelResult,
ListSinceBlockResult,
ListTransactionsResult,
ListWalletDirResult,
MemoryManager,
MultiSigResult,
NetTarget,
Network,
NetworkAddress,
Node,
NodeAddress,
NodeBan,
NonFinalizedPsbt,
Payment,
Peer,
PeerNetworkInfo,
PsbtBIP32Deriv,
PsbtMissingData,
PsbtWitnessUtxoInput,
ReceivedAccount,
ReceivedAddress,
ReceivedLabel,
RescanBlockChainResult,
RpcAccount,
RpcAddress,
RpcCommands,
RpcPsbtInput,
RpcPsbtOutput,
RpcPsbtScript,
RpcScriptPubKey,
RpcTransaction,
RpcTransactionOutput,
SetWalletFlagResult,
SignRawTransactionError,
SignRawTransactionResult,
SignRawTransactionWithWalletResult,
Softfork,
SoftforkProgress,
SubmitHeaderResult,
TestMempoolAcceptResult,
TransactionDetails,
UnspentOutput,
ValidateAddressResultImpl,
WalletCreateFundedPsbtResult,
WalletProcessPsbtResult
}
import org.bitcoins.commons.jsonmodels.wallet.{
BitGoResult,
BitcoinerLiveEstimate,
BitcoinerLiveResult
}
import org.bitcoins.crypto.{
DoubleSha256Digest,
DoubleSha256DigestBE,
ECDigitalSignature,
ECPublicKey,
RipeMd160Digest,
RipeMd160DigestBE,
Sha256Hash160Digest
}
import org.bitcoins.commons.jsonmodels.bitcoind._
import org.bitcoins.commons.jsonmodels.wallet._
import org.bitcoins.crypto._
import play.api.libs.functional.syntax._
import play.api.libs.json._
@ -525,8 +402,25 @@ object JsonSerializers {
implicit val embeddedResultReads: Reads[EmbeddedResult] =
Json.reads[EmbeddedResult]
implicit val addressInfoResultReads: Reads[AddressInfoResult] =
Json.reads[AddressInfoResult]
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 receivedLabelReads: Reads[ReceivedLabel] =
Json.reads[ReceivedLabel]

View file

@ -1,6 +1,10 @@
package org.bitcoins.rpc.v18
import org.bitcoins.chain.models.BlockHeaderDbHelper
import org.bitcoins.commons.jsonmodels.bitcoind.{
AddressInfoResultPostV18,
AddressInfoResultPreV18
}
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.AddNodeArgument
import org.bitcoins.core.protocol.blockchain.RegTestNetChainParams
import org.bitcoins.rpc.client.common.BitcoindVersion
@ -109,4 +113,19 @@ class BitcoindV18RpcClientTest extends BitcoindRpcTest {
client.submitHeader(nextHeader.blockHeader).map(_ => succeed))
}
it should "have extra address information" in {
for {
(client, _) <- clientPairF
address <- client.getNewAddress
info <- client.getAddressInfo(address)
} yield {
info match {
case _: AddressInfoResultPreV18 =>
fail("Was expecting AddressInfoResultPostV18")
case postV18Info: AddressInfoResultPostV18 =>
assert(postV18Info.address == address)
}
}
}
}

View file

@ -223,7 +223,13 @@ trait WalletRpc { self: Client =>
}
def getAddressInfo(address: BitcoinAddress): Future[AddressInfoResult] = {
bitcoindCall[AddressInfoResult]("getaddressinfo",
List(JsString(address.value)))
self.version match {
case V16 | V17 =>
bitcoindCall[AddressInfoResultPreV18]("getaddressinfo",
List(JsString(address.value)))
case V18 | V19 | Experimental | Unknown =>
bitcoindCall[AddressInfoResultPostV18]("getaddressinfo",
List(JsString(address.value)))
}
}
}