Seq and Map Wrappers (#1131)

* Renamed size to byteSize in NetworkElement to avoid ambiguity

* Introduced SeqWrapper and MapWrapper to allow for wrapper case classes to have direct access to underlying methods

* Responded to review
This commit is contained in:
Nadav Kohen 2020-02-24 13:39:20 -07:00 committed by GitHub
parent 03cfbc0803
commit 052b64b7e2
40 changed files with 142 additions and 107 deletions

View File

@ -60,7 +60,7 @@ class RawTransactionRpcTest extends BitcoindRpcTest {
} yield { } yield {
assert(rpcTransaction.txid == transaction.txIdBE) assert(rpcTransaction.txid == transaction.txIdBE)
assert(rpcTransaction.locktime == transaction.lockTime) assert(rpcTransaction.locktime == transaction.lockTime)
assert(rpcTransaction.size == transaction.size) assert(rpcTransaction.size == transaction.byteSize)
assert(rpcTransaction.version == transaction.version.toInt) assert(rpcTransaction.version == transaction.version.toInt)
assert(rpcTransaction.vsize == transaction.vsize) assert(rpcTransaction.vsize == transaction.vsize)
} }

View File

@ -12,6 +12,7 @@ import org.bitcoins.core.protocol.BitcoinAddress
import org.bitcoins.core.protocol.blockchain.BlockHeader import org.bitcoins.core.protocol.blockchain.BlockHeader
import org.bitcoins.core.protocol.script.ScriptPubKey import org.bitcoins.core.protocol.script.ScriptPubKey
import org.bitcoins.core.protocol.transaction.Transaction import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.util.SeqWrapper
import org.bitcoins.core.wallet.fee.BitcoinFeeUnit import org.bitcoins.core.wallet.fee.BitcoinFeeUnit
import play.api.libs.json.JsObject import play.api.libs.json.JsObject
@ -161,6 +162,9 @@ case class TestMempoolAcceptResult(
final case class DeriveAddressesResult(addresses: Vector[BitcoinAddress]) final case class DeriveAddressesResult(addresses: Vector[BitcoinAddress])
extends OtherResult extends OtherResult
with SeqWrapper[BitcoinAddress] {
override protected val wrapped: Vector[BitcoinAddress] = addresses
}
final case class GetDescriptorInfoResult( final case class GetDescriptorInfoResult(
descriptor: String, descriptor: String,

View File

@ -2,12 +2,11 @@ package org.bitcoins.chain.blockchain
import org.bitcoins.chain.models.BlockHeaderDb import org.bitcoins.chain.models.BlockHeaderDb
import scala.collection.{mutable, IndexedSeqLike} import scala.collection.mutable
/** @inheritdoc */ /** @inheritdoc */
case class Blockchain(headers: Vector[BlockHeaderDb]) case class Blockchain(headers: Vector[BlockHeaderDb])
extends IndexedSeqLike[BlockHeaderDb, Vector[BlockHeaderDb]] extends BaseBlockChain {
with BaseBlockChain {
protected[blockchain] def compObjectfromHeaders( protected[blockchain] def compObjectfromHeaders(
headers: scala.collection.immutable.Seq[BlockHeaderDb]): Blockchain = headers: scala.collection.immutable.Seq[BlockHeaderDb]): Blockchain =

View File

@ -2,20 +2,13 @@ package org.bitcoins.chain.blockchain
import org.bitcoins.chain.models.BlockHeaderDb import org.bitcoins.chain.models.BlockHeaderDb
import scala.collection.immutable.IndexedSeq
/** @inheritdoc */ /** @inheritdoc */
case class Blockchain(headers: Vector[BlockHeaderDb]) case class Blockchain(headers: Vector[BlockHeaderDb]) extends BaseBlockChain {
extends IndexedSeq[BlockHeaderDb]
with BaseBlockChain {
protected[blockchain] def compObjectfromHeaders( protected[blockchain] def compObjectfromHeaders(
headers: scala.collection.immutable.Seq[BlockHeaderDb]) = headers: scala.collection.immutable.Seq[BlockHeaderDb]) =
Blockchain.fromHeaders(headers) Blockchain.fromHeaders(headers)
/** @inheritdoc */
override def seq = this
} }
object Blockchain extends BaseBlockChainCompObject { object Blockchain extends BaseBlockChainCompObject {

View File

@ -7,6 +7,7 @@ import org.bitcoins.chain.ChainVerificationLogger
import org.bitcoins.chain.validation.TipUpdateResult import org.bitcoins.chain.validation.TipUpdateResult
import org.bitcoins.chain.validation.TipValidation import org.bitcoins.chain.validation.TipValidation
import org.bitcoins.core.crypto.DoubleSha256DigestBE import org.bitcoins.core.crypto.DoubleSha256DigestBE
import org.bitcoins.core.util.SeqWrapper
import scala.annotation.tailrec import scala.annotation.tailrec
@ -33,7 +34,7 @@ import scala.annotation.tailrec
* }}} * }}}
* *
*/ */
private[blockchain] trait BaseBlockChain { private[blockchain] trait BaseBlockChain extends SeqWrapper[BlockHeaderDb] {
protected[blockchain] def compObjectfromHeaders( protected[blockchain] def compObjectfromHeaders(
headers: scala.collection.immutable.Seq[BlockHeaderDb]): Blockchain headers: scala.collection.immutable.Seq[BlockHeaderDb]): Blockchain
@ -43,12 +44,10 @@ private[blockchain] trait BaseBlockChain {
/** The height of the chain */ /** The height of the chain */
val height: Int = tip.height val height: Int = tip.height
val length: Int = headers.length
def apply(idx: Int): BlockHeaderDb = headers(idx)
def headers: Vector[BlockHeaderDb] def headers: Vector[BlockHeaderDb]
override protected lazy val wrapped: Vector[BlockHeaderDb] = headers
def find(predicate: BlockHeaderDb => Boolean): Option[BlockHeaderDb] def find(predicate: BlockHeaderDb => Boolean): Option[BlockHeaderDb]
/** Finds a block header at a given height */ /** Finds a block header at a given height */

View File

@ -74,8 +74,8 @@ class TransactionTest extends BitcoinSUnitTest {
val rawTx = TestUtil.rawTransaction val rawTx = TestUtil.rawTransaction
val tx = Transaction(rawTx) val tx = Transaction(rawTx)
//size is in bytes so divide by 2 //size is in bytes so divide by 2
assert(tx.size == tx.totalSize) assert(tx.byteSize == tx.totalSize)
tx.size must be(rawTx.size / 2) tx.byteSize must be(rawTx.size / 2)
} }
it must "serialize and deserialize a tx" in { it must "serialize and deserialize a tx" in {
@ -132,7 +132,7 @@ class TransactionTest extends BitcoinSUnitTest {
"0200000000010140d43a99926d43eb0e619bf0b3d83b4a31f60c176beecfb9d35bf45e54d0f7420100000017160014a4b4ca48de0b3fffc15404a1acdc8dbaae226955ffffffff0100e1f5050000000017a9144a1154d50b03292b3024370901711946cb7cccc387024830450221008604ef8f6d8afa892dee0f31259b6ce02dd70c545cfcfed8148179971876c54a022076d771d6e91bed212783c9b06e0de600fab2d518fad6f15a2b191d7fbd262a3e0121039d25ab79f41f75ceaf882411fd41fa670a4c672c23ffaf0e361a969cde0692e800000000" "0200000000010140d43a99926d43eb0e619bf0b3d83b4a31f60c176beecfb9d35bf45e54d0f7420100000017160014a4b4ca48de0b3fffc15404a1acdc8dbaae226955ffffffff0100e1f5050000000017a9144a1154d50b03292b3024370901711946cb7cccc387024830450221008604ef8f6d8afa892dee0f31259b6ce02dd70c545cfcfed8148179971876c54a022076d771d6e91bed212783c9b06e0de600fab2d518fad6f15a2b191d7fbd262a3e0121039d25ab79f41f75ceaf882411fd41fa670a4c672c23ffaf0e361a969cde0692e800000000"
val tx2 = WitnessTransaction(hex2) val tx2 = WitnessTransaction(hex2)
tx2.hex must be(hex2) tx2.hex must be(hex2)
tx2.size must be(216) tx2.byteSize must be(216)
tx2.weight must be(534) tx2.weight must be(534)
tx2.vsize must be(134) tx2.vsize must be(134)
tx2.baseSize must be(106) tx2.baseSize must be(106)

View File

@ -32,7 +32,7 @@ class RawTransactionInputParserTest extends FlatSpec with MustMatchers {
it must "find the correct size for an input" in { it must "find the correct size for an input" in {
val txInput: TransactionInput = RawTransactionInputParser.read(rawTxInput) val txInput: TransactionInput = RawTransactionInputParser.read(rawTxInput)
txInput.size must be(BitcoinSUtil.decodeHex(rawTxInput).size) txInput.byteSize must be(BitcoinSUtil.decodeHex(rawTxInput).size)
} }
it must "write a single input" in { it must "write a single input" in {

View File

@ -62,7 +62,7 @@ class RawTransactionOutPointParserTest extends BitcoinSUnitTest {
val rawOutPoint = val rawOutPoint =
"85d6b0da2edf96b282030d3f4f79d14cc8c882cfef1b3064170c850660317de100000000" "85d6b0da2edf96b282030d3f4f79d14cc8c882cfef1b3064170c850660317de100000000"
val outPoint = RawTransactionOutPointParser.read(rawOutPoint) val outPoint = RawTransactionOutPointParser.read(rawOutPoint)
outPoint.size must be(36) outPoint.byteSize must be(36)
} }
it must "parse a outpoint with extremely large vout" in { it must "parse a outpoint with extremely large vout" in {

View File

@ -50,7 +50,7 @@ object BIP39Seed extends Factory[BIP39Seed] {
password: String = EMPTY_PASSWORD): BIP39Seed = { password: String = EMPTY_PASSWORD): BIP39Seed = {
val salt = s"mnemonic$password" val salt = s"mnemonic$password"
val words = mnemonic.words.mkString(" ") val words = mnemonic.mkString(" ")
val encodedBytes = PBKDF2 val encodedBytes = PBKDF2
.withSha512(words, salt, ITERATION_COUNT, DERIVED_KEY_LENGTH) .withSha512(words, salt, ITERATION_COUNT, DERIVED_KEY_LENGTH)

View File

@ -92,7 +92,7 @@ sealed abstract class ExtKey extends NetworkElement {
case Nil => Success(accum) case Nil => Success(accum)
} }
} }
loop(path.path.toList, pub) loop(path.toList, pub)
} }
} }
@ -184,7 +184,7 @@ sealed abstract class ExtPrivateKey
* specialized version of a BIP32 path * specialized version of a BIP32 path
*/ */
def deriveChildPrivKey(path: BIP32Path): ExtPrivateKey = { def deriveChildPrivKey(path: BIP32Path): ExtPrivateKey = {
path.path.foldLeft(this)((accum: ExtPrivateKey, curr: BIP32Node) => path.foldLeft(this)((accum: ExtPrivateKey, curr: BIP32Node) =>
accum.deriveChildPrivKey(curr.toUInt32)) accum.deriveChildPrivKey(curr.toUInt32))
} }
@ -326,8 +326,8 @@ object ExtPrivateKey extends Factory[ExtPrivateKey] {
chaincode, chaincode,
masterPrivKey) masterPrivKey)
path.path.foldLeft(root)((accum, curr) => path.foldLeft(root)(
accum.deriveChildPrivKey(curr.toUInt32)) (accum, curr) => accum.deriveChildPrivKey(curr.toUInt32))
} }
/** Generates a extended private key from the provided seed and version */ /** Generates a extended private key from the provided seed and version */

View File

@ -2,7 +2,7 @@ package org.bitcoins.core.crypto
import java.security.SecureRandom import java.security.SecureRandom
import org.bitcoins.core.util.{CryptoUtil, MaskedToString} import org.bitcoins.core.util.{CryptoUtil, MaskedToString, SeqWrapper}
import scodec.bits.{BitVector, ByteVector} import scodec.bits.{BitVector, ByteVector}
import scala.annotation.tailrec import scala.annotation.tailrec
@ -16,7 +16,9 @@ import scala.io.Source
* can be the root of a [[https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]] * can be the root of a [[https://github.com/bitcoin/bips/blob/master/bip-0032.mediawiki BIP32]]
* HD wallet. * HD wallet.
*/ */
sealed abstract class MnemonicCode extends MaskedToString { sealed abstract class MnemonicCode
extends SeqWrapper[String]
with MaskedToString {
require( require(
MnemonicCode.VALID_LENGTHS.contains(words.length), { MnemonicCode.VALID_LENGTHS.contains(words.length), {
val validLengths = MnemonicCode.VALID_LENGTHS.mkString(", ") val validLengths = MnemonicCode.VALID_LENGTHS.mkString(", ")
@ -51,6 +53,8 @@ sealed abstract class MnemonicCode extends MaskedToString {
*/ */
def words: Vector[String] def words: Vector[String]
override protected lazy val wrapped: Vector[String] = words
/** /**
* Returns the entropy initially provided to construct * Returns the entropy initially provided to construct
* this mnemonic code * this mnemonic code

View File

@ -86,7 +86,7 @@ sealed trait WitnessTxSigComponent extends TxSigComponent {
override def transaction: WitnessTransaction override def transaction: WitnessTransaction
def witness: ScriptWitness = transaction.witness.witnesses(inputIndex.toInt) def witness: ScriptWitness = transaction.witness(inputIndex.toInt)
def witnessVersion: WitnessVersion def witnessVersion: WitnessVersion

View File

@ -2,11 +2,12 @@ package org.bitcoins.core.hd
import org.bitcoins.core.crypto.ExtKey import org.bitcoins.core.crypto.ExtKey
import org.bitcoins.core.number.UInt32 import org.bitcoins.core.number.UInt32
import org.bitcoins.core.util.Factory import org.bitcoins.core.util.{Factory, SeqWrapper}
import scodec.bits.ByteVector import scodec.bits.ByteVector
abstract class BIP32Path { abstract class BIP32Path extends SeqWrapper[BIP32Node] {
def path: Vector[BIP32Node] def path: Vector[BIP32Node]
override protected lazy val wrapped: Vector[BIP32Node] = path
/** /**
* BIP32 paths can be subsets/superset of each other. * BIP32 paths can be subsets/superset of each other.
@ -31,12 +32,11 @@ abstract class BIP32Path {
* m/44'/1'/0 diff m/44'/2'/1 == None * m/44'/1'/0 diff m/44'/2'/1 == None
* }}} * }}}
*/ */
def diff(that: BIP32Path): Option[BIP32Path] = { def diff(otherPath: BIP32Path): Option[BIP32Path] = {
import that.{path => otherPath}
if (path.length > otherPath.length) { if (path.length > otherPath.length) {
None None
} else if (path == otherPath) { } else if (this.toVector == otherPath.toVector) {
Some(BIP32Path.empty) Some(BIP32Path.empty)
} else { } else {
val lengthDiff = otherPath.length - path.length val lengthDiff = otherPath.length - path.length
@ -64,7 +64,7 @@ abstract class BIP32Path {
// append the next divergent element to // append the next divergent element to
// the acummed value // the acummed value
case (Some(accum), ((None, their), _)) => case (Some(accum), ((None, their), _)) =>
Some(BIP32Path(accum.path :+ their)) Some(BIP32Path((accum :+ their).toVector))
// we've not yet reached the start of diverging // we've not yet reached the start of diverging
// paths // paths

View File

@ -53,6 +53,6 @@ object HDAccount {
} }
def isSameAccount(bip32Path: BIP32Path, account: HDAccount): Boolean = { def isSameAccount(bip32Path: BIP32Path, account: HDAccount): Boolean = {
isSameAccount(bip32Path.path, account) isSameAccount(bip32Path.toVector, account)
} }
} }

View File

@ -15,7 +15,7 @@ sealed abstract class CompactSizeUInt extends NetworkElement {
/** The number parsed from VarInt. */ /** The number parsed from VarInt. */
def num: UInt64 def num: UInt64
override def hex = size match { override def hex = byteSize match {
case 1 => BitcoinSUtil.flipEndianness(num.hex.slice(14, 16)) case 1 => BitcoinSUtil.flipEndianness(num.hex.slice(14, 16))
case 3 => "fd" + BitcoinSUtil.flipEndianness(num.hex.slice(12, 16)) case 3 => "fd" + BitcoinSUtil.flipEndianness(num.hex.slice(12, 16))
case 5 => "fe" + BitcoinSUtil.flipEndianness(num.hex.slice(8, 16)) case 5 => "fe" + BitcoinSUtil.flipEndianness(num.hex.slice(8, 16))
@ -37,7 +37,9 @@ sealed abstract class CompactSizeUInt extends NetworkElement {
} }
object CompactSizeUInt extends Factory[CompactSizeUInt] { object CompactSizeUInt extends Factory[CompactSizeUInt] {
private case class CompactSizeUIntImpl(num: UInt64, override val size: Long) private case class CompactSizeUIntImpl(
num: UInt64,
override val byteSize: Long)
extends CompactSizeUInt extends CompactSizeUInt
val zero: CompactSizeUInt = CompactSizeUInt(UInt64.zero) val zero: CompactSizeUInt = CompactSizeUInt(UInt64.zero)

View File

@ -11,7 +11,7 @@ import scodec.bits.ByteVector
trait NetworkElement extends Any { trait NetworkElement extends Any {
/** The size of the NetworkElement in bytes. */ /** The size of the NetworkElement in bytes. */
def size: Long = bytes.size def byteSize: Long = bytes.size
/** The hexadecimal representation of the NetworkElement */ /** The hexadecimal representation of the NetworkElement */
def hex: String = bytes.toHex def hex: String = bytes.toHex

View File

@ -3,7 +3,7 @@ package org.bitcoins.core.protocol.ln
import org.bitcoins.core.number.{UInt5, UInt8} import org.bitcoins.core.number.{UInt5, UInt8}
import org.bitcoins.core.protocol.NetworkElement import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.protocol.ln.util.LnUtil import org.bitcoins.core.protocol.ln.util.LnUtil
import org.bitcoins.core.util.Bech32 import org.bitcoins.core.util.{Bech32, SeqWrapper}
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scala.annotation.tailrec import scala.annotation.tailrec
@ -13,7 +13,9 @@ import scala.reflect.ClassTag
/** /**
* An aggregation of all the individual tagged fields in a [[org.bitcoins.core.protocol.ln.LnInvoice]] * An aggregation of all the individual tagged fields in a [[org.bitcoins.core.protocol.ln.LnInvoice]]
*/ */
sealed abstract class LnTaggedFields extends NetworkElement { sealed abstract class LnTaggedFields
extends SeqWrapper[LnTag]
with NetworkElement {
require(tag[LnTag.PaymentHashTag].nonEmpty, "You must supply a payment hash") require(tag[LnTag.PaymentHashTag].nonEmpty, "You must supply a payment hash")
require( require(
@ -26,6 +28,8 @@ sealed abstract class LnTaggedFields extends NetworkElement {
def tags: Vector[LnTag] def tags: Vector[LnTag]
override protected lazy val wrapped: Vector[LnTag] = tags
def tag[T <: LnTag: ClassTag]: Option[T] = def tag[T <: LnTag: ClassTag]: Option[T] =
tags.collectFirst { tags.collectFirst {
case t: T => t case t: T => t

View File

@ -10,7 +10,7 @@ import org.bitcoins.core.protocol.ln.node.NodeId
import org.bitcoins.core.protocol.ln.routing.LnRoute import org.bitcoins.core.protocol.ln.routing.LnRoute
import org.bitcoins.core.protocol.ln.util.LnUtil import org.bitcoins.core.protocol.ln.util.LnUtil
import org.bitcoins.core.protocol.script.{P2WPKHWitnessSPKV0, P2WSHWitnessSPKV0} import org.bitcoins.core.protocol.script.{P2WPKHWitnessSPKV0, P2WSHWitnessSPKV0}
import org.bitcoins.core.util.{Bech32, CryptoUtil} import org.bitcoins.core.util.{Bech32, CryptoUtil, SeqWrapper}
import scodec.bits.ByteVector import scodec.bits.ByteVector
import scala.annotation.tailrec import scala.annotation.tailrec
@ -19,7 +19,7 @@ import scala.annotation.tailrec
* One of the tagged fields on a Lightning Network invoice * One of the tagged fields on a Lightning Network invoice
* [[https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md#tagged-fields]] * [[https://github.com/lightningnetwork/lightning-rfc/blob/master/11-payment-encoding.md#tagged-fields]]
*/ */
sealed abstract class LnTag { sealed trait LnTag {
def prefix: LnTagPrefix def prefix: LnTagPrefix
@ -217,7 +217,10 @@ object LnTag {
} }
} }
case class RoutingInfo(routes: Vector[LnRoute]) extends LnTag { case class RoutingInfo(routes: Vector[LnRoute])
extends SeqWrapper[LnRoute]
with LnTag {
override protected val wrapped: Vector[LnRoute] = routes
override val prefix: LnTagPrefix = LnTagPrefix.RoutingInfo override val prefix: LnTagPrefix = LnTagPrefix.RoutingInfo
@ -247,7 +250,7 @@ object LnTag {
accum accum
} else { } else {
val route = LnRoute.fromBytes(remaining) val route = LnRoute.fromBytes(remaining)
val newRemaining = remaining.slice(route.size, remaining.size) val newRemaining = remaining.slice(route.byteSize, remaining.size)
loop(newRemaining, accum.:+(route)) loop(newRemaining, accum.:+(route))
} }
} }

View File

@ -71,7 +71,7 @@ sealed abstract class Transaction extends NetworkElement {
* [[https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#Transaction_size_calculations]] * [[https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#Transaction_size_calculations]]
*/ */
def baseSize: Long = this match { def baseSize: Long = this match {
case btx: BaseTransaction => btx.size case btx: BaseTransaction => btx.byteSize
case wtx: WitnessTransaction => case wtx: WitnessTransaction =>
BaseTransaction(wtx.version, wtx.inputs, wtx.outputs, wtx.lockTime).baseSize BaseTransaction(wtx.version, wtx.inputs, wtx.outputs, wtx.lockTime).baseSize
} }
@ -106,7 +106,7 @@ sealed abstract class Transaction extends NetworkElement {
sealed abstract class BaseTransaction extends Transaction { sealed abstract class BaseTransaction extends Transaction {
override def bytes = RawBaseTransactionParser.write(this) override def bytes = RawBaseTransactionParser.write(this)
override def weight = size * 4 override def weight = byteSize * 4
} }
@ -120,8 +120,8 @@ case object EmptyTransaction extends BaseTransaction {
sealed abstract class WitnessTransaction extends Transaction { sealed abstract class WitnessTransaction extends Transaction {
require( require(
inputs.length == witness.witnesses.length, inputs.length == witness.length,
s"Must have same amount of inputs and witnesses in witness tx, inputs=${inputs.length} witnesses=${witness.witnesses.length}" s"Must have same amount of inputs and witnesses in witness tx, inputs=${inputs.length} witnesses=${witness.length}"
) )
/** The txId for the witness transaction from satoshi's original serialization */ /** The txId for the witness transaction from satoshi's original serialization */
@ -153,7 +153,7 @@ sealed abstract class WitnessTransaction extends Transaction {
*/ */
override def weight: Long = { override def weight: Long = {
val base = BaseTransaction(version, inputs, outputs, lockTime) val base = BaseTransaction(version, inputs, outputs, lockTime)
base.size * 3 + size base.byteSize * 3 + byteSize
} }
override def bytes = RawWitnessTransactionParser.write(this) override def bytes = RawWitnessTransactionParser.write(this)

View File

@ -11,7 +11,7 @@ case class TransactionOutput(value: CurrencyUnit, scriptPubKey: ScriptPubKey)
extends NetworkElement { extends NetworkElement {
//https://bitcoin.org/en/developer-reference#txout //https://bitcoin.org/en/developer-reference#txout
override def size = scriptPubKey.size + 8 override def byteSize = scriptPubKey.byteSize + 8
override def bytes = RawTransactionOutputParser.write(this) override def bytes = RawTransactionOutputParser.write(this)
} }

View File

@ -3,7 +3,7 @@ package org.bitcoins.core.protocol.transaction
import org.bitcoins.core.protocol.NetworkElement import org.bitcoins.core.protocol.NetworkElement
import org.bitcoins.core.protocol.script.{EmptyScriptWitness, ScriptWitness} import org.bitcoins.core.protocol.script.{EmptyScriptWitness, ScriptWitness}
import org.bitcoins.core.serializers.transaction.RawTransactionWitnessParser import org.bitcoins.core.serializers.transaction.RawTransactionWitnessParser
import org.bitcoins.core.util.BitcoinSUtil import org.bitcoins.core.util.{BitcoinSUtil, SeqWrapper}
import scodec.bits.ByteVector import scodec.bits.ByteVector
/** /**
@ -11,8 +11,11 @@ import scodec.bits.ByteVector
* The witness data for [[org.bitcoins.core.protocol.script.ScriptSignature ScriptSignature]] in this transaction * The witness data for [[org.bitcoins.core.protocol.script.ScriptSignature ScriptSignature]] in this transaction
* [[https://github.com/bitcoin/bitcoin/blob/b4e4ba475a5679e09f279aaf2a83dcf93c632bdb/src/primitives/transaction.h#L232-L268]] * [[https://github.com/bitcoin/bitcoin/blob/b4e4ba475a5679e09f279aaf2a83dcf93c632bdb/src/primitives/transaction.h#L232-L268]]
*/ */
sealed abstract class TransactionWitness extends NetworkElement { sealed abstract class TransactionWitness
extends SeqWrapper[ScriptWitness]
with NetworkElement {
val witnesses: Vector[ScriptWitness] val witnesses: Vector[ScriptWitness]
override protected val wrapped: Vector[ScriptWitness] = witnesses
override def bytes: ByteVector = { override def bytes: ByteVector = {
RawTransactionWitnessParser.write(this) RawTransactionWitnessParser.write(this)

View File

@ -387,7 +387,7 @@ case class PSBT(
if (!previousElements.exists(_.key == expectedBytes)) { if (!previousElements.exists(_.key == expectedBytes)) {
val fp = val fp =
if (extKey.fingerprint == ExtKey.masterFingerprint) { if (extKey.fingerprint == ExtKey.masterFingerprint) {
extKey.deriveChildPubKey(path.path.head).get.fingerprint extKey.deriveChildPubKey(path.head).get.fingerprint
} else { } else {
extKey.fingerprint extKey.fingerprint
} }
@ -579,7 +579,7 @@ case class PSBT(
case Some( case Some(
InputPSBTRecord.FinalizedScriptWitness(scriptWitness)) => InputPSBTRecord.FinalizedScriptWitness(scriptWitness)) =>
TransactionWitness( TransactionWitness(
witness.witnesses.updated(index, scriptWitness)) witness.updated(index, scriptWitness).toVector)
} }
} }
WitnessTransaction(transaction.version, WitnessTransaction(transaction.version,

View File

@ -13,7 +13,7 @@ import org.bitcoins.core.protocol.transaction.{
WitnessTransaction WitnessTransaction
} }
import org.bitcoins.core.script.crypto.HashType import org.bitcoins.core.script.crypto.HashType
import org.bitcoins.core.util.{CryptoUtil, Factory} import org.bitcoins.core.util.{CryptoUtil, Factory, SeqWrapper}
import org.bitcoins.core.wallet.signer.{BitcoinSigner, BitcoinSignerSingle} import org.bitcoins.core.wallet.signer.{BitcoinSigner, BitcoinSignerSingle}
import org.bitcoins.core.wallet.utxo._ import org.bitcoins.core.wallet.utxo._
import scodec.bits.ByteVector import scodec.bits.ByteVector
@ -87,11 +87,13 @@ sealed trait PSBTMapFactory[
} }
case class GlobalPSBTMap(elements: Vector[GlobalPSBTRecord]) case class GlobalPSBTMap(elements: Vector[GlobalPSBTRecord])
extends PSBTMap[GlobalPSBTRecord] { extends SeqWrapper[GlobalPSBTRecord]
with PSBTMap[GlobalPSBTRecord] {
import org.bitcoins.core.psbt.GlobalPSBTRecord._ import org.bitcoins.core.psbt.GlobalPSBTRecord._
import org.bitcoins.core.psbt.PSBTGlobalKeyId._ import org.bitcoins.core.psbt.PSBTGlobalKeyId._
require(getRecords(UnsignedTransactionKeyId).nonEmpty, require(getRecords(UnsignedTransactionKeyId).nonEmpty,
"A GlobalPSBTMap must have a Unsigned Transaction") "A GlobalPSBTMap must have a Unsigned Transaction")
override val wrapped: Vector[GlobalPSBTRecord] = elements
def unsignedTransaction: UnsignedTransaction = { def unsignedTransaction: UnsignedTransaction = {
getRecords(UnsignedTransactionKeyId).head getRecords(UnsignedTransactionKeyId).head
@ -150,11 +152,14 @@ object GlobalPSBTMap extends PSBTMapFactory[GlobalPSBTRecord, GlobalPSBTMap] {
} }
case class InputPSBTMap(elements: Vector[InputPSBTRecord]) case class InputPSBTMap(elements: Vector[InputPSBTRecord])
extends PSBTMap[InputPSBTRecord] { extends SeqWrapper[InputPSBTRecord]
with PSBTMap[InputPSBTRecord] {
require( require(
this.witnessUTXOOpt.isEmpty || this.nonWitnessOrUnknownUTXOOpt.isEmpty, this.witnessUTXOOpt.isEmpty || this.nonWitnessOrUnknownUTXOOpt.isEmpty,
"InputPSBTMap cannot have both a NonWitnessOrUnknownUTXO and a WitnessUTXO" "InputPSBTMap cannot have both a NonWitnessOrUnknownUTXO and a WitnessUTXO"
) )
override protected val wrapped: Vector[InputPSBTRecord] = elements
import org.bitcoins.core.psbt.InputPSBTRecord._ import org.bitcoins.core.psbt.InputPSBTRecord._
import org.bitcoins.core.psbt.PSBTInputKeyId._ import org.bitcoins.core.psbt.PSBTInputKeyId._
@ -642,7 +647,7 @@ object InputPSBTMap extends PSBTMapFactory[InputPSBTRecord, InputPSBTMap] {
sigComponent.transaction match { sigComponent.transaction match {
case _: BaseTransaction => InputPSBTMap(utxos ++ Vector(scriptSig)) case _: BaseTransaction => InputPSBTMap(utxos ++ Vector(scriptSig))
case wtx: WitnessTransaction => case wtx: WitnessTransaction =>
val witness = wtx.witness.witnesses(sigComponent.inputIndex.toInt) val witness = wtx.witness(sigComponent.inputIndex.toInt)
val scriptWitness = FinalizedScriptWitness(witness) val scriptWitness = FinalizedScriptWitness(witness)
val finalizedSigs = val finalizedSigs =
if (witness != EmptyScriptWitness) { if (witness != EmptyScriptWitness) {
@ -721,10 +726,13 @@ object InputPSBTMap extends PSBTMapFactory[InputPSBTRecord, InputPSBTMap] {
override def recordFactory: Factory[InputPSBTRecord] = InputPSBTRecord override def recordFactory: Factory[InputPSBTRecord] = InputPSBTRecord
} }
case class OutputPSBTMap(elements: Vector[OutputPSBTRecord]) case class OutputPSBTMap(elements: Vector[OutputPSBTRecord])
extends PSBTMap[OutputPSBTRecord] { extends SeqWrapper[OutputPSBTRecord]
with PSBTMap[OutputPSBTRecord] {
import org.bitcoins.core.psbt.OutputPSBTRecord._ import org.bitcoins.core.psbt.OutputPSBTRecord._
import org.bitcoins.core.psbt.PSBTOutputKeyId._ import org.bitcoins.core.psbt.PSBTOutputKeyId._
override val wrapped: Vector[OutputPSBTRecord] = elements
def redeemScriptOpt: Option[RedeemScript] = { def redeemScriptOpt: Option[RedeemScript] = {
getRecords(RedeemScriptKeyId).headOption getRecords(RedeemScriptKeyId).headOption
} }

View File

@ -39,11 +39,11 @@ object PSBTRecord {
if (keyCmpctUInt.toLong == 0) { if (keyCmpctUInt.toLong == 0) {
(ByteVector.empty, ByteVector.empty) (ByteVector.empty, ByteVector.empty)
} else { } else {
val key = bytes.drop(keyCmpctUInt.size).take(keyCmpctUInt.toLong) val key = bytes.drop(keyCmpctUInt.byteSize).take(keyCmpctUInt.toLong)
val valueBytes = bytes.drop(keyCmpctUInt.size + keyCmpctUInt.toLong) val valueBytes = bytes.drop(keyCmpctUInt.byteSize + keyCmpctUInt.toLong)
val valueCmpctUInt = CompactSizeUInt.parse(valueBytes) val valueCmpctUInt = CompactSizeUInt.parse(valueBytes)
val value = valueBytes val value = valueBytes
.drop(valueCmpctUInt.size) .drop(valueCmpctUInt.byteSize)
.take(valueCmpctUInt.toLong) .take(valueCmpctUInt.toLong)
(key, value) (key, value)
@ -74,8 +74,8 @@ object GlobalPSBTRecord extends Factory[GlobalPSBTRecord] {
derivationPath: BIP32Path) derivationPath: BIP32Path)
extends GlobalPSBTRecord { extends GlobalPSBTRecord {
require( require(
derivationPath.path.length == xpub.depth.toInt, derivationPath.length == xpub.depth.toInt,
s"Derivation path length does not match xpubkey depth, difference: ${derivationPath.path.length - xpub.depth.toInt}" s"Derivation path length does not match xpubkey depth, difference: ${derivationPath.length - xpub.depth.toInt}"
) )
require( require(
masterFingerprint.length == 4, masterFingerprint.length == 4,
@ -83,7 +83,7 @@ object GlobalPSBTRecord extends Factory[GlobalPSBTRecord] {
override type KeyId = XPubKeyKeyId.type override type KeyId = XPubKeyKeyId.type
override val key: ByteVector = ByteVector(XPubKeyKeyId.byte) ++ xpub.bytes override val key: ByteVector = ByteVector(XPubKeyKeyId.byte) ++ xpub.bytes
override val value: ByteVector = derivationPath.path override val value: ByteVector = derivationPath
.foldLeft(masterFingerprint)(_ ++ _.toUInt32.bytesLE) .foldLeft(masterFingerprint)(_ ++ _.toUInt32.bytesLE)
} }
@ -155,7 +155,8 @@ object InputPSBTRecord extends Factory[InputPSBTRecord] {
pubKey: ECPublicKey, pubKey: ECPublicKey,
signature: ECDigitalSignature) signature: ECDigitalSignature)
extends InputPSBTRecord { extends InputPSBTRecord {
require(pubKey.size == 33, s"pubKey must be 33 bytes, got: ${pubKey.size}") require(pubKey.byteSize == 33,
s"pubKey must be 33 bytes, got: ${pubKey.byteSize}")
override type KeyId = PartialSignatureKeyId.type override type KeyId = PartialSignatureKeyId.type
override val key: ByteVector = ByteVector(PartialSignatureKeyId.byte) ++ pubKey.bytes override val key: ByteVector = ByteVector(PartialSignatureKeyId.byte) ++ pubKey.bytes
@ -186,12 +187,13 @@ object InputPSBTRecord extends Factory[InputPSBTRecord] {
masterFingerprint: ByteVector, masterFingerprint: ByteVector,
path: BIP32Path) path: BIP32Path)
extends InputPSBTRecord { extends InputPSBTRecord {
require(pubKey.size == 33, s"pubKey must be 33 bytes, got: ${pubKey.size}") require(pubKey.byteSize == 33,
s"pubKey must be 33 bytes, got: ${pubKey.byteSize}")
override type KeyId = BIP32DerivationPathKeyId.type override type KeyId = BIP32DerivationPathKeyId.type
override val key: ByteVector = ByteVector(BIP32DerivationPathKeyId.byte) ++ pubKey.bytes override val key: ByteVector = ByteVector(BIP32DerivationPathKeyId.byte) ++ pubKey.bytes
override val value: ByteVector = override val value: ByteVector =
path.path.foldLeft(masterFingerprint)(_ ++ _.toUInt32.bytesLE) path.foldLeft(masterFingerprint)(_ ++ _.toUInt32.bytesLE)
} }
case class FinalizedScriptSig(scriptSig: ScriptSignature) case class FinalizedScriptSig(scriptSig: ScriptSignature)
@ -307,12 +309,13 @@ object OutputPSBTRecord extends Factory[OutputPSBTRecord] {
masterFingerprint: ByteVector, masterFingerprint: ByteVector,
path: BIP32Path) path: BIP32Path)
extends OutputPSBTRecord { extends OutputPSBTRecord {
require(pubKey.size == 33, s"pubKey must be 33 bytes, got: ${pubKey.size}") require(pubKey.byteSize == 33,
s"pubKey must be 33 bytes, got: ${pubKey.byteSize}")
override type KeyId = BIP32DerivationPathKeyId.type override type KeyId = BIP32DerivationPathKeyId.type
override val key: ByteVector = ByteVector(BIP32DerivationPathKeyId.byte) ++ pubKey.bytes override val key: ByteVector = ByteVector(BIP32DerivationPathKeyId.byte) ++ pubKey.bytes
override val value: ByteVector = override val value: ByteVector =
path.path.foldLeft(masterFingerprint)(_ ++ _.toUInt32.bytesLE) path.foldLeft(masterFingerprint)(_ ++ _.toUInt32.bytesLE)
} }
case class Unknown(key: ByteVector, value: ByteVector) case class Unknown(key: ByteVector, value: ByteVector)

View File

@ -1130,17 +1130,11 @@ sealed abstract class ScriptInterpreter extends BitcoinSLogger {
case b: BaseTxSigComponent => case b: BaseTxSigComponent =>
b.transaction match { b.transaction match {
case wtx: WitnessTransaction => case wtx: WitnessTransaction =>
wtx.witness wtx.witness(txSigComponent.inputIndex.toInt).stack.nonEmpty
.witnesses(txSigComponent.inputIndex.toInt)
.stack
.nonEmpty
case _: BaseTransaction => false case _: BaseTransaction => false
} }
case r: WitnessTxSigComponentRebuilt => case r: WitnessTxSigComponentRebuilt =>
r.transaction.witness r.transaction.witness(txSigComponent.inputIndex.toInt).stack.nonEmpty
.witnesses(txSigComponent.inputIndex.toInt)
.stack
.nonEmpty
} }
if (unexpectedWitness) if (unexpectedWitness)

View File

@ -19,7 +19,7 @@ sealed abstract class RawSerializerHelper {
bytes: ByteVector, bytes: ByteVector,
constructor: ByteVector => T): (Seq[T], ByteVector) = { constructor: ByteVector => T): (Seq[T], ByteVector) = {
val count = CompactSizeUInt.parse(bytes) val count = CompactSizeUInt.parse(bytes)
val payload = bytes.splitAt(count.size.toInt)._2 val payload = bytes.splitAt(count.byteSize.toInt)._2
var counter = 0 var counter = 0
val b = Vector.newBuilder[T] val b = Vector.newBuilder[T]
@tailrec @tailrec
@ -28,7 +28,7 @@ sealed abstract class RawSerializerHelper {
remaining remaining
} else { } else {
val parsed = constructor(remaining) val parsed = constructor(remaining)
val (_, newRemaining) = remaining.splitAt(parsed.size) val (_, newRemaining) = remaining.splitAt(parsed.byteSize)
counter = counter + 1 counter = counter + 1
b.+=(parsed) b.+=(parsed)

View File

@ -15,9 +15,9 @@ sealed abstract class RawBloomFilterSerializer
override def read(bytes: ByteVector): BloomFilter = { override def read(bytes: ByteVector): BloomFilter = {
val filterSize = CompactSizeUInt.parseCompactSizeUInt(bytes) val filterSize = CompactSizeUInt.parseCompactSizeUInt(bytes)
val filter = bytes.slice(filterSize.size.toInt, val filter = bytes.slice(filterSize.byteSize.toInt,
filterSize.size.toInt + filterSize.num.toInt) filterSize.byteSize.toInt + filterSize.num.toInt)
val hashFuncsIndex = (filterSize.size + filterSize.num.toInt).toInt val hashFuncsIndex = (filterSize.byteSize + filterSize.num.toInt).toInt
val hashFuncs = UInt32( val hashFuncs = UInt32(
bytes.slice(hashFuncsIndex, hashFuncsIndex + 4).reverse) bytes.slice(hashFuncsIndex, hashFuncsIndex + 4).reverse)
val tweakIndex = hashFuncsIndex + 4 val tweakIndex = hashFuncsIndex + 4

View File

@ -16,7 +16,7 @@ trait RawAddrMessageSerializer extends RawBitcoinSerializer[AddrMessage] {
override def read(bytes: ByteVector): AddrMessage = { override def read(bytes: ByteVector): AddrMessage = {
val ipCount = CompactSizeUInt.parseCompactSizeUInt(bytes) val ipCount = CompactSizeUInt.parseCompactSizeUInt(bytes)
val ipAddressBytes = bytes.slice(ipCount.size.toInt, bytes.size) val ipAddressBytes = bytes.slice(ipCount.byteSize.toInt, bytes.size)
val (networkIpAddresses, _) = val (networkIpAddresses, _) =
parseNetworkIpAddresses(ipCount, ipAddressBytes) parseNetworkIpAddresses(ipCount, ipAddressBytes)
AddrMessage(ipCount, networkIpAddresses) AddrMessage(ipCount, networkIpAddresses)
@ -48,7 +48,7 @@ trait RawAddrMessageSerializer extends RawBitcoinSerializer[AddrMessage] {
val networkIpAddress = val networkIpAddress =
RawNetworkIpAddressSerializer.read(remainingBytes) RawNetworkIpAddressSerializer.read(remainingBytes)
val newRemainingBytes = val newRemainingBytes =
remainingBytes.slice(networkIpAddress.size, remainingBytes.size) remainingBytes.slice(networkIpAddress.byteSize, remainingBytes.size)
loop(remainingAddresses - 1, loop(remainingAddresses - 1,
newRemainingBytes, newRemainingBytes,
networkIpAddress :: accum) networkIpAddress :: accum)

View File

@ -14,7 +14,7 @@ trait RawFilterAddMessageSerializer
override def read(bytes: ByteVector): FilterAddMessage = { override def read(bytes: ByteVector): FilterAddMessage = {
val elementSize = CompactSizeUInt.parseCompactSizeUInt(bytes) val elementSize = CompactSizeUInt.parseCompactSizeUInt(bytes)
val element = bytes.slice(elementSize.size.toInt, bytes.size) val element = bytes.slice(elementSize.byteSize.toInt, bytes.size)
FilterAddMessage(elementSize, element) FilterAddMessage(elementSize, element)
} }

View File

@ -20,7 +20,7 @@ trait RawGetBlocksMessageSerializer
val version = ProtocolVersion(bytes.take(4)) val version = ProtocolVersion(bytes.take(4))
val hashCount = val hashCount =
CompactSizeUInt.parseCompactSizeUInt(bytes.slice(4, bytes.size)) CompactSizeUInt.parseCompactSizeUInt(bytes.slice(4, bytes.size))
val blockHeaderStartByte = (hashCount.size + 4).toInt val blockHeaderStartByte = (hashCount.byteSize + 4).toInt
val blockHeaderBytesStopHash = bytes.slice(blockHeaderStartByte, bytes.size) val blockHeaderBytesStopHash = bytes.slice(blockHeaderStartByte, bytes.size)
val (blockHashHeaders, remainingBytes) = val (blockHashHeaders, remainingBytes) =
parseBlockHeaders(blockHeaderBytesStopHash, hashCount) parseBlockHeaders(blockHeaderBytesStopHash, hashCount)

View File

@ -15,7 +15,7 @@ trait RawGetHeadersMessageSerializer
val version = ProtocolVersion(bytes.take(4)) val version = ProtocolVersion(bytes.take(4))
val hashCount = val hashCount =
CompactSizeUInt.parseCompactSizeUInt(bytes.slice(4, bytes.length)) CompactSizeUInt.parseCompactSizeUInt(bytes.slice(4, bytes.length))
val hashesStartIndex = (hashCount.size + 4).toInt val hashesStartIndex = (hashCount.byteSize + 4).toInt
val (hashes, remainingBytes) = val (hashes, remainingBytes) =
parseHashes(bytes.slice(hashesStartIndex, bytes.length), hashCount) parseHashes(bytes.slice(hashesStartIndex, bytes.length), hashCount)
val hashStop = DoubleSha256Digest(remainingBytes.take(32)) val hashStop = DoubleSha256Digest(remainingBytes.take(32))

View File

@ -12,7 +12,7 @@ trait RawHeadersMessageSerializer extends RawBitcoinSerializer[HeadersMessage] {
def read(bytes: ByteVector): HeadersMessage = { def read(bytes: ByteVector): HeadersMessage = {
val compactSizeUInt = CompactSizeUInt.parseCompactSizeUInt(bytes) val compactSizeUInt = CompactSizeUInt.parseCompactSizeUInt(bytes)
val headerStartIndex = compactSizeUInt.size.toInt val headerStartIndex = compactSizeUInt.byteSize.toInt
val headerBytes = bytes.slice(headerStartIndex, bytes.length) val headerBytes = bytes.slice(headerStartIndex, bytes.length)
val headers = parseBlockHeaders(headerBytes, compactSizeUInt) val headers = parseBlockHeaders(headerBytes, compactSizeUInt)
HeadersMessage(compactSizeUInt, headers) HeadersMessage(compactSizeUInt, headers)

View File

@ -19,7 +19,7 @@ trait RawInventoryMessageSerializer
*/ */
override def read(bytes: ByteVector): InventoryMessage = { override def read(bytes: ByteVector): InventoryMessage = {
val inventoryCount = CompactSizeUInt.parseCompactSizeUInt(bytes) val inventoryCount = CompactSizeUInt.parseCompactSizeUInt(bytes)
val inventoryStart = inventoryCount.size.toInt val inventoryStart = inventoryCount.byteSize.toInt
val remainingBytes = bytes.slice(inventoryStart, bytes.size) val remainingBytes = bytes.slice(inventoryStart, bytes.size)
val (inventories, _) = parseInventories(remainingBytes, inventoryCount) val (inventories, _) = parseInventories(remainingBytes, inventoryCount)
InventoryMessage(inventoryCount, inventories) InventoryMessage(inventoryCount, inventories)

View File

@ -11,24 +11,24 @@ trait RawRejectMessageSerializer extends RawBitcoinSerializer[RejectMessage] {
def read(bytes: ByteVector): RejectMessage = { def read(bytes: ByteVector): RejectMessage = {
val messageSize = CompactSizeUInt.parseCompactSizeUInt(bytes) val messageSize = CompactSizeUInt.parseCompactSizeUInt(bytes)
val message: String = bytes val message: String = bytes
.slice(messageSize.size.toInt, .slice(messageSize.byteSize.toInt,
messageSize.size.toInt + messageSize.byteSize.toInt +
messageSize.num.toInt) messageSize.num.toInt)
.toArray .toArray
.map(_.toChar) .map(_.toChar)
.mkString .mkString
val code: Char = bytes(messageSize.size.toInt + messageSize.num.toInt).toChar val code: Char = bytes(messageSize.byteSize.toInt + messageSize.num.toInt).toChar
val reasonSizeStartIndex = messageSize.size.toInt + messageSize.num.toInt + 1 val reasonSizeStartIndex = messageSize.byteSize.toInt + messageSize.num.toInt + 1
val reasonSize = CompactSizeUInt.parseCompactSizeUInt( val reasonSize = CompactSizeUInt.parseCompactSizeUInt(
bytes.slice(reasonSizeStartIndex.toInt, bytes.size)) bytes.slice(reasonSizeStartIndex.toInt, bytes.size))
val reason = bytes val reason = bytes
.slice( .slice(
(reasonSizeStartIndex + reasonSize.size).toInt, (reasonSizeStartIndex + reasonSize.byteSize).toInt,
(reasonSizeStartIndex + reasonSize.size.toInt + reasonSize.num.toInt)) (reasonSizeStartIndex + reasonSize.byteSize.toInt + reasonSize.num.toInt))
.toArray .toArray
.map(_.toChar) .map(_.toChar)
.mkString .mkString
val extraStartIndex = (reasonSizeStartIndex + reasonSize.size.toInt + reasonSize.num.toInt) val extraStartIndex = (reasonSizeStartIndex + reasonSize.byteSize.toInt + reasonSize.num.toInt)
val extra = bytes.slice(extraStartIndex, bytes.size) val extra = bytes.slice(extraStartIndex, bytes.size)
RejectMessage(messageSize, message, code, reasonSize, reason, extra) RejectMessage(messageSize, message, code, reasonSize, reason, extra)
} }

View File

@ -43,7 +43,7 @@ trait RawVersionMessageSerializer
val userAgentSize = val userAgentSize =
CompactSizeUInt.parseCompactSizeUInt(bytes.slice(80, bytes.size)) CompactSizeUInt.parseCompactSizeUInt(bytes.slice(80, bytes.size))
val userAgentBytesStartIndex = 80 + userAgentSize.size.toInt val userAgentBytesStartIndex = 80 + userAgentSize.byteSize.toInt
val userAgentBytes = bytes.slice( val userAgentBytes = bytes.slice(
userAgentBytesStartIndex, userAgentBytesStartIndex,

View File

@ -17,7 +17,7 @@ sealed abstract class RawScriptWitnessParser
def read(bytes: ByteVector): ScriptWitness = { def read(bytes: ByteVector): ScriptWitness = {
//first byte is the number of stack items //first byte is the number of stack items
val stackSize = CompactSizeUInt.parseCompactSizeUInt(bytes) val stackSize = CompactSizeUInt.parseCompactSizeUInt(bytes)
val (_, stackBytes) = bytes.splitAt(stackSize.size.toInt) val (_, stackBytes) = bytes.splitAt(stackSize.byteSize.toInt)
@tailrec @tailrec
def loop( def loop(
remainingBytes: ByteVector, remainingBytes: ByteVector,
@ -27,7 +27,7 @@ sealed abstract class RawScriptWitnessParser
else { else {
val elementSize = CompactSizeUInt.parseCompactSizeUInt(remainingBytes) val elementSize = CompactSizeUInt.parseCompactSizeUInt(remainingBytes)
val (_, stackElementBytes) = val (_, stackElementBytes) =
remainingBytes.splitAt(elementSize.size.toInt) remainingBytes.splitAt(elementSize.byteSize.toInt)
val stackElement = stackElementBytes.take(elementSize.num.toInt) val stackElement = stackElementBytes.take(elementSize.num.toInt)
val (_, newRemainingBytes) = val (_, newRemainingBytes) =
stackElementBytes.splitAt(stackElement.size) stackElementBytes.splitAt(stackElement.size)

View File

@ -38,7 +38,7 @@ sealed abstract class RawTransactionWitnessParser {
} }
def write(witness: TransactionWitness): ByteVector = { def write(witness: TransactionWitness): ByteVector = {
witness.witnesses.foldLeft(ByteVector.empty)(_ ++ _.bytes) witness.foldLeft(ByteVector.empty)(_ ++ _.bytes)
} }
} }

View File

@ -588,7 +588,8 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
//but scala collections don't allow you to use 'slice' with longs //but scala collections don't allow you to use 'slice' with longs
val len = Try(compactSizeUInt.num.toInt).getOrElse(Int.MaxValue) val len = Try(compactSizeUInt.num.toInt).getOrElse(Int.MaxValue)
val scriptPubKeyBytes = val scriptPubKeyBytes =
bytes.slice(compactSizeUInt.size.toInt, len + compactSizeUInt.size.toInt) bytes.slice(compactSizeUInt.byteSize.toInt,
len + compactSizeUInt.byteSize.toInt)
val script: List[ScriptToken] = ScriptParser.fromBytes(scriptPubKeyBytes) val script: List[ScriptToken] = ScriptParser.fromBytes(scriptPubKeyBytes)
f(script.toVector) f(script.toVector)
} }

View File

@ -0,0 +1,17 @@
package org.bitcoins.core.util
trait SeqWrapper[+T] extends IndexedSeq[T] {
protected def wrapped: IndexedSeq[T]
override def iterator: Iterator[T] = wrapped.iterator
override def length: Int = wrapped.length
override def apply(idx: Int): T = wrapped(idx)
}
trait MapWrapper[K, +T] extends Map[K, T] {
protected def wrapped: Map[K, T]
override def +[B1 >: T](kv: (K, B1)): Map[K, B1] = wrapped.+(kv)
override def get(key: K): Option[T] = wrapped.get(key)
override def iterator: Iterator[(K, T)] = wrapped.iterator
override def updated[V1 >: T](key: K, value: V1): Map[K, V1] =
wrapped.updated(key, value)
}

View File

@ -293,7 +293,7 @@ object BitcoinSignerSingle {
btx.lockTime, btx.lockTime,
transactionWitness) transactionWitness)
case wtx: WitnessTransaction => case wtx: WitnessTransaction =>
wtx.witness.witnesses(inputIndex) match { wtx.witness(inputIndex) match {
case EmptyScriptWitness => case EmptyScriptWitness =>
val transactionWitnessOpt = val transactionWitnessOpt =
psbt psbt
@ -740,8 +740,9 @@ sealed abstract class P2WPKHSigner
val pubKey = signer.publicKey val pubKey = signer.publicKey
val unsignedTxWitness = TransactionWitness( val unsignedTxWitness = TransactionWitness(
wtx.witness.witnesses wtx.witness
.updated(inputIndex.toInt, spendingInfoToSatisfy.scriptWitness)) .updated(inputIndex.toInt, spendingInfoToSatisfy.scriptWitness)
.toVector)
val unsignedWtx = WitnessTransaction(wtx.version, val unsignedWtx = WitnessTransaction(wtx.version,
wtx.inputs, wtx.inputs,