mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2024-11-19 18:02:54 +01:00
Create ScriptFactory.isValidAsm() to standardize how check validity o… (#2629)
* Create ScriptFactory.isValidAsm() to standardize how check validity of a script * Fix compile * Fix docs
This commit is contained in:
parent
593b1e2ce1
commit
097fa24e58
@ -17,15 +17,16 @@ class TxSigComponentTest extends BitcoinSUnitTest {
|
||||
|
||||
it should "correctly construct P2SHTxSigComponent" in {
|
||||
val p2shNoNest = P2SHScriptPubKey(EmptyScriptPubKey)
|
||||
|
||||
val pubKey = ECPublicKey.freshPublicKey
|
||||
val btx = BaseTransaction(
|
||||
TransactionConstants.validLockVersion,
|
||||
Vector(
|
||||
TransactionInput(
|
||||
TransactionOutPoint(DoubleSha256Digest.empty, UInt32.zero),
|
||||
P2SHScriptSignature(ConditionalScriptSignature(EmptyScriptSignature,
|
||||
condition = true),
|
||||
EmptyScriptPubKey),
|
||||
P2SHScriptSignature(scriptSig =
|
||||
ConditionalScriptSignature(EmptyScriptSignature,
|
||||
condition = true),
|
||||
redeemScript = P2WPKHWitnessSPKV0(pubKey)),
|
||||
TransactionConstants.sequence
|
||||
)),
|
||||
Vector(TransactionOutput(Satoshis.one, EmptyScriptPubKey)),
|
||||
|
@ -14,9 +14,7 @@ class MultiSignatureScriptSignatureTest extends BitcoinSUnitTest {
|
||||
}
|
||||
|
||||
it must "Fail validation if asm is empty" in {
|
||||
assert(
|
||||
!MultiSignatureScriptSignature.isMultiSignatureScriptSignature(
|
||||
Vector.empty))
|
||||
assert(!MultiSignatureScriptSignature.isValidAsm(Vector.empty))
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -60,7 +60,7 @@ case class UTXORecord(
|
||||
blockHash = blockHash)
|
||||
|
||||
case (path: NestedSegWitHDPath, Some(redeemScript), Some(scriptWitness))
|
||||
if WitnessScriptPubKey.isWitnessScriptPubKey(redeemScript.asm) =>
|
||||
if WitnessScriptPubKey.isValidAsm(redeemScript.asm) =>
|
||||
NestedSegwitV0SpendingInfo(outpoint,
|
||||
TransactionOutput(value, scriptPubKey),
|
||||
path,
|
||||
|
@ -184,10 +184,7 @@ object TxSigComponent {
|
||||
}
|
||||
case _: P2SHScriptPubKey =>
|
||||
val p2shScriptSig = scriptSig.asInstanceOf[P2SHScriptSignature]
|
||||
if (
|
||||
WitnessScriptPubKey.isWitnessScriptPubKey(
|
||||
p2shScriptSig.redeemScript.asm)
|
||||
) {
|
||||
if (WitnessScriptPubKey.isValidAsm(p2shScriptSig.redeemScript.asm)) {
|
||||
transaction match {
|
||||
case _: NonWitnessTransaction =>
|
||||
throw new IllegalArgumentException(
|
||||
|
@ -14,9 +14,8 @@ trait ScriptFactory[T <: Script] extends Factory[T] {
|
||||
def buildScript(
|
||||
asm: Vector[ScriptToken],
|
||||
constructor: Vector[ScriptToken] => T,
|
||||
invariant: Seq[ScriptToken] => Boolean,
|
||||
errorMsg: String): T = {
|
||||
if (invariant(asm)) {
|
||||
if (isValidAsm(asm)) {
|
||||
constructor(asm)
|
||||
} else throw new IllegalArgumentException(errorMsg)
|
||||
}
|
||||
@ -47,4 +46,7 @@ trait ScriptFactory[T <: Script] extends Factory[T] {
|
||||
def fromAsmHex(hex: String): T = {
|
||||
fromAsmBytes(BytesUtil.decodeHex(hex))
|
||||
}
|
||||
|
||||
/** Determines if the given asm is a valid T */
|
||||
def isValidAsm(asm: Seq[ScriptToken]): Boolean
|
||||
}
|
||||
|
@ -78,7 +78,6 @@ object P2PKHScriptPubKey extends ScriptFactory[P2PKHScriptPubKey] {
|
||||
def fromAsm(asm: Seq[ScriptToken]): P2PKHScriptPubKey = {
|
||||
buildScript(asm.toVector,
|
||||
P2PKHScriptPubKeyImpl.apply,
|
||||
isP2PKHScriptPubKey,
|
||||
"Given asm was not a p2pkh scriptPubKey, got: " + asm)
|
||||
}
|
||||
|
||||
@ -87,7 +86,7 @@ object P2PKHScriptPubKey extends ScriptFactory[P2PKHScriptPubKey] {
|
||||
/** Checks if the given asm matches the pattern for
|
||||
* [[org.bitcoins.core.protocol.script.P2PKHScriptPubKey P2PKHScriptPubKey]]
|
||||
*/
|
||||
def isP2PKHScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
asm match {
|
||||
case Seq(OP_DUP,
|
||||
OP_HASH160,
|
||||
@ -218,14 +217,13 @@ object MultiSignatureScriptPubKey
|
||||
def fromAsm(asm: Seq[ScriptToken]): MultiSignatureScriptPubKey = {
|
||||
buildScript(asm.toVector,
|
||||
MultiSignatureScriptPubKeyImpl.apply,
|
||||
isMultiSignatureScriptPubKey,
|
||||
"Given asm was not a MultSignatureScriptPubKey, got: " + asm)
|
||||
}
|
||||
|
||||
def apply(asm: Seq[ScriptToken]): MultiSignatureScriptPubKey = fromAsm(asm)
|
||||
|
||||
/** Determines if the given script tokens are a multisignature `scriptPubKey` */
|
||||
def isMultiSignatureScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
val containsMultiSigOp =
|
||||
asm.contains(OP_CHECKMULTISIG) || asm.contains(OP_CHECKMULTISIGVERIFY)
|
||||
|
||||
@ -321,7 +319,7 @@ object P2SHScriptPubKey extends ScriptFactory[P2SHScriptPubKey] {
|
||||
/** Checks if the given asm matches the pattern for
|
||||
* [[org.bitcoins.core.protocol.script.P2SHScriptPubKey P2SHScriptPubKey]]
|
||||
*/
|
||||
def isP2SHScriptPubKey(asm: Seq[ScriptToken]): Boolean =
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean =
|
||||
asm match {
|
||||
case Seq(OP_HASH160,
|
||||
_: BytesToPushOntoStack,
|
||||
@ -334,7 +332,6 @@ object P2SHScriptPubKey extends ScriptFactory[P2SHScriptPubKey] {
|
||||
def fromAsm(asm: Seq[ScriptToken]): P2SHScriptPubKey = {
|
||||
buildScript(asm.toVector,
|
||||
P2SHScriptPubKeyImpl.apply,
|
||||
isP2SHScriptPubKey,
|
||||
"Given asm was not a p2sh scriptPubkey, got: " + asm)
|
||||
}
|
||||
|
||||
@ -371,7 +368,6 @@ object P2PKScriptPubKey extends ScriptFactory[P2PKScriptPubKey] {
|
||||
def fromAsm(asm: Seq[ScriptToken]): P2PKScriptPubKey = {
|
||||
buildScript(asm.toVector,
|
||||
P2PKScriptPubKeyImpl.apply,
|
||||
isP2PKScriptPubKey,
|
||||
"Given asm was not a p2pk scriptPubKey, got: " + asm)
|
||||
}
|
||||
|
||||
@ -380,7 +376,7 @@ object P2PKScriptPubKey extends ScriptFactory[P2PKScriptPubKey] {
|
||||
/** Sees if the given asm matches the
|
||||
* [[org.bitcoins.core.protocol.script.P2PKHScriptPubKey P2PKHScriptPubKey]] pattern
|
||||
*/
|
||||
def isP2PKScriptPubKey(asm: Seq[ScriptToken]): Boolean =
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean =
|
||||
asm match {
|
||||
case Seq(_: BytesToPushOntoStack, _: ScriptConstant, OP_CHECKSIG) => true
|
||||
case _ => false
|
||||
@ -416,7 +412,7 @@ sealed trait LockTimeScriptPubKey extends RawScriptPubKey {
|
||||
object LockTimeScriptPubKey extends ScriptFactory[LockTimeScriptPubKey] {
|
||||
|
||||
def fromAsm(asm: Seq[ScriptToken]): LockTimeScriptPubKey = {
|
||||
require(isValidLockTimeScriptPubKey(asm))
|
||||
require(isValidAsm(asm))
|
||||
if (asm.contains(OP_CHECKLOCKTIMEVERIFY)) CLTVScriptPubKey(asm)
|
||||
else if (asm.contains(OP_CHECKSEQUENCEVERIFY)) CSVScriptPubKey(asm)
|
||||
else
|
||||
@ -424,9 +420,9 @@ object LockTimeScriptPubKey extends ScriptFactory[LockTimeScriptPubKey] {
|
||||
"Given asm was not a LockTimeScriptPubKey, got: " + asm)
|
||||
}
|
||||
|
||||
def isValidLockTimeScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
CLTVScriptPubKey.isCLTVScriptPubKey(asm) || CSVScriptPubKey
|
||||
.isCSVScriptPubKey(asm)
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
CLTVScriptPubKey.isValidAsm(asm) || CSVScriptPubKey
|
||||
.isValidAsm(asm)
|
||||
}
|
||||
}
|
||||
|
||||
@ -449,7 +445,6 @@ object CLTVScriptPubKey extends ScriptFactory[CLTVScriptPubKey] {
|
||||
def fromAsm(asm: Seq[ScriptToken]): CLTVScriptPubKey = {
|
||||
buildScript(asm.toVector,
|
||||
CLTVScriptPubKeyImpl.apply,
|
||||
isCLTVScriptPubKey,
|
||||
"Given asm was not a CLTVScriptPubKey, got: " + asm)
|
||||
}
|
||||
|
||||
@ -474,13 +469,13 @@ object CLTVScriptPubKey extends ScriptFactory[CLTVScriptPubKey] {
|
||||
CLTVScriptPubKey(asm)
|
||||
}
|
||||
|
||||
def isCLTVScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
if (asm.isEmpty) {
|
||||
false
|
||||
} else if (asm.head.isInstanceOf[BytesToPushOntoStack]) {
|
||||
val tailTokens = asm.slice(4, asm.length)
|
||||
if (
|
||||
P2SHScriptPubKey.isP2SHScriptPubKey(tailTokens) || tailTokens
|
||||
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
||||
.contains(OP_CHECKLOCKTIMEVERIFY)
|
||||
) return false
|
||||
asm.slice(0, 4) match {
|
||||
@ -494,7 +489,7 @@ object CLTVScriptPubKey extends ScriptFactory[CLTVScriptPubKey] {
|
||||
} else {
|
||||
val tailTokens = asm.slice(3, asm.length)
|
||||
if (
|
||||
P2SHScriptPubKey.isP2SHScriptPubKey(tailTokens) || tailTokens
|
||||
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
||||
.contains(OP_CHECKLOCKTIMEVERIFY)
|
||||
) return false
|
||||
asm.slice(0, 3) match {
|
||||
@ -541,7 +536,6 @@ object CSVScriptPubKey extends ScriptFactory[CSVScriptPubKey] {
|
||||
def fromAsm(asm: Seq[ScriptToken]): CSVScriptPubKey = {
|
||||
buildScript(asm.toVector,
|
||||
CSVScriptPubKeyImpl.apply,
|
||||
isCSVScriptPubKey,
|
||||
"Given asm was not a CSVScriptPubKey, got: " + asm)
|
||||
}
|
||||
|
||||
@ -568,11 +562,11 @@ object CSVScriptPubKey extends ScriptFactory[CSVScriptPubKey] {
|
||||
CSVScriptPubKey(asm)
|
||||
}
|
||||
|
||||
def isCSVScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
if (asm.head.isInstanceOf[BytesToPushOntoStack]) {
|
||||
val tailTokens = asm.slice(4, asm.length)
|
||||
if (
|
||||
P2SHScriptPubKey.isP2SHScriptPubKey(tailTokens) || tailTokens
|
||||
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
||||
.contains(OP_CHECKSEQUENCEVERIFY)
|
||||
) return false
|
||||
asm.slice(0, 4) match {
|
||||
@ -586,7 +580,7 @@ object CSVScriptPubKey extends ScriptFactory[CSVScriptPubKey] {
|
||||
} else {
|
||||
val tailTokens = asm.slice(3, asm.length)
|
||||
if (
|
||||
P2SHScriptPubKey.isP2SHScriptPubKey(tailTokens) || tailTokens
|
||||
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
||||
.contains(OP_CHECKSEQUENCEVERIFY)
|
||||
) return false
|
||||
asm.slice(0, 3) match {
|
||||
@ -619,13 +613,13 @@ sealed trait ConditionalScriptPubKey extends RawScriptPubKey {
|
||||
|
||||
val opElseIndex: Int = opElseIndexOpt.get
|
||||
|
||||
require(!P2SHScriptPubKey.isP2SHScriptPubKey(trueSPK.asm) && !P2SHScriptPubKey
|
||||
.isP2SHScriptPubKey(falseSPK.asm),
|
||||
require(!P2SHScriptPubKey.isValidAsm(trueSPK.asm) && !P2SHScriptPubKey
|
||||
.isValidAsm(falseSPK.asm),
|
||||
"ConditionalScriptPubKey cannot wrap P2SH")
|
||||
require(
|
||||
!WitnessScriptPubKey
|
||||
.isWitnessScriptPubKey(trueSPK.asm) && !WitnessScriptPubKey
|
||||
.isWitnessScriptPubKey(falseSPK.asm),
|
||||
.isValidAsm(trueSPK.asm) && !WitnessScriptPubKey
|
||||
.isValidAsm(falseSPK.asm),
|
||||
"ConditionalScriptPubKey cannot wrap SegWit ScriptPubKey"
|
||||
)
|
||||
|
||||
@ -754,7 +748,6 @@ object NonStandardIfConditionalScriptPubKey
|
||||
buildScript(
|
||||
asm = asm.toVector,
|
||||
constructor = NonStandardIfConditionalScriptPubKeyImpl.apply,
|
||||
invariant = isNonStandardIfConditionalScriptPubKey,
|
||||
errorMsg =
|
||||
"Given asm was not a NonStandardIfConditionalScriptPubKey, got: " + asm
|
||||
)
|
||||
@ -770,13 +763,13 @@ object NonStandardIfConditionalScriptPubKey
|
||||
fromAsm(asm)
|
||||
}
|
||||
|
||||
def isNonStandardIfConditionalScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
val validIf = ConditionalScriptPubKey
|
||||
.isConditionalScriptPubKeyWithElseIndex(asm, OP_IF)
|
||||
._1
|
||||
|
||||
val isMultiSigWithTimeout = MultiSignatureWithTimeoutScriptPubKey
|
||||
.isMultiSignatureWithTimeoutScriptPubKey(asm)
|
||||
.isValidAsm(asm)
|
||||
|
||||
validIf && !isMultiSigWithTimeout
|
||||
}
|
||||
@ -784,10 +777,9 @@ object NonStandardIfConditionalScriptPubKey
|
||||
|
||||
sealed trait MultiSignatureWithTimeoutScriptPubKey
|
||||
extends IfConditionalScriptPubKey {
|
||||
require(
|
||||
MultiSignatureScriptPubKey.isMultiSignatureScriptPubKey(super.firstSPK.asm),
|
||||
"True case must be MultiSignatureSPK")
|
||||
require(CLTVScriptPubKey.isCLTVScriptPubKey(super.secondSPK.asm),
|
||||
require(MultiSignatureScriptPubKey.isValidAsm(super.firstSPK.asm),
|
||||
"True case must be MultiSignatureSPK")
|
||||
require(CLTVScriptPubKey.isValidAsm(super.secondSPK.asm),
|
||||
"False case must be CLTVSPK")
|
||||
|
||||
override def firstSPK: MultiSignatureScriptPubKey = {
|
||||
@ -826,7 +818,6 @@ object MultiSignatureWithTimeoutScriptPubKey
|
||||
buildScript(
|
||||
asm = asm.toVector,
|
||||
constructor = MultiSignatureWithTimeoutScriptPubKeyImpl.apply,
|
||||
invariant = isMultiSignatureWithTimeoutScriptPubKey,
|
||||
errorMsg =
|
||||
s"Given asm was not a MultiSignatureWithTimeoutScriptPubKey, got: $asm"
|
||||
)
|
||||
@ -841,17 +832,15 @@ object MultiSignatureWithTimeoutScriptPubKey
|
||||
fromAsm(asm)
|
||||
}
|
||||
|
||||
def isMultiSignatureWithTimeoutScriptPubKey(
|
||||
asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
val (validIf, opElseIndexOpt) = ConditionalScriptPubKey
|
||||
.isConditionalScriptPubKeyWithElseIndex(asm, OP_IF)
|
||||
|
||||
lazy val validMultiSigWithCLTV = opElseIndexOpt match {
|
||||
case Some(opElseIndex) =>
|
||||
MultiSignatureScriptPubKey
|
||||
.isMultiSignatureScriptPubKey(
|
||||
asm.slice(1, opElseIndex)) && CLTVScriptPubKey
|
||||
.isCLTVScriptPubKey(asm.slice(opElseIndex + 1, asm.length - 1))
|
||||
.isValidAsm(asm.slice(1, opElseIndex)) && CLTVScriptPubKey
|
||||
.isValidAsm(asm.slice(opElseIndex + 1, asm.length - 1))
|
||||
case _ => false
|
||||
}
|
||||
|
||||
@ -879,7 +868,6 @@ object NonStandardNotIfConditionalScriptPubKey
|
||||
buildScript(
|
||||
asm = asm.toVector,
|
||||
constructor = NonStandardNotIfConditionalScriptPubKeyImpl.apply,
|
||||
invariant = isNonStandardNotIfConditionalScriptPubKey,
|
||||
errorMsg = "Given asm was not a NotIfConditionalScriptPubKey, got: " + asm
|
||||
)
|
||||
}
|
||||
@ -893,8 +881,7 @@ object NonStandardNotIfConditionalScriptPubKey
|
||||
fromAsm(asm)
|
||||
}
|
||||
|
||||
def isNonStandardNotIfConditionalScriptPubKey(
|
||||
asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
ConditionalScriptPubKey
|
||||
.isConditionalScriptPubKeyWithElseIndex(asm, OP_NOTIF)
|
||||
._1
|
||||
@ -948,7 +935,6 @@ object P2PKWithTimeoutScriptPubKey
|
||||
buildScript(
|
||||
asm = asm.toVector,
|
||||
constructor = P2PKWithTimeoutScriptPubKeyImpl.apply,
|
||||
invariant = isP2PKWithTimeoutScriptPubKey,
|
||||
errorMsg = s"Given asm was not a P2PKWithTimeoutScriptPubKey, got $asm"
|
||||
)
|
||||
}
|
||||
@ -975,7 +961,7 @@ object P2PKWithTimeoutScriptPubKey
|
||||
)
|
||||
}
|
||||
|
||||
def isP2PKWithTimeoutScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
if (asm.length < 5) {
|
||||
false
|
||||
} else {
|
||||
@ -1025,15 +1011,12 @@ object NonStandardScriptPubKey extends ScriptFactory[NonStandardScriptPubKey] {
|
||||
|
||||
def fromAsm(asm: Seq[ScriptToken]): NonStandardScriptPubKey = {
|
||||
//everything can be a NonStandardScriptPubkey, thus the trivially true function
|
||||
buildScript(asm.toVector,
|
||||
NonStandardScriptPubKeyImpl.apply,
|
||||
{ _ =>
|
||||
true
|
||||
},
|
||||
"")
|
||||
buildScript(asm.toVector, NonStandardScriptPubKeyImpl.apply, "")
|
||||
}
|
||||
|
||||
def apply(asm: Seq[ScriptToken]): NonStandardScriptPubKey = fromAsm(asm)
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = true
|
||||
}
|
||||
|
||||
/** Represents the empty ScriptPubKey */
|
||||
@ -1049,43 +1032,46 @@ object RawScriptPubKey extends ScriptFactory[RawScriptPubKey] {
|
||||
def fromAsm(asm: Seq[ScriptToken]): RawScriptPubKey =
|
||||
asm match {
|
||||
case Nil => EmptyScriptPubKey
|
||||
case _
|
||||
if P2PKWithTimeoutScriptPubKey.isP2PKWithTimeoutScriptPubKey(asm) =>
|
||||
case _ if P2PKWithTimeoutScriptPubKey.isValidAsm(asm) =>
|
||||
P2PKWithTimeoutScriptPubKey.fromAsm(asm)
|
||||
case _
|
||||
if MultiSignatureWithTimeoutScriptPubKey
|
||||
.isMultiSignatureWithTimeoutScriptPubKey(asm) =>
|
||||
.isValidAsm(asm) =>
|
||||
MultiSignatureWithTimeoutScriptPubKey.fromAsm(asm)
|
||||
case _
|
||||
if NonStandardIfConditionalScriptPubKey
|
||||
.isNonStandardIfConditionalScriptPubKey(asm) =>
|
||||
.isValidAsm(asm) =>
|
||||
NonStandardIfConditionalScriptPubKey.fromAsm(asm)
|
||||
case _
|
||||
if NonStandardNotIfConditionalScriptPubKey
|
||||
.isNonStandardNotIfConditionalScriptPubKey(asm) =>
|
||||
.isValidAsm(asm) =>
|
||||
NonStandardNotIfConditionalScriptPubKey.fromAsm(asm)
|
||||
case _ if P2PKHScriptPubKey.isP2PKHScriptPubKey(asm) =>
|
||||
case _ if P2PKHScriptPubKey.isValidAsm(asm) =>
|
||||
P2PKHScriptPubKey(asm)
|
||||
case _ if P2PKScriptPubKey.isP2PKScriptPubKey(asm) =>
|
||||
case _ if P2PKScriptPubKey.isValidAsm(asm) =>
|
||||
P2PKScriptPubKey(asm)
|
||||
case _ if MultiSignatureScriptPubKey.isMultiSignatureScriptPubKey(asm) =>
|
||||
case _ if MultiSignatureScriptPubKey.isValidAsm(asm) =>
|
||||
MultiSignatureScriptPubKey(asm)
|
||||
case _ if CLTVScriptPubKey.isCLTVScriptPubKey(asm) =>
|
||||
case _ if CLTVScriptPubKey.isValidAsm(asm) =>
|
||||
CLTVScriptPubKey(asm)
|
||||
case _ if CSVScriptPubKey.isCSVScriptPubKey(asm) => CSVScriptPubKey(asm)
|
||||
case _ if WitnessCommitment.isWitnessCommitment(asm) =>
|
||||
case _ if CSVScriptPubKey.isValidAsm(asm) => CSVScriptPubKey(asm)
|
||||
case _ if WitnessCommitment.isValidAsm(asm) =>
|
||||
WitnessCommitment(asm)
|
||||
case _ => NonStandardScriptPubKey(asm)
|
||||
}
|
||||
|
||||
def apply(asm: Seq[ScriptToken]): RawScriptPubKey = fromAsm(asm)
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
!WitnessScriptPubKey.isValidAsm(asm) && !P2SHScriptPubKey.isValidAsm(asm)
|
||||
}
|
||||
}
|
||||
|
||||
object NonWitnessScriptPubKey extends ScriptFactory[NonWitnessScriptPubKey] {
|
||||
val empty: NonWitnessScriptPubKey = fromAsm(Nil)
|
||||
|
||||
def fromAsm(asm: Seq[ScriptToken]): NonWitnessScriptPubKey = {
|
||||
if (P2SHScriptPubKey.isP2SHScriptPubKey(asm)) {
|
||||
if (P2SHScriptPubKey.isValidAsm(asm)) {
|
||||
P2SHScriptPubKey(asm)
|
||||
} else {
|
||||
RawScriptPubKey.fromAsm(asm)
|
||||
@ -1093,6 +1079,10 @@ object NonWitnessScriptPubKey extends ScriptFactory[NonWitnessScriptPubKey] {
|
||||
}
|
||||
|
||||
def apply(asm: Seq[ScriptToken]): NonWitnessScriptPubKey = fromAsm(asm)
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
!WitnessScriptPubKey.isValidAsm(asm)
|
||||
}
|
||||
}
|
||||
|
||||
/** Factory companion object used to create
|
||||
@ -1102,12 +1092,12 @@ object ScriptPubKey extends ScriptFactory[ScriptPubKey] {
|
||||
val empty: ScriptPubKey = fromAsm(Nil)
|
||||
|
||||
/** Creates a `scriptPubKey` from its asm representation */
|
||||
def fromAsm(asm: Seq[ScriptToken]): ScriptPubKey = {
|
||||
override def fromAsm(asm: Seq[ScriptToken]): ScriptPubKey = {
|
||||
val nonWitnessScriptPubKey = NonWitnessScriptPubKey.fromAsm(asm)
|
||||
if (
|
||||
nonWitnessScriptPubKey
|
||||
.isInstanceOf[NonStandardScriptPubKey] && WitnessScriptPubKey
|
||||
.isWitnessScriptPubKey(asm)
|
||||
.isValidAsm(asm)
|
||||
) {
|
||||
WitnessScriptPubKey(asm)
|
||||
} else {
|
||||
@ -1116,6 +1106,9 @@ object ScriptPubKey extends ScriptFactory[ScriptPubKey] {
|
||||
}
|
||||
|
||||
def apply(asm: Seq[ScriptToken]): ScriptPubKey = fromAsm(asm)
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = true
|
||||
|
||||
}
|
||||
|
||||
/** This type represents a
|
||||
@ -1156,11 +1149,11 @@ object WitnessScriptPubKey extends ScriptFactory[WitnessScriptPubKey] {
|
||||
|
||||
def fromAsm(asm: Seq[ScriptToken]): WitnessScriptPubKey =
|
||||
asm match {
|
||||
case _ if P2WPKHWitnessSPKV0.isValid(asm) =>
|
||||
case _ if P2WPKHWitnessSPKV0.isValidAsm(asm) =>
|
||||
P2WPKHWitnessSPKV0.fromAsm(asm)
|
||||
case _ if P2WSHWitnessSPKV0.isValid(asm) =>
|
||||
case _ if P2WSHWitnessSPKV0.isValidAsm(asm) =>
|
||||
P2WSHWitnessSPKV0.fromAsm(asm)
|
||||
case _ if WitnessScriptPubKey.isWitnessScriptPubKey(asm) =>
|
||||
case _ if WitnessScriptPubKey.isValidAsm(asm) =>
|
||||
UnassignedWitnessScriptPubKey(asm)
|
||||
case _ =>
|
||||
throw new IllegalArgumentException(
|
||||
@ -1173,7 +1166,7 @@ object WitnessScriptPubKey extends ScriptFactory[WitnessScriptPubKey] {
|
||||
* [[https://github.com/bitcoin/bitcoin/blob/14d01309bed59afb08651f2b701ff90371b15b20/src/script/script.cpp#L223-L237 this function]]
|
||||
* inside of Bitcoin Core
|
||||
*/
|
||||
def isWitnessScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
|
||||
//multisig spk with zero public keys
|
||||
//OP_0, BytesToPushOntoStackImpl(3), ScriptConstantImpl(ByteVector(3 bytes, 0x0000ae)
|
||||
@ -1188,8 +1181,8 @@ object WitnessScriptPubKey extends ScriptFactory[WitnessScriptPubKey] {
|
||||
val firstOp = asm.headOption
|
||||
if (bytes.size < 4 || bytes.size > 42) false
|
||||
else if (!validWitVersions.contains(firstOp.getOrElse(OP_1NEGATE))) false
|
||||
else if (MultiSignatureScriptPubKey.isMultiSignatureScriptPubKey(asm)) false
|
||||
else if (LockTimeScriptPubKey.isValidLockTimeScriptPubKey(asm)) false
|
||||
else if (MultiSignatureScriptPubKey.isValidAsm(asm)) false
|
||||
else if (LockTimeScriptPubKey.isValidAsm(asm)) false
|
||||
else if (asm(1).toLong + 2 == bytes.size) true
|
||||
else false
|
||||
}
|
||||
@ -1212,18 +1205,17 @@ object WitnessScriptPubKeyV0 extends ScriptFactory[WitnessScriptPubKeyV0] {
|
||||
* Verison 0 witness program need to have an OP_0 as the first operation
|
||||
* [[https://github.com/bitcoin/bitcoin/blob/449f9b8debcceb61a92043bc7031528a53627c47/src/script/script.cpp#L215-L229]]
|
||||
*/
|
||||
def isValid(asm: Seq[ScriptToken]): Boolean = {
|
||||
asm.headOption.contains(OP_0) && WitnessScriptPubKey.isWitnessScriptPubKey(
|
||||
asm)
|
||||
def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
asm.headOption.contains(OP_0) && WitnessScriptPubKey.isValidAsm(asm)
|
||||
}
|
||||
|
||||
def apply(asm: Seq[ScriptToken]): WitnessScriptPubKeyV0 = fromAsm(asm)
|
||||
|
||||
override def fromAsm(asm: Seq[ScriptToken]): WitnessScriptPubKeyV0 =
|
||||
asm match {
|
||||
case _ if P2WPKHWitnessSPKV0.isValid(asm) =>
|
||||
case _ if P2WPKHWitnessSPKV0.isValidAsm(asm) =>
|
||||
P2WPKHWitnessSPKV0.fromAsm(asm)
|
||||
case _ if P2WSHWitnessSPKV0.isValid(asm) =>
|
||||
case _ if P2WSHWitnessSPKV0.isValidAsm(asm) =>
|
||||
P2WSHWitnessSPKV0.fromAsm(asm)
|
||||
case _ =>
|
||||
sys.error(
|
||||
@ -1250,14 +1242,12 @@ object P2WPKHWitnessSPKV0 extends ScriptFactory[P2WPKHWitnessSPKV0] {
|
||||
override def fromAsm(asm: Seq[ScriptToken]): P2WPKHWitnessSPKV0 = {
|
||||
buildScript(asm.toVector,
|
||||
P2WPKHWitnessSPKV0Impl.apply,
|
||||
isValid,
|
||||
s"Given asm was not a P2WPKHWitnessSPKV0, got $asm")
|
||||
}
|
||||
|
||||
def isValid(asm: Seq[ScriptToken]): Boolean = {
|
||||
def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
val asmBytes = BytesUtil.toByteVector(asm)
|
||||
asmBytes.size == 22 && WitnessScriptPubKeyV0.isValid(asm)
|
||||
|
||||
asmBytes.size == 22 && WitnessScriptPubKeyV0.isValidAsm(asm)
|
||||
}
|
||||
|
||||
def fromHash(hash: Sha256Hash160Digest): P2WPKHWitnessSPKV0 = {
|
||||
@ -1296,13 +1286,12 @@ object P2WSHWitnessSPKV0 extends ScriptFactory[P2WSHWitnessSPKV0] {
|
||||
override def fromAsm(asm: Seq[ScriptToken]): P2WSHWitnessSPKV0 = {
|
||||
buildScript(asm.toVector,
|
||||
P2WSHWitnessSPKV0Impl.apply,
|
||||
isValid,
|
||||
s"Given asm was not a P2WSHWitnessSPKV0, got $asm")
|
||||
}
|
||||
|
||||
def isValid(asm: Seq[ScriptToken]): Boolean = {
|
||||
def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
val asmBytes = BytesUtil.toByteVector(asm)
|
||||
WitnessScriptPubKeyV0.isValid(asm) &&
|
||||
WitnessScriptPubKeyV0.isValidAsm(asm) &&
|
||||
asmBytes.size == 34
|
||||
}
|
||||
|
||||
@ -1344,11 +1333,14 @@ object UnassignedWitnessScriptPubKey
|
||||
buildScript(
|
||||
asm.toVector,
|
||||
UnassignedWitnessScriptPubKeyImpl.apply,
|
||||
WitnessScriptPubKey.isWitnessScriptPubKey,
|
||||
"Given asm was not a valid witness script pubkey: " + asm
|
||||
)
|
||||
}
|
||||
def apply(asm: Seq[ScriptToken]): UnassignedWitnessScriptPubKey = fromAsm(asm)
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
WitnessScriptPubKey.isValidAsm(asm)
|
||||
}
|
||||
}
|
||||
|
||||
/** This trait represents the witness commitment found in the coinbase transaction
|
||||
@ -1389,7 +1381,6 @@ object WitnessCommitment extends ScriptFactory[WitnessCommitment] {
|
||||
override def fromAsm(asm: Seq[ScriptToken]): WitnessCommitment = {
|
||||
buildScript(asm.toVector,
|
||||
WitnessCommitmentImpl.apply,
|
||||
isWitnessCommitment,
|
||||
"Given asm was not a valid witness commitment, got: " + asm)
|
||||
}
|
||||
|
||||
@ -1403,7 +1394,7 @@ object WitnessCommitment extends ScriptFactory[WitnessCommitment] {
|
||||
/** This determines if the given asm has the correct witness structure according to
|
||||
* [[https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#commitment-structure BIP141]]
|
||||
*/
|
||||
def isWitnessCommitment(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
if (asm.size < 3) false
|
||||
else {
|
||||
val minCommitmentSize = 38
|
||||
|
@ -45,11 +45,12 @@ object NonStandardScriptSignature
|
||||
def fromAsm(asm: Seq[ScriptToken]): NonStandardScriptSignature = {
|
||||
buildScript(asm = asm.toVector,
|
||||
constructor = NonStandardScriptSignatureImpl(_),
|
||||
invariant = { _ =>
|
||||
true
|
||||
},
|
||||
errorMsg = "")
|
||||
}
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
/** A script signature to be used in tests for signing EmptyScriptPubKey.
|
||||
@ -61,7 +62,7 @@ case object TrivialTrueScriptSignature extends ScriptSignature {
|
||||
override lazy val asm: Vector[ScriptToken] =
|
||||
Vector(OP_TRUE)
|
||||
|
||||
def isTrivialTrueScriptSignature(asm: Seq[ScriptToken]): Boolean = {
|
||||
def isValid(asm: Seq[ScriptToken]): Boolean = {
|
||||
asm == this.asm
|
||||
}
|
||||
}
|
||||
@ -97,7 +98,6 @@ object P2PKHScriptSignature extends ScriptFactory[P2PKHScriptSignature] {
|
||||
buildScript(
|
||||
asm = asm.toVector,
|
||||
constructor = P2PKHScriptSignatureImpl(_),
|
||||
invariant = isP2PKHScriptSig(_),
|
||||
errorMsg = s"Given asm was not a P2PKHScriptSignature, got: $asm"
|
||||
)
|
||||
}
|
||||
@ -119,7 +119,7 @@ object P2PKHScriptSignature extends ScriptFactory[P2PKHScriptSignature] {
|
||||
}
|
||||
|
||||
/** Determines if the given asm matches a [[P2PKHScriptSignature]] */
|
||||
def isP2PKHScriptSig(asm: Seq[ScriptToken]): Boolean =
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean =
|
||||
asm match {
|
||||
case Seq(_: BytesToPushOntoStack,
|
||||
maybeSig: ScriptConstant,
|
||||
@ -148,7 +148,7 @@ sealed trait P2SHScriptSignature extends ScriptSignature {
|
||||
EmptyScriptPubKey
|
||||
} else if (
|
||||
scriptSig == EmptyScriptSignature &&
|
||||
WitnessScriptPubKey.isWitnessScriptPubKey(asm.tail)
|
||||
WitnessScriptPubKey.isValidAsm(asm.tail)
|
||||
) {
|
||||
//if we have an EmptyScriptSignature, we need to check if the rest of the asm
|
||||
//is a Witness script. It is not necessarily a witness script, since this code
|
||||
@ -163,7 +163,7 @@ sealed trait P2SHScriptSignature extends ScriptSignature {
|
||||
/** Returns the script signature of this p2shScriptSig with no serialized redeemScript */
|
||||
def scriptSignatureNoRedeemScript: ScriptSignature = {
|
||||
//witness scriptPubKeys always have EmptyScriptSigs
|
||||
if (WitnessScriptPubKey.isWitnessScriptPubKey(asm)) {
|
||||
if (WitnessScriptPubKey.isValidAsm(asm)) {
|
||||
EmptyScriptSignature
|
||||
} else {
|
||||
val asmWithoutRedeemScriptAndPushOp: Try[Seq[ScriptToken]] = Try {
|
||||
@ -222,23 +222,33 @@ object P2SHScriptSignature extends ScriptFactory[P2SHScriptSignature] {
|
||||
P2SHScriptSignature(EmptyScriptSignature, witnessScriptPubKey)
|
||||
}
|
||||
|
||||
def fromAsm(asm: Seq[ScriptToken]): P2SHScriptSignature = {
|
||||
override def buildScript(
|
||||
asm: Vector[ScriptToken],
|
||||
constructor: Vector[ScriptToken] => P2SHScriptSignature,
|
||||
errorMsg: String): P2SHScriptSignature = {
|
||||
//everything can be a P2SHScriptSignature, thus passing the trivially true function
|
||||
//the most important thing to note is we cannot have a P2SHScriptSignature unless
|
||||
//we have a P2SHScriptPubKey
|
||||
//previously P2SHScriptSignature's redeem script had to be standard scriptPubKey's, this
|
||||
//was removed in 0.11 or 0.12 of Bitcoin Core
|
||||
constructor(asm)
|
||||
}
|
||||
|
||||
def fromAsm(asm: Seq[ScriptToken]): P2SHScriptSignature = {
|
||||
buildScript(asm = asm.toVector,
|
||||
constructor = P2SHScriptSignatureImpl(_),
|
||||
invariant = { _ =>
|
||||
true
|
||||
},
|
||||
errorMsg =
|
||||
s"Given asm tokens are not a p2sh scriptSig, got: $asm")
|
||||
}
|
||||
|
||||
/** Tests if the given asm tokens are a [[P2SHScriptSignature]] */
|
||||
def isP2SHScriptSig(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
//as noted above, techinically _anything_ can be a p2sh scriptsig
|
||||
//this applies basic checks to see if it's a standard redeemScript
|
||||
//rather than a non standard redeeScript.
|
||||
|
||||
//this will return false if the redeemScript is not a
|
||||
//supported scriptpubkey type in our library
|
||||
asm.size > 1 && isRedeemScript(asm.last)
|
||||
}
|
||||
|
||||
@ -323,7 +333,6 @@ object MultiSignatureScriptSignature
|
||||
buildScript(
|
||||
asm = asm.toVector,
|
||||
constructor = MultiSignatureScriptSignatureImpl(_),
|
||||
invariant = isMultiSignatureScriptSignature(_),
|
||||
errorMsg =
|
||||
s"The given asm tokens were not a multisignature script sig: $asm"
|
||||
)
|
||||
@ -335,7 +344,7 @@ object MultiSignatureScriptSignature
|
||||
* @param asm the asm to check if it falls in the multisignature script sig format
|
||||
* @return boolean indicating if the scriptsignature is a multisignature script signature
|
||||
*/
|
||||
def isMultiSignatureScriptSignature(asm: Seq[ScriptToken]): Boolean =
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean =
|
||||
asm.isEmpty match {
|
||||
case true => false
|
||||
//case false if (asm.size == 1) => false
|
||||
@ -394,12 +403,11 @@ object P2PKScriptSignature extends ScriptFactory[P2PKScriptSignature] {
|
||||
def fromAsm(asm: Seq[ScriptToken]): P2PKScriptSignature = {
|
||||
buildScript(asm.toVector,
|
||||
P2PKScriptSignatureImpl(_),
|
||||
isP2PKScriptSignature(_),
|
||||
"The given asm tokens were not a p2pk script sig: " + asm)
|
||||
}
|
||||
|
||||
/** P2PK scriptSigs always have the pattern [pushop, digitalSignature] */
|
||||
def isP2PKScriptSignature(asm: Seq[ScriptToken]): Boolean =
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean =
|
||||
asm match {
|
||||
case Seq(_: BytesToPushOntoStack, _: ScriptConstant) => true
|
||||
case _ => false
|
||||
@ -413,7 +421,6 @@ object P2PKWithTimeoutScriptSignature
|
||||
buildScript(
|
||||
asm.toVector,
|
||||
ConditionalScriptSignature.fromAsm,
|
||||
isP2PKWithTimeoutScriptSignature,
|
||||
s"The given asm tokens were not a P2PKWithTimeoutScriptSignature, got $asm"
|
||||
)
|
||||
}
|
||||
@ -424,10 +431,10 @@ object P2PKWithTimeoutScriptSignature
|
||||
ConditionalScriptSignature(P2PKScriptSignature(signature), beforeTimeout)
|
||||
}
|
||||
|
||||
def isP2PKWithTimeoutScriptSignature(asm: Seq[ScriptToken]): Boolean = {
|
||||
P2PKScriptSignature.isP2PKScriptSignature(
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
P2PKScriptSignature.isValidAsm(
|
||||
asm.dropRight(1)) && ConditionalScriptSignature
|
||||
.isValidConditionalScriptSig(asm)
|
||||
.isValidAsm(asm)
|
||||
}
|
||||
}
|
||||
|
||||
@ -455,9 +462,6 @@ object CLTVScriptSignature extends ScriptFactory[CLTVScriptSignature] {
|
||||
override def fromAsm(asm: Seq[ScriptToken]): CLTVScriptSignature = {
|
||||
buildScript(asm = asm.toVector,
|
||||
constructor = CLTVScriptSignatureImpl(_),
|
||||
invariant = { _ =>
|
||||
true
|
||||
},
|
||||
errorMsg = s"Given asm was not a CLTVScriptSignature $asm")
|
||||
}
|
||||
|
||||
@ -468,6 +472,10 @@ object CLTVScriptSignature extends ScriptFactory[CLTVScriptSignature] {
|
||||
def apply(scriptSig: ScriptSignature): CLTVScriptSignature = {
|
||||
fromHex(scriptSig.hex)
|
||||
}
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
sealed trait CSVScriptSignature extends LockTimeScriptSignature {
|
||||
@ -483,9 +491,6 @@ object CSVScriptSignature extends ScriptFactory[CSVScriptSignature] {
|
||||
override def fromAsm(asm: Seq[ScriptToken]): CSVScriptSignature = {
|
||||
buildScript(asm = asm.toVector,
|
||||
constructor = CSVScriptSignatureImpl(_),
|
||||
invariant = { _ =>
|
||||
true
|
||||
},
|
||||
errorMsg = s"Given asm was not a CLTVScriptSignature $asm")
|
||||
}
|
||||
|
||||
@ -496,11 +501,13 @@ object CSVScriptSignature extends ScriptFactory[CSVScriptSignature] {
|
||||
def apply(scriptSig: ScriptSignature): CSVScriptSignature = {
|
||||
fromHex(scriptSig.hex)
|
||||
}
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = true
|
||||
}
|
||||
|
||||
/** ScriptSignature for both OP_IF and OP_NOTIF ScriptPubKeys */
|
||||
sealed trait ConditionalScriptSignature extends ScriptSignature {
|
||||
require(ConditionalScriptSignature.isValidConditionalScriptSig(asm),
|
||||
require(ConditionalScriptSignature.isValidAsm(asm),
|
||||
"ConditionalScriptSignature must end in true or false")
|
||||
|
||||
def isTrue: Boolean = {
|
||||
@ -535,7 +542,6 @@ object ConditionalScriptSignature
|
||||
override def fromAsm(asm: Seq[ScriptToken]): ConditionalScriptSignature = {
|
||||
buildScript(asm.toVector,
|
||||
ConditionalScriptSignatureImpl.apply,
|
||||
isValidConditionalScriptSig,
|
||||
s"Given asm was not a ConditionalScriptSignature: $asm")
|
||||
}
|
||||
|
||||
@ -573,7 +579,7 @@ object ConditionalScriptSignature
|
||||
}
|
||||
}
|
||||
|
||||
def isValidConditionalScriptSig(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
asm.lastOption.exists(Vector(OP_0, OP_FALSE, OP_1, OP_TRUE).contains)
|
||||
}
|
||||
}
|
||||
@ -593,22 +599,20 @@ object ScriptSignature extends ScriptFactory[ScriptSignature] {
|
||||
def fromAsm(tokens: Seq[ScriptToken]): ScriptSignature =
|
||||
tokens match {
|
||||
case Nil => EmptyScriptSignature
|
||||
case _
|
||||
if TrivialTrueScriptSignature.isTrivialTrueScriptSignature(tokens) =>
|
||||
case _ if TrivialTrueScriptSignature.isValid(tokens) =>
|
||||
TrivialTrueScriptSignature
|
||||
case _ if P2SHScriptSignature.isP2SHScriptSig(tokens) =>
|
||||
case _ if P2SHScriptSignature.isValidAsm(tokens) =>
|
||||
P2SHScriptSignature.fromAsm(tokens)
|
||||
case _
|
||||
if ConditionalScriptSignature.isValidConditionalScriptSig(tokens) =>
|
||||
case _ if ConditionalScriptSignature.isValidAsm(tokens) =>
|
||||
ConditionalScriptSignature.fromAsm(tokens)
|
||||
case _
|
||||
if MultiSignatureScriptSignature.isMultiSignatureScriptSignature(
|
||||
tokens) =>
|
||||
case _ if MultiSignatureScriptSignature.isValidAsm(tokens) =>
|
||||
MultiSignatureScriptSignature.fromAsm(tokens)
|
||||
case _ if P2PKHScriptSignature.isP2PKHScriptSig(tokens) =>
|
||||
case _ if P2PKHScriptSignature.isValidAsm(tokens) =>
|
||||
P2PKHScriptSignature.fromAsm(tokens)
|
||||
case _ if P2PKScriptSignature.isP2PKScriptSignature(tokens) =>
|
||||
case _ if P2PKScriptSignature.isValidAsm(tokens) =>
|
||||
P2PKScriptSignature.fromAsm(tokens)
|
||||
case _ => NonStandardScriptSignature.fromAsm(tokens)
|
||||
}
|
||||
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = true
|
||||
}
|
||||
|
@ -278,12 +278,11 @@ case class PSBT(
|
||||
val out = tx.outputs(txIn.previousOutput.vout.toInt)
|
||||
|
||||
val outIsWitnessScript =
|
||||
WitnessScriptPubKey.isWitnessScriptPubKey(out.scriptPubKey.asm)
|
||||
WitnessScriptPubKey.isValidAsm(out.scriptPubKey.asm)
|
||||
val hasWitScript = inputMap.witnessScriptOpt.isDefined
|
||||
val hasWitRedeemScript =
|
||||
inputMap.redeemScriptOpt.isDefined && WitnessScriptPubKey
|
||||
.isWitnessScriptPubKey(
|
||||
inputMap.redeemScriptOpt.get.redeemScript.asm)
|
||||
.isValidAsm(inputMap.redeemScriptOpt.get.redeemScript.asm)
|
||||
val notBIP143Vulnerable = {
|
||||
!out.scriptPubKey.isInstanceOf[WitnessScriptPubKeyV0] && !(
|
||||
hasWitRedeemScript &&
|
||||
@ -317,7 +316,7 @@ case class PSBT(
|
||||
* @return PSBT with added tx
|
||||
*/
|
||||
def addWitnessUTXOToInput(output: TransactionOutput, index: Int): PSBT = {
|
||||
require(WitnessScriptPubKey.isWitnessScriptPubKey(output.scriptPubKey.asm),
|
||||
require(WitnessScriptPubKey.isValidAsm(output.scriptPubKey.asm),
|
||||
s"Given output was not a Witness UTXO: $output")
|
||||
require(
|
||||
index < inputMaps.size,
|
||||
@ -351,10 +350,10 @@ case class PSBT(
|
||||
|
||||
val inputMap = inputMaps(index)
|
||||
|
||||
val isWitScript = WitnessScriptPubKey.isWitnessScriptPubKey(script.asm)
|
||||
val isWitScript = WitnessScriptPubKey.isValidAsm(script.asm)
|
||||
val redeemScriptOpt = inputMap.redeemScriptOpt
|
||||
val hasRedeemScript = redeemScriptOpt.isDefined && WitnessScriptPubKey
|
||||
.isWitnessScriptPubKey(redeemScriptOpt.get.redeemScript.asm)
|
||||
.isValidAsm(redeemScriptOpt.get.redeemScript.asm)
|
||||
|
||||
val elements = if (!isWitScript && hasRedeemScript) {
|
||||
inputMap.filterRecords(WitnessScriptKeyId) :+ InputPSBTRecord
|
||||
@ -487,9 +486,9 @@ case class PSBT(
|
||||
|
||||
val outputMap = outputMaps(index)
|
||||
val redeemScriptOpt = outputMap.redeemScriptOpt.map(_.redeemScript)
|
||||
val isWitScript = WitnessScriptPubKey.isWitnessScriptPubKey(script.asm)
|
||||
val isWitScript = WitnessScriptPubKey.isValidAsm(script.asm)
|
||||
val hasWitScript = redeemScriptOpt.isDefined && WitnessScriptPubKey
|
||||
.isWitnessScriptPubKey(redeemScriptOpt.get.asm)
|
||||
.isValidAsm(redeemScriptOpt.get.asm)
|
||||
|
||||
val newElement =
|
||||
if (!isWitScript && hasWitScript)
|
||||
|
@ -341,7 +341,6 @@ object P2PKWithTimeoutScriptPubKey
|
||||
buildScript(
|
||||
asm = asm.toVector,
|
||||
constructor = P2PKWithTimeoutScriptPubKeyImpl.apply,
|
||||
invariant = isP2PKWithTimeoutScriptPubKey,
|
||||
errorMsg = s"Given asm was not a P2PKWithTimeoutScriptPubKey, got $asm"
|
||||
)
|
||||
}
|
||||
@ -368,7 +367,7 @@ object P2PKWithTimeoutScriptPubKey
|
||||
)
|
||||
}
|
||||
|
||||
def isP2PKWithTimeoutScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
if (asm.length == 12) {
|
||||
val pubKey = ECPublicKey.fromBytes(asm(2).bytes)
|
||||
val lockTimeTry = Try(ScriptNumber.fromBytes(asm(5).bytes))
|
||||
@ -393,7 +392,7 @@ We now need to ensure that `ScriptPubKey.fromAsm(p2pkWithTimeoutSPK.asm)` return
|
||||
```scala mdoc:compile-only
|
||||
asm match {
|
||||
case Nil => EmptyScriptPubKey
|
||||
case _ if P2PKWithTimeoutScriptPubKey.isP2PKWithTimeoutScriptPubKey(asm) =>
|
||||
case _ if P2PKWithTimeoutScriptPubKey.isValidAsm(asm) =>
|
||||
P2PKWithTimeoutScriptPubKey.fromAsm(asm)
|
||||
//...
|
||||
}
|
||||
@ -430,7 +429,6 @@ object P2PKScriptSignature extends ScriptFactory[P2PKScriptSignature] {
|
||||
def fromAsm(asm: Seq[ScriptToken]): P2PKScriptSignature = {
|
||||
buildScript(asm.toVector,
|
||||
P2PKScriptSignatureImpl(_),
|
||||
isP2PKScriptSignature(_),
|
||||
"The given asm tokens were not a p2pk script sig: " + asm)
|
||||
}
|
||||
|
||||
@ -442,7 +440,7 @@ object P2PKScriptSignature extends ScriptFactory[P2PKScriptSignature] {
|
||||
}
|
||||
|
||||
/** P2PK scriptSigs always have the pattern [pushop, digitalSignature] */
|
||||
def isP2PKScriptSignature(asm: Seq[ScriptToken]): Boolean = asm match {
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = asm match {
|
||||
case Seq(_: BytesToPushOntoStack, _: ScriptConstant) => true
|
||||
case _ => false
|
||||
}
|
||||
@ -464,7 +462,6 @@ object P2PKWithTimeoutScriptSignature
|
||||
buildScript(
|
||||
asm.toVector,
|
||||
ConditionalScriptSignature.fromAsm,
|
||||
isP2PKWithTimeoutScriptSignature,
|
||||
s"The given asm tokens were not a P2PKWithTimeoutScriptSignature, got $asm"
|
||||
)
|
||||
}
|
||||
@ -475,9 +472,9 @@ object P2PKWithTimeoutScriptSignature
|
||||
ConditionalScriptSignature(P2PKScriptSignature(signature), beforeTimeout)
|
||||
}
|
||||
|
||||
def isP2PKWithTimeoutScriptSignature(asm: Seq[ScriptToken]): Boolean = {
|
||||
P2PKScriptSignature.isP2PKScriptSignature(asm.dropRight(1)) && ConditionalScriptSignature
|
||||
.isValidConditionalScriptSig(asm)
|
||||
override def isValidAsm(asm: Seq[ScriptToken]): Boolean = {
|
||||
P2PKScriptSignature.isValidAsm(asm.dropRight(1)) && ConditionalScriptSignature
|
||||
.isValidAsm(asm)
|
||||
}
|
||||
}
|
||||
```
|
||||
@ -491,7 +488,7 @@ If you added a new `ScriptSignature` type in the previous step, you must add a `
|
||||
```scala mdoc:compile-only
|
||||
tokens match {
|
||||
//...
|
||||
case _ if P2PKScriptSignature.isP2PKScriptSignature(tokens) =>
|
||||
case _ if P2PKScriptSignature.isValidAsm(tokens) =>
|
||||
P2PKScriptSignature.fromAsm(tokens)
|
||||
//...
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user