diff --git a/core-test/.jvm/src/test/scala/org/bitcoins/core/protocol/transaction/TaprootWalletTestCase.scala b/core-test/.jvm/src/test/scala/org/bitcoins/core/protocol/transaction/TaprootWalletTestCase.scala index 381613d874..639d4f7acd 100644 --- a/core-test/.jvm/src/test/scala/org/bitcoins/core/protocol/transaction/TaprootWalletTestCase.scala +++ b/core-test/.jvm/src/test/scala/org/bitcoins/core/protocol/transaction/TaprootWalletTestCase.scala @@ -1,9 +1,9 @@ package org.bitcoins.core.protocol.transaction import org.bitcoins.core.protocol.Bech32mAddress -import org.bitcoins.core.protocol.script._ +import org.bitcoins.core.protocol.script.* import org.bitcoins.crypto.{Sha256Digest, XOnlyPubKey} -import upickle.default._ +import upickle.default.* case class Given(internalPubkey: XOnlyPubKey, treeOpt: Option[TapscriptTree]) { @@ -74,7 +74,7 @@ object TaprootWalletTestCase { else if (`given`.objOpt.isDefined) { val givenObj = `given`.obj val script = ScriptPubKey.fromAsmHex(givenObj("script").str) - val leafVersion = givenObj("leafVersion").num.toByte + val leafVersion = LeafVersion.fromByte(givenObj("leafVersion").num.toByte) val leaf = TapLeaf(leafVersion, script) Some(leaf) } else { diff --git a/core-test/src/test/scala/org/bitcoins/core/protocol/script/TaprootWitnessTest.scala b/core-test/src/test/scala/org/bitcoins/core/protocol/script/TaprootWitnessTest.scala index 840e9e6107..dd27428e48 100644 --- a/core-test/src/test/scala/org/bitcoins/core/protocol/script/TaprootWitnessTest.scala +++ b/core-test/src/test/scala/org/bitcoins/core/protocol/script/TaprootWitnessTest.scala @@ -50,7 +50,7 @@ class TaprootWitnessTest extends BitcoinSUnitTest { "7520c7b5db9562078049719228db2ac80cb9643ec96c8055aa3b29c2c03d4d99edb0ac" val spk = ScriptPubKey.fromAsmHex(asmHex) assert(asmHex == spk.asmHex) - val leaf = TapLeaf(0xc0.toByte, spk) + val leaf = TapLeaf(LeafVersion.Tapscript, spk) val hash = TaprootScriptPath.computeTapleafHash(leaf) assert(hash.hex == expected) } diff --git a/core-test/src/test/scala/org/bitcoins/core/protocol/script/descriptor/DescriptorTest.scala b/core-test/src/test/scala/org/bitcoins/core/protocol/script/descriptor/DescriptorTest.scala index 218e8cf7d5..e6eeebf281 100644 --- a/core-test/src/test/scala/org/bitcoins/core/protocol/script/descriptor/DescriptorTest.scala +++ b/core-test/src/test/scala/org/bitcoins/core/protocol/script/descriptor/DescriptorTest.scala @@ -1,6 +1,6 @@ package org.bitcoins.core.protocol.script.descriptor -import org.bitcoins.core.protocol.script._ +import org.bitcoins.core.protocol.script.* import org.bitcoins.crypto.{ECPrivateKey, ECPublicKey} import org.bitcoins.testkitcore.util.BitcoinSUnitTest import org.scalatest.Assertion @@ -536,7 +536,7 @@ class DescriptorTest extends BitcoinSUnitTest { case pub: ECPublicKey => pub.toXOnly } val tree = - TapLeaf(TapLeaf.leafVersion, P2PKScriptPubKey(derivedKey.toXOnly)) + TapLeaf(LeafVersion.Tapscript, P2PKScriptPubKey(derivedKey.toXOnly)) val (_, spk) = TaprootScriptPubKey.fromInternalKeyTapscriptTree(internal, tree) spk diff --git a/core/src/main/scala/org/bitcoins/core/protocol/script/ControlBlock.scala b/core/src/main/scala/org/bitcoins/core/protocol/script/ControlBlock.scala index d3a2cea9fb..cfb153cae4 100644 --- a/core/src/main/scala/org/bitcoins/core/protocol/script/ControlBlock.scala +++ b/core/src/main/scala/org/bitcoins/core/protocol/script/ControlBlock.scala @@ -22,11 +22,11 @@ sealed abstract class ControlBlock extends NetworkElement { XOnlyPubKey.fromBytes(bytes.slice(1, 33)) } - val leafVersion: Byte = - (bytes.head & TaprootScriptPath.TAPROOT_LEAF_MASK).toByte + val leafVersion: LeafVersion = + LeafVersion.fromByte((bytes.head & LeafVersion.TAPROOT_LEAF_MASK).toByte) val isTapLeafMask: Boolean = { - (bytes.head & TaprootScriptPath.TAPROOT_LEAF_MASK).toByte == TaprootScriptPath.TAPROOT_LEAF_TAPSCRIPT + (bytes.head & LeafVersion.TAPROOT_LEAF_MASK).toByte == LeafVersion.Tapscript.toByte } /** Leaf or branch hashes embedded in the control block */ @@ -71,7 +71,8 @@ object TapscriptControlBlock extends Factory[TapscriptControlBlock] { if (bytes.isEmpty) { false } else { - TapLeaf.knownLeafVersions.contains(bytes.head) && + LeafVersion.knownLeafVersions.contains( + LeafVersion.fromMaskedByte(bytes.head)) && ControlBlock.isValid(bytes) && XOnlyPubKey.fromBytesT(bytes.slice(1, 33)).isSuccess } @@ -79,7 +80,7 @@ object TapscriptControlBlock extends Factory[TapscriptControlBlock] { /** Creates a control block with no scripts, just an internal key */ def fromXOnlyPubKey(internalKey: XOnlyPubKey): TapscriptControlBlock = { - fromBytes(TapLeaf.leafVersion +: internalKey.bytes) + fromBytes(LeafVersion.Tapscript.toByte +: internalKey.bytes) } override def fromBytes(bytes: ByteVector): TapscriptControlBlock = { diff --git a/core/src/main/scala/org/bitcoins/core/protocol/script/LeafVersion.scala b/core/src/main/scala/org/bitcoins/core/protocol/script/LeafVersion.scala new file mode 100644 index 0000000000..bc76d3a1c3 --- /dev/null +++ b/core/src/main/scala/org/bitcoins/core/protocol/script/LeafVersion.scala @@ -0,0 +1,35 @@ +package org.bitcoins.core.protocol.script + +sealed abstract class LeafVersion { + def toByte: Byte +} + +object LeafVersion { + + /** BIP342 specifies validity rules that apply for leaf version 0xc0, but + * future proposals can introduce rules for other leaf versions. + * + * @see + * https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#rationale + */ + case object Tapscript extends LeafVersion { + override def toByte: Byte = 0xc0.toByte + } + + case class UnknownLeafVersion(toByte: Byte) extends LeafVersion + + val knownLeafVersions: Vector[LeafVersion] = Vector( + Tapscript /*, 0xc1.toByte*/ ) + + final val TAPROOT_LEAF_MASK: Byte = 0xfe.toByte + + def fromByte(byte: Byte): LeafVersion = { + knownLeafVersions + .find(_.toByte == byte) + .getOrElse(UnknownLeafVersion(byte)) + } + + def fromMaskedByte(byte: Byte): LeafVersion = { + fromByte((TAPROOT_LEAF_MASK & byte).toByte) + } +} diff --git a/core/src/main/scala/org/bitcoins/core/protocol/script/ScriptWitness.scala b/core/src/main/scala/org/bitcoins/core/protocol/script/ScriptWitness.scala index b0aec3b79d..99e34127b3 100644 --- a/core/src/main/scala/org/bitcoins/core/protocol/script/ScriptWitness.scala +++ b/core/src/main/scala/org/bitcoins/core/protocol/script/ScriptWitness.scala @@ -7,7 +7,7 @@ import org.bitcoins.core.serializers.script.{ ScriptParser } import org.bitcoins.core.util.{BitcoinScriptUtil, BytesUtil} -import org.bitcoins.crypto._ +import org.bitcoins.crypto.* import scodec.bits.ByteVector /** Created by chris on 11/10/16. The witness used to evaluate a @@ -416,10 +416,6 @@ object TaprootScriptPath extends Factory[TaprootScriptPath] { final val TAPROOT_CONTROL_MAX_SIZE: Int = { TAPROOT_CONTROL_BASE_SIZE + TAPROOT_CONTROL_NODE_SIZE * TAPROOT_CONTROL_MAX_NODE_COUNT } - - final val TAPROOT_LEAF_MASK: Byte = 0xfe.toByte - final val TAPROOT_LEAF_TAPSCRIPT: Byte = 0xc0.toByte - override def fromBytes(bytes: ByteVector): TaprootScriptPath = { RawScriptWitnessParser.read(bytes) match { case t: TaprootScriptPath => t @@ -485,7 +481,8 @@ object TaprootScriptPath extends Factory[TaprootScriptPath] { */ def computeTapleafHash(leaf: TapLeaf): Sha256Digest = { val bytes = - ByteVector.fromInt(i = leaf.leafVersion, size = 1) ++ leaf.spk.bytes + ByteVector.fromInt(i = leaf.leafVersion.toByte, + size = 1) ++ leaf.spk.bytes CryptoUtil.tapLeafHash(bytes) } diff --git a/core/src/main/scala/org/bitcoins/core/protocol/script/TapLeaf.scala b/core/src/main/scala/org/bitcoins/core/protocol/script/TapLeaf.scala index 2f408722a7..56192cc8de 100644 --- a/core/src/main/scala/org/bitcoins/core/protocol/script/TapLeaf.scala +++ b/core/src/main/scala/org/bitcoins/core/protocol/script/TapLeaf.scala @@ -29,10 +29,11 @@ case class TapBranch(tree1: TapscriptTree, tree2: TapscriptTree) } } -case class TapLeaf(leafVersion: Byte, spk: ScriptPubKey) extends TapscriptTree { +case class TapLeaf(leafVersion: LeafVersion, spk: ScriptPubKey) + extends TapscriptTree { override val bytes: ByteVector = - ByteVector.fromInt(leafVersion, 1) ++ spk.bytes + ByteVector.fromInt(leafVersion.toByte, 1) ++ spk.bytes val sha256: Sha256Digest = CryptoUtil.tapLeafHash(bytes) override val leafs: Vector[TapLeaf] = Vector(this) @@ -41,18 +42,6 @@ case class TapLeaf(leafVersion: Byte, spk: ScriptPubKey) extends TapscriptTree { } } -object TapLeaf { - val leafVersion: Byte = 0xc0.toByte - - /** BIP342 specifies validity rules that apply for leaf version 0xc0, but - * future proposals can introduce rules for other leaf versions. - * - * @see - * https://github.com/bitcoin/bips/blob/master/bip-0341.mediawiki#rationale - */ - val knownLeafVersions: Vector[Byte] = Vector(leafVersion, 0xc1.toByte) -} - object TapscriptTree { def buildTapscriptTree(leafs: Vector[TapLeaf]): TapscriptTree = { diff --git a/core/src/main/scala/org/bitcoins/core/protocol/script/descriptor/DescriptorExpression.scala b/core/src/main/scala/org/bitcoins/core/protocol/script/descriptor/DescriptorExpression.scala index 9104e1d36c..d36149bf2d 100644 --- a/core/src/main/scala/org/bitcoins/core/protocol/script/descriptor/DescriptorExpression.scala +++ b/core/src/main/scala/org/bitcoins/core/protocol/script/descriptor/DescriptorExpression.scala @@ -386,7 +386,7 @@ case class TapscriptLeafExpression(source: RawSPKScriptExpression) private def scriptPubKey: ScriptPubKey = source.scriptPubKey override def tree: TapLeaf = - TapLeaf(TapLeaf.leafVersion, scriptPubKey) + TapLeaf(LeafVersion.Tapscript, scriptPubKey) } object SingleECPublicKeyExpression diff --git a/core/src/main/scala/org/bitcoins/core/psbt/PSBTRecord.scala b/core/src/main/scala/org/bitcoins/core/psbt/PSBTRecord.scala index 28f79c5b48..9d9361f828 100644 --- a/core/src/main/scala/org/bitcoins/core/psbt/PSBTRecord.scala +++ b/core/src/main/scala/org/bitcoins/core/psbt/PSBTRecord.scala @@ -4,7 +4,7 @@ import org.bitcoins.core.crypto.ExtPublicKey import org.bitcoins.core.hd.BIP32Path import org.bitcoins.core.number.{Int32, UInt32, UInt64} import org.bitcoins.core.protocol.CompactSizeUInt -import org.bitcoins.core.protocol.script._ +import org.bitcoins.core.protocol.script.* import org.bitcoins.core.protocol.transaction.{ BaseTransaction, NonWitnessTransaction, @@ -13,7 +13,7 @@ import org.bitcoins.core.protocol.transaction.{ } import org.bitcoins.core.serializers.script.RawScriptWitnessParser import org.bitcoins.core.util.BytesUtil -import org.bitcoins.crypto.{HashType, _} +import org.bitcoins.crypto.* import scodec.bits.ByteVector import scala.annotation.tailrec @@ -59,7 +59,7 @@ sealed trait GlobalPSBTRecord extends PSBTRecord { } object GlobalPSBTRecord extends Factory[GlobalPSBTRecord] { - import org.bitcoins.core.psbt.PSBTGlobalKeyId._ + import org.bitcoins.core.psbt.PSBTGlobalKeyId.* case class UnsignedTransaction(transaction: NonWitnessTransaction) extends GlobalPSBTRecord { @@ -107,7 +107,7 @@ object GlobalPSBTRecord extends Factory[GlobalPSBTRecord] { } override def fromBytes(bytes: ByteVector): GlobalPSBTRecord = { - import org.bitcoins.core.psbt.PSBTGlobalKeyId._ + import org.bitcoins.core.psbt.PSBTGlobalKeyId.* val (key, value) = PSBTRecord.fromBytes(bytes) PSBTGlobalKeyId.fromByte(key.head) match { @@ -141,7 +141,7 @@ sealed trait InputPSBTRecord extends PSBTRecord { } object InputPSBTRecord extends Factory[InputPSBTRecord] { - import org.bitcoins.core.psbt.PSBTInputKeyId._ + import org.bitcoins.core.psbt.PSBTInputKeyId.* case class NonWitnessOrUnknownUTXO(transactionSpent: Transaction) extends InputPSBTRecord { @@ -352,7 +352,7 @@ object InputPSBTRecord extends Factory[InputPSBTRecord] { case class TRLeafScript( controlBlock: ControlBlock, script: RawScriptPubKey, - leafVersion: Byte) + leafVersion: LeafVersion) extends InputPSBTRecord { override type KeyId = TRLeafScriptKeyId.type @@ -361,7 +361,7 @@ object InputPSBTRecord extends Factory[InputPSBTRecord] { } override val value: ByteVector = { - script.asmBytes ++ ByteVector.fromByte(leafVersion) + script.asmBytes ++ ByteVector.fromByte(leafVersion.toByte) } } @@ -411,7 +411,7 @@ object InputPSBTRecord extends Factory[InputPSBTRecord] { } override def fromBytes(bytes: ByteVector): InputPSBTRecord = { - import org.bitcoins.core.psbt.PSBTInputKeyId._ + import org.bitcoins.core.psbt.PSBTInputKeyId.* val (key, value) = PSBTRecord.fromBytes(bytes) PSBTInputKeyId.fromByte(key.head) match { @@ -530,7 +530,7 @@ object InputPSBTRecord extends Factory[InputPSBTRecord] { val script = RawScriptPubKey.fromAsmBytes(value.init) - TRLeafScript(controlBlock, script, value.last) + TRLeafScript(controlBlock, script, LeafVersion.fromByte(value.last)) case TRBIP32DerivationPathKeyId => val pubKey = XOnlyPubKey(key.tail) val numHashes = CompactSizeUInt.fromBytes(value) @@ -575,7 +575,7 @@ sealed trait OutputPSBTRecord extends PSBTRecord { } object OutputPSBTRecord extends Factory[OutputPSBTRecord] { - import org.bitcoins.core.psbt.PSBTOutputKeyId._ + import org.bitcoins.core.psbt.PSBTOutputKeyId.* case class RedeemScript(redeemScript: ScriptPubKey) extends OutputPSBTRecord { override type KeyId = RedeemScriptKeyId.type diff --git a/core/src/main/scala/org/bitcoins/core/script/ScriptProgram.scala b/core/src/main/scala/org/bitcoins/core/script/ScriptProgram.scala index e6bfd71588..9a6cda6510 100644 --- a/core/src/main/scala/org/bitcoins/core/script/ScriptProgram.scala +++ b/core/src/main/scala/org/bitcoins/core/script/ScriptProgram.scala @@ -1,18 +1,12 @@ package org.bitcoins.core.script -import org.bitcoins.core.crypto._ +import org.bitcoins.core.crypto.* import org.bitcoins.core.number.UInt32 -import org.bitcoins.core.protocol.script.{ - TapLeaf, - TaprootKeyPath, - TaprootScriptPath, - TaprootUnknownPath, - TaprootWitness -} -import org.bitcoins.core.script.constant._ +import org.bitcoins.core.protocol.script.* +import org.bitcoins.core.script.constant.* import org.bitcoins.core.script.control.{OP_ELSE, OP_ENDIF, OP_IF, OP_NOTIF} import org.bitcoins.core.script.flag.ScriptFlag -import org.bitcoins.core.script.result._ +import org.bitcoins.core.script.result.* import org.bitcoins.core.util.BitcoinScriptUtil import org.bitcoins.crypto.Sha256Digest @@ -91,7 +85,7 @@ sealed trait ScriptProgram { */ def tapLeafHashOpt: Option[Sha256Digest] = { getTapscriptOpt.map { sp => - val leaf = TapLeaf(TaprootScriptPath.TAPROOT_LEAF_TAPSCRIPT, sp.script) + val leaf = TapLeaf(LeafVersion.Tapscript, sp.script) val hash = TaprootScriptPath.computeTapleafHash(leaf) hash }