Creating LockTimeScriptPubKey type to generecize different locktime types, refactoring EscrowTimeout to accept LockTimeScriptPubKeys instead of only CSVScriptPubKeys

This commit is contained in:
Chris Stewart 2017-04-02 14:10:29 -05:00
parent 365c0a698b
commit 13c8960a04
7 changed files with 99 additions and 98 deletions

View file

@ -305,16 +305,9 @@ object P2PKScriptPubKey extends ScriptFactory[P2PKScriptPubKey] {
}
/**
* Represents a scriptPubKey that contains OP_CHECKLOCKTIMEVERIFY.
* Adds an absolute/defined locktime condition to any scriptPubKey.
* [[https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki]]
* Format: <locktime> OP_CLTV OP_DROP <scriptPubKey>
*/
sealed trait CLTVScriptPubKey extends ScriptPubKey {
/** Determines the nested ScriptPubKey inside the CLTVScriptPubKey */
def scriptPubKeyAfterCLTV : ScriptPubKey = {
sealed trait LockTimeScriptPubKey extends ScriptPubKey {
/** Determines the nested ScriptPubKey inside the LockTimeScriptPubKey */
def nestedScriptPubKey : ScriptPubKey = {
val bool : Boolean = asm.head.isInstanceOf[ScriptNumberOperation]
bool match {
case true => ScriptPubKey(asm.slice(3, asm.length))
@ -322,17 +315,43 @@ sealed trait CLTVScriptPubKey extends ScriptPubKey {
}
}
/** The absolute CLTV-LockTime value (i.e. the output will remain unspendable until this timestamp or block height */
/** The relative locktime value (i.e. the amount of time the output should remain unspendable) */
def locktime : ScriptNumber = {
asm.head match {
case scriptNumOp: ScriptNumberOperation => ScriptNumber(scriptNumOp.underlying)
case pushBytes : BytesToPushOntoStack => ScriptNumber(asm(1).hex)
case x @ (_ : ScriptConstant | _ : ScriptOperation) => throw new IllegalArgumentException("In a CLTVScriptPubKey, " +
case _: BytesToPushOntoStack => ScriptNumber(asm(1).hex)
case x @ (_ : ScriptConstant | _ : ScriptOperation) => throw new IllegalArgumentException("In a LockTimeScriptPubKey, " +
"the first asm must be either a ScriptNumberOperation (i.e. OP_5), or the BytesToPushOntoStack for the proceeding ScriptConstant.")
}
}
}
object LockTimeScriptPubKey extends ScriptFactory[LockTimeScriptPubKey] {
override def fromBytes(bytes: Seq[Byte]): LockTimeScriptPubKey = {
val asm = RawScriptPubKeyParser.read(bytes).asm
fromAsm(asm)
}
def fromAsm(asm: Seq[ScriptToken]): LockTimeScriptPubKey = {
require(isValidLockTimeScriptPubKey(asm))
if (asm.contains(OP_CHECKLOCKTIMEVERIFY)) CLTVScriptPubKey(asm)
else if (asm.contains(OP_CHECKSEQUENCEVERIFY)) CSVScriptPubKey(asm)
else throw new IllegalArgumentException("Given asm was not a LockTimeScriptPubKey, got: " + asm)
}
def isValidLockTimeScriptPubKey(asm: Seq[ScriptToken]): Boolean = {
CLTVScriptPubKey.isCLTVScriptPubKey(asm) || CSVScriptPubKey.isCSVScriptPubKey(asm)
}
}
/**
* Represents a scriptPubKey that contains OP_CHECKLOCKTIMEVERIFY.
* Adds an absolute/defined locktime condition to any scriptPubKey.
* [[https://github.com/bitcoin/bips/blob/master/bip-0065.mediawiki]]
* Format: <locktime> OP_CLTV OP_DROP <scriptPubKey>
*/
sealed trait CLTVScriptPubKey extends LockTimeScriptPubKey
object CLTVScriptPubKey extends ScriptFactory[CLTVScriptPubKey] {
private case class CLTVScriptPubKeyImpl(hex : String) extends CLTVScriptPubKey
@ -402,28 +421,7 @@ object CLTVScriptPubKey extends ScriptFactory[CLTVScriptPubKey] {
* https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki
* Format: <locktime> OP_CSV OP_DROP <scriptPubKey>
*/
sealed trait CSVScriptPubKey extends ScriptPubKey {
/** Determines the nested ScriptPubKey inside the CSVScriptPubKey */
def scriptPubKeyAfterCSV : ScriptPubKey = {
val bool : Boolean = asm.head.isInstanceOf[ScriptNumberOperation]
bool match {
case true => ScriptPubKey(asm.slice(3, asm.length))
case false => ScriptPubKey(asm.slice(4, asm.length))
}
}
/** The relative CSV-LockTime value (i.e. the amount of time the output should remain unspendable) */
def locktime : ScriptNumber = {
asm.head match {
case scriptNumOp: ScriptNumberOperation => ScriptNumber(scriptNumOp.underlying)
case pushBytes : BytesToPushOntoStack => ScriptNumber(asm(1).hex)
case x @ (_ : ScriptConstant | _ : ScriptOperation) => throw new IllegalArgumentException("In a CSVScriptPubKey, " +
"the first asm must be either a ScriptNumberOperation (i.e. OP_5), or the BytesToPushOntoStack for the proceeding ScriptConstant.")
}
}
}
sealed trait CSVScriptPubKey extends LockTimeScriptPubKey
object CSVScriptPubKey extends ScriptFactory[CSVScriptPubKey] {
private case class CSVScriptPubKeyImpl(hex : String) extends CSVScriptPubKey
@ -515,7 +513,7 @@ object ScriptPubKey extends Factory[ScriptPubKey] with BitcoinSLogger {
case _ if CSVScriptPubKey.isCSVScriptPubKey(asm) => CSVScriptPubKey(asm)
case _ if WitnessScriptPubKey.isWitnessScriptPubKey(asm) => WitnessScriptPubKey(asm).get
case _ if WitnessCommitment.isWitnessCommitment(asm) => WitnessCommitment(asm)
case _ if CSVEscrowTimeoutScriptPubKey.isValidCSVEscrowTimeout(asm) => CSVEscrowTimeoutScriptPubKey.fromAsm(asm)
case _ if EscrowTimeoutScriptPubKey.isValidEscrowTimeout(asm) => EscrowTimeoutScriptPubKey.fromAsm(asm)
case _ => NonStandardScriptPubKey(asm)
}
@ -670,9 +668,9 @@ object WitnessCommitment extends ScriptFactory[WitnessCommitment] {
/** Represents a [[ScriptPubKey]] that either times out allowing Alice to spend from the scriptpubkey
* or allows a federation to spend from the escrow
* [[https://github.com/bitcoin/bips/blob/master/bip-0112.mediawiki#contracts-with-expiration-deadlines]]
* Format: OP_IF <multsig scriptpubkey> OP_ELSE <csv scriptPubKey> OP_ENDIF
* Format: OP_IF <multsig scriptpubkey> OP_ELSE <locktime scriptPubKey> OP_ENDIF
*/
sealed trait CSVEscrowTimeoutScriptPubKey extends ScriptPubKey {
sealed trait EscrowTimeoutScriptPubKey extends ScriptPubKey {
/** The [[MultiSignatureScriptPubKey]] that can be used to spend funds */
def escrow: MultiSignatureScriptPubKey = {
val escrowAsm = asm.slice(1,opElseIndex)
@ -680,9 +678,9 @@ sealed trait CSVEscrowTimeoutScriptPubKey extends ScriptPubKey {
}
/** The [[CSVScriptPubKey]] that you can spend funds from after a certain timeout */
def timeout: CSVScriptPubKey = {
def timeout: LockTimeScriptPubKey = {
val timeoutAsm = asm.slice(opElseIndex+1, asm.length-1)
CSVScriptPubKey(timeoutAsm)
LockTimeScriptPubKey.fromAsm(timeoutAsm)
}
private def opElseIndex: Int = {
@ -692,19 +690,19 @@ sealed trait CSVEscrowTimeoutScriptPubKey extends ScriptPubKey {
}
}
object CSVEscrowTimeoutScriptPubKey extends ScriptFactory[CSVEscrowTimeoutScriptPubKey] {
private case class CSVEscrowTimeoutScriptPubKeyImpl(hex: String) extends CSVEscrowTimeoutScriptPubKey
object EscrowTimeoutScriptPubKey extends ScriptFactory[EscrowTimeoutScriptPubKey] {
private case class EscrowTimeoutScriptPubKeyImpl(hex: String) extends EscrowTimeoutScriptPubKey
override def fromBytes(bytes: Seq[Byte]): CSVEscrowTimeoutScriptPubKey = {
override def fromBytes(bytes: Seq[Byte]): EscrowTimeoutScriptPubKey = {
val asm = RawScriptPubKeyParser.read(bytes).asm
fromAsm(asm)
}
override def fromAsm(asm: Seq[ScriptToken]): CSVEscrowTimeoutScriptPubKey = {
buildScript(asm, CSVEscrowTimeoutScriptPubKeyImpl(_), isValidCSVEscrowTimeout(_), "Given asm was not a valid CSVEscrowTimeout, got: " + asm)
override def fromAsm(asm: Seq[ScriptToken]): EscrowTimeoutScriptPubKey = {
buildScript(asm, EscrowTimeoutScriptPubKeyImpl(_), isValidEscrowTimeout(_), "Given asm was not a valid CSVEscrowTimeout, got: " + asm)
}
def isValidCSVEscrowTimeout(asm: Seq[ScriptToken]): Boolean = {
def isValidEscrowTimeout(asm: Seq[ScriptToken]): Boolean = {
val opElseIndex = asm.indexOf(OP_ELSE)
val correctControlStructure = asm.headOption.contains(OP_IF) && asm.last == OP_ENDIF && opElseIndex != -1
if (correctControlStructure) {
@ -716,7 +714,7 @@ object CSVEscrowTimeoutScriptPubKey extends ScriptFactory[CSVEscrowTimeoutScript
} else false
}
def apply(escrow: MultiSignatureScriptPubKey, timeout: CSVScriptPubKey): CSVEscrowTimeoutScriptPubKey = {
def apply(escrow: MultiSignatureScriptPubKey, timeout: LockTimeScriptPubKey): EscrowTimeoutScriptPubKey = {
fromAsm(Seq(OP_IF) ++ escrow.asm ++ Seq(OP_ELSE) ++ timeout.asm ++ Seq(OP_ENDIF))
}
}

View file

@ -214,16 +214,12 @@ object P2SHScriptSignature extends ScriptFactory[P2SHScriptSignature] {
redeemScriptTry match {
case Success(redeemScript) =>
redeemScript match {
case x : P2PKHScriptPubKey => true
case x : MultiSignatureScriptPubKey => true
case x : P2SHScriptPubKey => true
case x : P2PKScriptPubKey => true
case x : CLTVScriptPubKey => true
case x : CSVScriptPubKey => true
case x : WitnessScriptPubKeyV0 => true
case x : UnassignedWitnessScriptPubKey => true
case x : NonStandardScriptPubKey => false
case x : WitnessCommitment => false
case _: P2PKHScriptPubKey | _: MultiSignatureScriptPubKey
| _: P2SHScriptPubKey | _: P2PKScriptPubKey
| _: CLTVScriptPubKey | _: CSVScriptPubKey
| _: WitnessScriptPubKeyV0 | _: UnassignedWitnessScriptPubKey
| _: EscrowTimeoutScriptPubKey => true
case _: NonStandardScriptPubKey | _: WitnessCommitment => false
case EmptyScriptPubKey => false
}
case Failure(_) => false
@ -376,8 +372,8 @@ object CLTVScriptSignature extends Factory[CLTVScriptSignature] {
case p2pkScriptPubKey : P2PKScriptPubKey => CLTVScriptSignature(P2PKScriptSignature(sigs.head))
case p2pkhScriptPubKey : P2PKHScriptPubKey => CLTVScriptSignature(P2PKHScriptSignature(sigs.head, pubKeys.head))
case multiSigScriptPubKey : MultiSignatureScriptPubKey => CLTVScriptSignature(MultiSignatureScriptSignature(sigs))
case cltvScriptPubKey : CLTVScriptPubKey => apply(cltvScriptPubKey.scriptPubKeyAfterCLTV, sigs, pubKeys)
case csvScriptPubKey : CSVScriptPubKey => apply(csvScriptPubKey.scriptPubKeyAfterCSV, sigs, pubKeys)
case cltvScriptPubKey : CLTVScriptPubKey => apply(cltvScriptPubKey.nestedScriptPubKey, sigs, pubKeys)
case csvScriptPubKey : CSVScriptPubKey => apply(csvScriptPubKey.nestedScriptPubKey, sigs, pubKeys)
case EmptyScriptPubKey => CLTVScriptSignature(EmptyScriptSignature)
case _: WitnessScriptPubKeyV0 | _ : UnassignedWitnessScriptPubKey =>
//bare segwit always has an empty script sig, see BIP141
@ -421,10 +417,10 @@ object CSVScriptSignature extends Factory[CSVScriptSignature] {
case _: P2PKScriptPubKey => CSVScriptSignature(P2PKScriptSignature(sigs.head))
case _: P2PKHScriptPubKey => CSVScriptSignature(P2PKHScriptSignature(sigs.head, pubKeys.head))
case _: MultiSignatureScriptPubKey => CSVScriptSignature(MultiSignatureScriptSignature(sigs))
case cltvScriptPubKey : CLTVScriptPubKey => CSVScriptSignature(cltvScriptPubKey.scriptPubKeyAfterCLTV, sigs, pubKeys)
case csvScriptPubKey : CSVScriptPubKey => CSVScriptSignature(csvScriptPubKey.scriptPubKeyAfterCSV, sigs, pubKeys)
case csvEscrowTimeout: CSVEscrowTimeoutScriptPubKey =>
CSVScriptSignature(csvEscrowTimeout.timeout.scriptPubKeyAfterCSV,sigs,pubKeys)
case cltvScriptPubKey : CLTVScriptPubKey => CSVScriptSignature(cltvScriptPubKey.nestedScriptPubKey, sigs, pubKeys)
case csvScriptPubKey : CSVScriptPubKey => CSVScriptSignature(csvScriptPubKey.nestedScriptPubKey, sigs, pubKeys)
case csvEscrowTimeout: EscrowTimeoutScriptPubKey =>
CSVScriptSignature(csvEscrowTimeout.timeout.nestedScriptPubKey,sigs,pubKeys)
case EmptyScriptPubKey => CSVScriptSignature(EmptyScriptSignature)
case _: WitnessScriptPubKeyV0 | _ : UnassignedWitnessScriptPubKey =>
//bare segwit always has an empty script sig, see BIP141
@ -477,10 +473,10 @@ object ScriptSignature extends Factory[ScriptSignature] with BitcoinSLogger {
case _: NonStandardScriptPubKey => Try(NonStandardScriptSignature.fromAsm(tokens))
case s : CLTVScriptPubKey => fromScriptPubKey(tokens, s.scriptPubKeyAfterCLTV)
case s : CSVScriptPubKey => fromScriptPubKey(tokens, s.scriptPubKeyAfterCSV)
case escrowWithTimeout : CSVEscrowTimeoutScriptPubKey =>
val isMultiSig = BitcoinScriptUtil.castToBool(tokens.head)
if (isMultiSig) Try(MultiSignatureScriptSignature.fromAsm(tokens.tail))
else Try(CSVEscrowTimeoutScriptSignature.fromAsm(tokens,escrowWithTimeout))
case escrowWithTimeout : EscrowTimeoutScriptPubKey =>
val isMultSig = BitcoinScriptUtil.castToBool(tokens.head)
if (isMultSig) Try(MultiSignatureScriptSignature.fromAsm(tokens.tail))
else Try(EscrowTimeoutScriptSignature.fromAsm(tokens,escrowWithTimeout))
case _: WitnessScriptPubKeyV0 | _: UnassignedWitnessScriptPubKey => Success(EmptyScriptSignature)
case EmptyScriptPubKey =>
if (tokens.isEmpty) Success(EmptyScriptSignature) else Try(NonStandardScriptSignature.fromAsm(tokens))
@ -492,41 +488,41 @@ object ScriptSignature extends Factory[ScriptSignature] with BitcoinSLogger {
}
}
/** [[ScriptSignature]] that spends a [[CSVEscrowTimeoutScriptPubKey]], the underlying script signature can be
/** [[ScriptSignature]] that spends a [[EscrowTimeoutScriptPubKey]], the underlying script signature can be
* a [[MultiSignatureScriptSignature]] or a [[CSVScriptSignature]] as those are te two underlying scripts
* of a [[CSVEscrowTimeoutScriptPubKey]]
* of a [[EscrowTimeoutScriptPubKey]]
*
* If the last element of the [[asm]] evaluates to true, it is a scriptsig that attempts to spend the escrow
* if the last element of the [[asm]] evaluates to false, it is a scriptsig that attempts to spend the timeout
* */
sealed trait CSVEscrowTimeoutScriptSignature extends ScriptSignature {
sealed trait EscrowTimeoutScriptSignature extends ScriptSignature {
def scriptSig: ScriptSignature = ScriptSignature(hex)
override def signatures = scriptSig.signatures
override def toString = "CSVEscrowWithTimeoutScriptSignature(" + scriptSig + ")"
/** Checks if the given asm fulfills the timeout or escrow of the [[CSVEscrowTimeoutScriptPubKey]] */
/** Checks if the given asm fulfills the timeout or escrow of the [[EscrowTimeoutScriptPubKey]] */
def isEscrow: Boolean = BitcoinScriptUtil.castToBool(asm.last)
def isTimeout: Boolean = !isEscrow
}
object CSVEscrowTimeoutScriptSignature extends Factory[CSVEscrowTimeoutScriptSignature] {
private case class CSVEscrowTimeoutScriptSignatureImpl(hex: String) extends CSVEscrowTimeoutScriptSignature
object EscrowTimeoutScriptSignature extends Factory[EscrowTimeoutScriptSignature] {
private case class EscrowTimeoutScriptSignatureImpl(hex: String) extends EscrowTimeoutScriptSignature
override def fromBytes(bytes: Seq[Byte]): CSVEscrowTimeoutScriptSignature = {
CSVEscrowTimeoutScriptSignatureImpl(BitcoinSUtil.encodeHex(bytes))
override def fromBytes(bytes: Seq[Byte]): EscrowTimeoutScriptSignature = {
EscrowTimeoutScriptSignatureImpl(BitcoinSUtil.encodeHex(bytes))
}
def fromAsm(asm: Seq[ScriptToken], scriptPubKey: CSVEscrowTimeoutScriptPubKey): CSVEscrowTimeoutScriptSignature = {
require(isValidCSVEscrowTimeoutScriptSig(asm,scriptPubKey), "Given asm was not a CSVEscrowWithTimeoutScriptSignature, got: " + asm)
def fromAsm(asm: Seq[ScriptToken], scriptPubKey: EscrowTimeoutScriptPubKey): EscrowTimeoutScriptSignature = {
require(isValidEscrowTimeoutScriptSig(asm,scriptPubKey), "Given asm was not a CSVEscrowWithTimeoutScriptSignature, got: " + asm)
val asmHex = asm.map(_.hex).mkString
val c = CompactSizeUInt.calculateCompactSizeUInt(asmHex)
val fullHex = c.hex + asmHex
fromHex(fullHex)
}
def fromAsm(asm: Seq[ScriptToken]): CSVEscrowTimeoutScriptSignature = {
def fromAsm(asm: Seq[ScriptToken]): EscrowTimeoutScriptSignature = {
require(asm.nonEmpty)
val nested = asm.take(asm.length - 1)
val nestedScriptSig = if (BitcoinScriptUtil.castToBool(asm.last)) {
@ -541,26 +537,26 @@ object CSVEscrowTimeoutScriptSignature extends Factory[CSVEscrowTimeoutScriptSig
fromBytes(fullBytes)
}
def isValidCSVEscrowTimeoutScriptSig(asm: Seq[ScriptToken],
scriptPubKey: CSVEscrowTimeoutScriptPubKey): Boolean = {
def isValidEscrowTimeoutScriptSig(asm: Seq[ScriptToken],
scriptPubKey: EscrowTimeoutScriptPubKey): Boolean = {
val nested = asm.take(asm.length - 1)
val isMultiSig = BitcoinScriptUtil.castToBool(asm.last)
if (isMultiSig) {
MultiSignatureScriptSignature.isMultiSignatureScriptSignature(nested)
} else {
val locktimeScript = scriptPubKey.timeout.scriptPubKeyAfterCSV
val locktimeScript = scriptPubKey.timeout.nestedScriptPubKey
Try(ScriptSignature(nested,locktimeScript)).isSuccess
}
}
def apply(scriptSig: ScriptSignature): CSVEscrowTimeoutScriptSignature = fromBytes(scriptSig.bytes)
def apply(scriptSig: ScriptSignature): EscrowTimeoutScriptSignature = fromBytes(scriptSig.bytes)
def apply(multiSigScriptSig: MultiSignatureScriptSignature): CSVEscrowTimeoutScriptSignature = {
def apply(multiSigScriptSig: MultiSignatureScriptSignature): EscrowTimeoutScriptSignature = {
val asm = multiSigScriptSig.asm ++ Seq(OP_1)
fromAsm(asm)
}
def apply(csv: CSVScriptSignature): CSVEscrowTimeoutScriptSignature = {
def apply(csv: CSVScriptSignature): EscrowTimeoutScriptSignature = {
val asm = csv.asm ++ Seq(OP_0)
fromAsm(asm)
}

View file

@ -78,8 +78,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
else scriptPubKeyExecutedProgram
case _: P2PKHScriptPubKey | _: P2PKScriptPubKey | _: MultiSignatureScriptPubKey | _: CSVScriptPubKey
| _: CLTVScriptPubKey | _: NonStandardScriptPubKey | _: WitnessCommitment
| _: CSVEscrowTimeoutScriptPubKey | EmptyScriptPubKey =>
logger.info("")
| _: EscrowTimeoutScriptPubKey | EmptyScriptPubKey =>
scriptPubKeyExecutedProgram
}
}
@ -165,7 +164,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
}
case s @ (_ : P2SHScriptPubKey | _ : P2PKHScriptPubKey | _ : P2PKScriptPubKey | _ : MultiSignatureScriptPubKey
| _ : CLTVScriptPubKey | _ : CSVScriptPubKey | _: NonStandardScriptPubKey | _ : WitnessCommitment
| _: CSVEscrowTimeoutScriptPubKey | EmptyScriptPubKey) =>
| _: EscrowTimeoutScriptPubKey | EmptyScriptPubKey) =>
logger.debug("redeemScript: " + s.asm)
run(scriptPubKeyExecutedProgram,stack,s)
}
@ -520,7 +519,7 @@ trait ScriptInterpreter extends CryptoInterpreter with StackInterpreter with Con
p2shScriptSig.redeemScript.isInstanceOf[WitnessScriptPubKey]
case _: CLTVScriptPubKey | _: CSVScriptPubKey | _: MultiSignatureScriptPubKey | _: NonStandardScriptPubKey
| _: P2PKScriptPubKey | _: P2PKHScriptPubKey | _: WitnessCommitment
| _: CSVEscrowTimeoutScriptPubKey | EmptyScriptPubKey =>
| _: EscrowTimeoutScriptPubKey | EmptyScriptPubKey =>
w.witness.stack.isEmpty
}
!witnessedUsed

View file

@ -308,7 +308,7 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
}
case _: P2PKHScriptPubKey | _: P2PKScriptPubKey | _: MultiSignatureScriptPubKey
| _: NonStandardScriptPubKey | _: CLTVScriptPubKey | _: CSVScriptPubKey
| _: WitnessCommitment | _: CSVEscrowTimeoutScriptPubKey | EmptyScriptPubKey => script
| _: WitnessCommitment | _: EscrowTimeoutScriptPubKey | EmptyScriptPubKey => script
}
/** Removes the given [[ECDigitalSignature]] from the list of [[ScriptToken]] if it exists. */
@ -354,7 +354,7 @@ trait BitcoinScriptUtil extends BitcoinSLogger {
case Right(_) => Nil //error
}
/** Casts the given script token to a boolean value
/** Casts the given script token to a boolean value
* Mimics this function inside of Bitcoin Core
* [[https://github.com/bitcoin/bitcoin/blob/8c1dbc5e9ddbafb77e60e8c4e6eb275a3a76ac12/src/script/interpreter.cpp#L38]]
* All bytes in the byte vector must be zero, unless it is the last byte, which can be 0 or 0x80 (negative zero)

View file

@ -139,10 +139,18 @@ class TransactionSignatureCreatorSpec extends Properties("TransactionSignatureCr
Seq(ScriptErrorPushSize, ScriptOk).contains(result)
}
property("generate a valid signature for a csv escrow timeout transaction") =
Prop.forAll(TransactionGenerators.spendableCSVEscrowTimeoutTransaction) { txSigComponent: TransactionSignatureComponent =>
Prop.forAll(TransactionGenerators.spendableEscrowTimeoutTransaction) { txSigComponent: TransactionSignatureComponent =>
val program = ScriptProgram(txSigComponent)
val result = ScriptInterpreter.run(program)
result == ScriptOk
}
property("fail to evaluate a csv escrow timeout transaction due to invalid csv timeout values") = {
Prop.forAll(TransactionGenerators.unspendableEscrowTimeoutTransaction) { txSigComponent: TransactionSignatureComponent =>
val program = ScriptProgram(txSigComponent)
val result = ScriptInterpreter.run(program)
result == ScriptErrorUnsatisfiedLocktime
}
}
}

View file

@ -33,9 +33,9 @@ class CLTVScriptPubKeyTest extends FlatSpec with MustMatchers {
val pubKey = ECPrivateKey().publicKey
val p2pkh = P2PKHScriptPubKey(pubKey)
CLTVScriptPubKey(scriptNum17, p2pkh).scriptPubKeyAfterCLTV must be (p2pkh)
CLTVScriptPubKey(scriptNum5, p2pkh).scriptPubKeyAfterCLTV must be (p2pkh)
CLTVScriptPubKey(negativeOne, p2pkh).scriptPubKeyAfterCLTV must be (p2pkh)
CLTVScriptPubKey(scriptNum17, p2pkh).nestedScriptPubKey must be (p2pkh)
CLTVScriptPubKey(scriptNum5, p2pkh).nestedScriptPubKey must be (p2pkh)
CLTVScriptPubKey(negativeOne, p2pkh).nestedScriptPubKey must be (p2pkh)
CLTVScriptPubKey(scriptNum17, p2pkh).locktime must be (scriptNum17)
CLTVScriptPubKey(scriptNum5, p2pkh).locktime must be (scriptNum5)

View file

@ -33,9 +33,9 @@ class CSVScriptPubKeyTest extends FlatSpec with MustMatchers {
val pubKey = ECPrivateKey().publicKey
val p2pkh = P2PKHScriptPubKey(pubKey)
CSVScriptPubKey(scriptNum17, p2pkh).scriptPubKeyAfterCSV must be(p2pkh)
CSVScriptPubKey(scriptNum5, p2pkh).scriptPubKeyAfterCSV must be(p2pkh)
CSVScriptPubKey(negativeOne, p2pkh).scriptPubKeyAfterCSV must be(p2pkh)
CSVScriptPubKey(scriptNum17, p2pkh).nestedScriptPubKey must be(p2pkh)
CSVScriptPubKey(scriptNum5, p2pkh).nestedScriptPubKey must be(p2pkh)
CSVScriptPubKey(negativeOne, p2pkh).nestedScriptPubKey must be(p2pkh)
CSVScriptPubKey(scriptNum17, p2pkh).locktime must be(scriptNum17)
CSVScriptPubKey(scriptNum5, p2pkh).locktime must be(scriptNum5)