ScriptSignature from P2WSH Witness (#1605)

This commit is contained in:
Nadav Kohen 2020-06-24 15:44:16 -05:00 committed by GitHub
parent 876d419939
commit b92a93c912
3 changed files with 39 additions and 1 deletions

View file

@ -19,4 +19,12 @@ class ScriptWitnessSpec extends Properties("ScriptWitnessSpec") {
P2WSHWitnessV0(spk).redeemScript == spk
}
}
property("pull script signature out of p2wsh witness") = {
Prop.forAll(ScriptGenerators.rawScriptPubKey,
ScriptGenerators.rawScriptSignature) {
case ((spk, _), scriptSig) =>
P2WSHWitnessV0(spk, scriptSig).scriptSignature == scriptSig
}
}
}

View file

@ -1,7 +1,11 @@
package org.bitcoins.core.protocol.script
import org.bitcoins.core.protocol.CompactSizeUInt
import org.bitcoins.core.serializers.script.RawScriptWitnessParser
import org.bitcoins.core.script.constant.{OP_0, ScriptNumberOperation}
import org.bitcoins.core.serializers.script.{
RawScriptWitnessParser,
ScriptParser
}
import org.bitcoins.core.util.{BitcoinScriptUtil, BytesUtil}
import org.bitcoins.crypto.{
ECDigitalSignature,
@ -106,6 +110,21 @@ sealed abstract class P2WSHWitnessV0 extends ScriptWitnessV0 {
relevantStack.map(ECDigitalSignature.fromBytes)
}
// Note that this is not guaranteed to work for non-standard script signatures
lazy val scriptSignature: ScriptSignature = {
val asm = stack.toVector.tail.reverse.flatMap { bytes =>
if (bytes.isEmpty) {
Vector(OP_0)
} else if (bytes.length == 1 && bytes.head <= 16 && bytes.head >= -1) {
ScriptNumberOperation.fromNumber(bytes.head.toLong).toVector
} else {
ScriptParser.fromBytes(CompactSizeUInt.calc(bytes).bytes ++ bytes)
}
}
ScriptSignature.fromAsm(asm)
}
override def toString =
s"P2WSHWitnessV0(${stack.map(BytesUtil.encodeHex(_)).toString})"
}

View file

@ -539,6 +539,17 @@ sealed abstract class ScriptGenerators extends BitcoinSLogger {
)
}
def rawScriptSignature: Gen[ScriptSignature] = {
Gen.oneOf(
p2pkScriptSignature,
p2pkhScriptSignature,
p2pkWithTimeoutScriptSignature,
multiSignatureScriptSignature,
emptyScriptSignature,
conditionalScriptSignature
)
}
/**
* Generates a `ScriptSignature` corresponding to the type of
* `ScriptPubKey` given.