mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 15:02:17 +01:00
Adding EscrowTimeScriptSignature to ScriptSignature.fromAsm -- we can now correctly type EscrowTimeoutScriptSignature from the only the asm
This commit is contained in:
parent
c457a957db
commit
c08d3fc70a
5 changed files with 29 additions and 27 deletions
|
@ -404,6 +404,8 @@ object ScriptSignature extends Factory[ScriptSignature] with BitcoinSLogger {
|
|||
case Nil => EmptyScriptSignature
|
||||
case _ if (tokens.size > 1 && P2SHScriptSignature.isRedeemScript(tokens.last)) =>
|
||||
P2SHScriptSignature.fromAsm(tokens)
|
||||
case _ if EscrowTimeoutScriptSignature.isEscrowTimeoutScriptSig(tokens) =>
|
||||
EscrowTimeoutScriptSignature.fromAsm(tokens)
|
||||
case _ if (MultiSignatureScriptSignature.isMultiSignatureScriptSignature(tokens)) =>
|
||||
MultiSignatureScriptSignature.fromAsm(tokens)
|
||||
case _ if P2PKHScriptSignature.isP2PKHScriptSig(tokens) => P2PKHScriptSignature.fromAsm(tokens)
|
||||
|
@ -449,9 +451,9 @@ object ScriptSignature extends Factory[ScriptSignature] with BitcoinSLogger {
|
|||
* if the last element of the [[asm]] evaluates to false, it is a scriptsig that attempts to spend the timeout
|
||||
* */
|
||||
sealed trait EscrowTimeoutScriptSignature extends ScriptSignature {
|
||||
def scriptSig: ScriptSignature = ScriptSignature(hex)
|
||||
def scriptSig: ScriptSignature = ScriptSignature(bytes.take(bytes.length - 1))
|
||||
override def signatures = scriptSig.signatures
|
||||
override def toString = "EscrowWithTimeoutScriptSignature(" + scriptSig + ")"
|
||||
override def toString = "EscrowTimeoutScriptSignature(" + hex + ")"
|
||||
|
||||
/** Checks if the given asm fulfills the timeout or escrow of the [[EscrowTimeoutScriptPubKey]] */
|
||||
def isEscrow: Boolean = BitcoinScriptUtil.castToBool(asm.last)
|
||||
|
@ -468,7 +470,7 @@ object EscrowTimeoutScriptSignature extends Factory[EscrowTimeoutScriptSignature
|
|||
}
|
||||
|
||||
def fromAsm(asm: Seq[ScriptToken], scriptPubKey: EscrowTimeoutScriptPubKey): EscrowTimeoutScriptSignature = {
|
||||
require(isValidEscrowTimeoutScriptSig(asm,scriptPubKey), "Given asm was not a EscrowWithTimeoutScriptSignature, got: " + asm)
|
||||
require(isEscrowTimeoutScriptSig(asm, Some(scriptPubKey)), "Given asm was not a EscrowWithTimeoutScriptSignature, got: " + asm)
|
||||
val asmHex = asm.map(_.hex).mkString
|
||||
val c = CompactSizeUInt.calculateCompactSizeUInt(asmHex)
|
||||
val fullHex = c.hex + asmHex
|
||||
|
@ -490,16 +492,24 @@ object EscrowTimeoutScriptSignature extends Factory[EscrowTimeoutScriptSignature
|
|||
fromBytes(fullBytes)
|
||||
}
|
||||
|
||||
def isValidEscrowTimeoutScriptSig(asm: Seq[ScriptToken],
|
||||
scriptPubKey: EscrowTimeoutScriptPubKey): Boolean = {
|
||||
def isEscrowTimeoutScriptSig(asm: Seq[ScriptToken], scriptPubKey: Option[EscrowTimeoutScriptPubKey] = None): Boolean = {
|
||||
val nested = asm.take(asm.length - 1)
|
||||
val isMultiSig = BitcoinScriptUtil.castToBool(asm.last)
|
||||
if (isMultiSig) {
|
||||
val last = asm.last
|
||||
val validIfToken = last == OP_0 || last == OP_1
|
||||
val isMultiSig = BitcoinScriptUtil.castToBool(last)
|
||||
if (isMultiSig && validIfToken) {
|
||||
MultiSignatureScriptSignature.isMultiSignatureScriptSignature(nested)
|
||||
} else {
|
||||
val locktimeScript = scriptPubKey.timeout.nestedScriptPubKey
|
||||
Try(ScriptSignature(nested,locktimeScript)).isSuccess
|
||||
}
|
||||
} else if (validIfToken) {
|
||||
//if they provide the [[EscrowTimeoutScriptPubKey]] we can detected
|
||||
// if we have a valid scriptsig for the timeout branch
|
||||
// if they do not provide it, we have to guess that it
|
||||
// is the timeout branch since we can nest ANY scriptPubKey inside of a [[LockTimeScriptPubKey]]
|
||||
val isValidTimeout = scriptPubKey.map { s =>
|
||||
val locktimeScript = s.timeout.nestedScriptPubKey
|
||||
Try(ScriptSignature.fromScriptPubKey(asm,locktimeScript)).isSuccess
|
||||
}
|
||||
isValidTimeout.getOrElse(true)
|
||||
} else false
|
||||
}
|
||||
|
||||
def apply(scriptSig: ScriptSignature): Try[EscrowTimeoutScriptSignature] = scriptSig match {
|
||||
|
|
|
@ -61,7 +61,7 @@ trait RawTransactionInputParser extends RawBitcoinSerializer[Seq[TransactionInpu
|
|||
|
||||
val scriptSigBytes = bytes.slice(outPointBytesSize,bytes.size)
|
||||
logger.debug("Scriptsig bytes: " + BitcoinSUtil.encodeHex(scriptSigBytes))
|
||||
val scriptSig : ScriptSignature = RawScriptSignatureParser.read(scriptSigBytes)
|
||||
val scriptSig: ScriptSignature = RawScriptSignatureParser.read(scriptSigBytes)
|
||||
logger.debug("Script sig parsed bytes: " + BitcoinSUtil.encodeHex(scriptSig.bytes))
|
||||
val sequenceBytesSize = 4
|
||||
val endOfScriptSigBytes = outPointBytesSize + scriptSig.bytes.size
|
||||
|
|
|
@ -12,7 +12,7 @@ import org.scalacheck.{Prop, Properties}
|
|||
class BitcoinAddressSpec extends Properties("BitcoinAddressSpec") {
|
||||
|
||||
property("get the same p2sh address no matter what factory function we use") =
|
||||
Prop.forAll(ScriptGenerators.pickRandomNonP2SHScriptPubKey) { case (scriptPubKey,_) =>
|
||||
Prop.forAll(ScriptGenerators.randomNonP2SHScriptPubKey) { case (scriptPubKey,_) =>
|
||||
//we should get the same address no matter which factory function we use
|
||||
val p2shScriptPubKey = P2SHScriptPubKey(scriptPubKey)
|
||||
P2SHAddress(scriptPubKey, TestNet3) == P2SHAddress(p2shScriptPubKey,TestNet3)
|
||||
|
@ -20,7 +20,7 @@ class BitcoinAddressSpec extends Properties("BitcoinAddressSpec") {
|
|||
}
|
||||
|
||||
property("All p2sh addresses created from factory functions must be valid") =
|
||||
Prop.forAll(ScriptGenerators.pickRandomNonP2SHScriptPubKey) { case (scriptPubKey,_) =>
|
||||
Prop.forAll(ScriptGenerators.randomNonP2SHScriptPubKey) { case (scriptPubKey,_) =>
|
||||
//we should get the same address no matter which factory function we use
|
||||
val addr = P2SHAddress(scriptPubKey, TestNet3)
|
||||
P2SHAddress.isP2SHAddress(addr)
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
package org.bitcoins.core.protocol.script
|
||||
|
||||
|
||||
import org.bitcoins.core.crypto.{ECDigitalSignature, EmptyDigitalSignature}
|
||||
import org.bitcoins.core.script.constant.{BytesToPushOntoStack, OP_0, ScriptConstant}
|
||||
import org.bitcoins.core.util.TransactionTestUtil
|
||||
import org.bitcoins.core.util.{BitcoinSLogger, TransactionTestUtil}
|
||||
import org.scalatest.{FlatSpec, MustMatchers}
|
||||
|
||||
/**
|
||||
* Created by chris on 3/8/16.
|
||||
*/
|
||||
class MultiSignatureScriptSignatureTest extends FlatSpec with MustMatchers {
|
||||
class MultiSignatureScriptSignatureTest extends FlatSpec with MustMatchers with BitcoinSLogger {
|
||||
|
||||
"MultiSignatureScriptSignature" must "find all of the digital signatures for a multisignature scriptSig" in {
|
||||
val (spendingTx,inputIndex,_,_) = TransactionTestUtil.signedMultiSignatureTransaction
|
||||
|
@ -17,11 +15,4 @@ class MultiSignatureScriptSignatureTest extends FlatSpec with MustMatchers {
|
|||
scriptSig.signatures.size must be (2)
|
||||
}
|
||||
|
||||
it must "give us the empty signature back when it is encoded as an OP_0 (this pushes an empty signature onto the stack)" in {
|
||||
val multiSigScriptSignature = ScriptSignature.fromAsm(List(OP_0, BytesToPushOntoStack(71),
|
||||
ScriptConstant("30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201"), OP_0))
|
||||
multiSigScriptSignature.signatures must be (Seq(
|
||||
ECDigitalSignature("30440220b119d67d389315308d1745f734a51ff3ec72e06081e84e236fdf9dc2f5d2a64802204b04e3bc38674c4422ea317231d642b56dc09d214a1ecbbf16ecca01ed996e2201"),
|
||||
EmptyDigitalSignature))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,8 @@ import org.scalacheck.{Prop, Properties}
|
|||
class TransactionInputSpec extends Properties("TranactionInputSpec") with BitcoinSLogger {
|
||||
|
||||
property("Serialization symmetry") =
|
||||
Prop.forAll(TransactionGenerators.inputs) { input =>
|
||||
TransactionInput(input.hex) == input
|
||||
Prop.forAllNoShrink(TransactionGenerators.inputs) { input =>
|
||||
val result = TransactionInput(input.hex) == input
|
||||
result
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue