mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 23:08:31 +01:00
properly generate both spendable and unspendable csv transactions, add factory to CSV/CLTVScriptSignatures
This commit is contained in:
parent
10d4041efb
commit
bb806716cb
7 changed files with 119 additions and 131 deletions
|
@ -376,9 +376,13 @@ object CLTVScriptPubKey extends Factory[CLTVScriptPubKey] {
|
||||||
CLTVScriptPubKey(asm)
|
CLTVScriptPubKey(asm)
|
||||||
}
|
}
|
||||||
|
|
||||||
def isCLTVScriptPubKey(asm : Seq[ScriptToken]) : Boolean = asm.slice(0,4) match {
|
def isCLTVScriptPubKey(asm : Seq[ScriptToken]) : Boolean = {
|
||||||
case List(lockTimeBytesToPush : BytesToPushOntoStack, lockTime : ScriptConstant, OP_CHECKLOCKTIMEVERIFY, OP_DROP) => true
|
val tailTokens = asm.slice(4, asm.length)
|
||||||
case _ => false
|
if (P2SHScriptPubKey.isP2SHScriptPubKey(tailTokens) || tailTokens.contains(OP_CHECKLOCKTIMEVERIFY)) return false
|
||||||
|
asm.slice(0,4) match {
|
||||||
|
case List(lockTimeBytesToPush : BytesToPushOntoStack, lockTime : ScriptConstant, OP_CHECKLOCKTIMEVERIFY, OP_DROP) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -429,10 +433,15 @@ object CSVScriptPubKey extends Factory[CSVScriptPubKey] {
|
||||||
CSVScriptPubKey(asm)
|
CSVScriptPubKey(asm)
|
||||||
}
|
}
|
||||||
|
|
||||||
def isCSVScriptPubKey(asm : Seq[ScriptToken]) : Boolean = asm.slice(0,4) match {
|
def isCSVScriptPubKey(asm : Seq[ScriptToken]) : Boolean = {
|
||||||
case List(lockTimeBytesToPush : BytesToPushOntoStack, lockTime : ScriptConstant, OP_CHECKSEQUENCEVERIFY, OP_DROP) => true
|
val tailTokens = asm.slice(4, asm.length)
|
||||||
case _ => false
|
if (P2SHScriptPubKey.isP2SHScriptPubKey(tailTokens) || tailTokens.contains(OP_CHECKSEQUENCEVERIFY)) return false
|
||||||
|
asm.slice(0,4) match {
|
||||||
|
case List(lockTimeBytesToPush : BytesToPushOntoStack, lockTime : ScriptConstant, OP_CHECKSEQUENCEVERIFY, OP_DROP) => true
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait NonStandardScriptPubKey extends ScriptPubKey
|
sealed trait NonStandardScriptPubKey extends ScriptPubKey
|
||||||
|
|
|
@ -416,52 +416,56 @@ object CLTVScriptSignature extends Factory[CLTVScriptSignature] {
|
||||||
* of [[ECPublicKey]] needed to satisfy the scriptPubKey. If a [[P2SHScriptPubKey]] is provided, a redeemScript must also be provided.
|
* of [[ECPublicKey]] needed to satisfy the scriptPubKey. If a [[P2SHScriptPubKey]] is provided, a redeemScript must also be provided.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def apply(scriptPubKey: ScriptPubKey, sigs : Seq[ECDigitalSignature], pubKeys : Seq[ECPublicKey], redeemScript : Option[ScriptPubKey]) : CLTVScriptSignature = scriptPubKey match {
|
def apply(scriptPubKey: ScriptPubKey, sigs : Seq[ECDigitalSignature], pubKeys : Seq[ECPublicKey]) : CLTVScriptSignature = scriptPubKey match {
|
||||||
case p2pkScriptPubKey : P2PKScriptPubKey => CLTVScriptSignature(P2PKScriptSignature(sigs.head))
|
case p2pkScriptPubKey : P2PKScriptPubKey => CLTVScriptSignature(P2PKScriptSignature(sigs.head))
|
||||||
case p2pkhScriptPubKey : P2PKHScriptPubKey => CLTVScriptSignature(P2PKHScriptSignature(sigs.head, pubKeys.head))
|
case p2pkhScriptPubKey : P2PKHScriptPubKey => CLTVScriptSignature(P2PKHScriptSignature(sigs.head, pubKeys.head))
|
||||||
case multiSigScriptPubKey : MultiSignatureScriptPubKey => CLTVScriptSignature(MultiSignatureScriptSignature(sigs))
|
case multiSigScriptPubKey : MultiSignatureScriptPubKey => CLTVScriptSignature(MultiSignatureScriptSignature(sigs))
|
||||||
case cltvScriptPubKey : CLTVScriptPubKey => apply(cltvScriptPubKey.scriptPubKeyAfterCLTV, sigs, pubKeys, redeemScript)
|
case cltvScriptPubKey : CLTVScriptPubKey => apply(cltvScriptPubKey.scriptPubKeyAfterCLTV, sigs, pubKeys)
|
||||||
case csvScriptPubKey : CSVScriptPubKey => apply(csvScriptPubKey.scriptPubKeyAfterCSV, sigs, pubKeys, redeemScript)
|
case csvScriptPubKey : CSVScriptPubKey => apply(csvScriptPubKey.scriptPubKeyAfterCSV, sigs, pubKeys)
|
||||||
case p2shScriptPubKey : P2SHScriptPubKey =>
|
|
||||||
require(redeemScript.isDefined, "If the underlying scriptSig is a P2SHScriptSignature, a redeemScript must be defined.")
|
|
||||||
val cltvScriptSigBeforeRedeemScript = apply(redeemScript.get, sigs, pubKeys, None)
|
|
||||||
CLTVScriptSignature(P2SHScriptSignature(cltvScriptSigBeforeRedeemScript, redeemScript.get))
|
|
||||||
case EmptyScriptPubKey => CLTVScriptSignature(EmptyScriptSignature)
|
case EmptyScriptPubKey => CLTVScriptSignature(EmptyScriptSignature)
|
||||||
case nonstandard : NonStandardScriptPubKey => throw new IllegalArgumentException("A NonStandardScriptSignature cannot be" +
|
case _ : NonStandardScriptPubKey | _ : P2SHScriptPubKey => throw new IllegalArgumentException("A NonStandardScriptSignature or P2SHScriptSignature cannot be" +
|
||||||
"the underlying scriptSig in a CLTVScriptSignature.")
|
"the underlying scriptSig in a CLTVScriptSignature. Got: " + this)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed trait CSVScriptSignature extends ScriptSignature {
|
sealed trait CSVScriptSignature extends ScriptSignature {
|
||||||
def scriptSig : ScriptSignature
|
def scriptSig : ScriptSignature = ScriptSignature(hex)
|
||||||
|
|
||||||
override def signatures : Seq[ECDigitalSignature] = scriptSig.signatures
|
override def signatures : Seq[ECDigitalSignature] = scriptSig.signatures
|
||||||
|
|
||||||
override def hex = scriptSig.hex
|
override def hex = scriptSig.hex
|
||||||
}
|
}
|
||||||
|
|
||||||
object CSVScriptSignature {
|
object CSVScriptSignature extends Factory[CSVScriptSignature] {
|
||||||
private case class CSVScriptSignatureImpl(scriptSig : ScriptSignature) extends CSVScriptSignature
|
private case class CSVScriptSignatureImpl(override val hex : String) extends CSVScriptSignature
|
||||||
|
|
||||||
|
override def fromBytes(bytes : Seq[Byte]) : CSVScriptSignature = {
|
||||||
|
val hex = BitcoinSUtil.encodeHex(bytes)
|
||||||
|
fromHex(hex)
|
||||||
|
}
|
||||||
|
|
||||||
|
override def fromHex(hex : String) : CSVScriptSignature = {
|
||||||
|
CSVScriptSignatureImpl(hex)
|
||||||
|
}
|
||||||
|
|
||||||
|
def apply(scriptSig : ScriptSignature) : CSVScriptSignature = {
|
||||||
|
fromHex(scriptSig.hex)
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Creates a CSVScriptSignature out the [[ScriptPubKey]] we are satisfying, a sequence of [[ECDigitalSignature]], and a sequence
|
* Creates a CSVScriptSignature out the [[ScriptPubKey]] we are satisfying, a sequence of [[ECDigitalSignature]], and a sequence
|
||||||
* of [[ECPublicKey]] needed to satisfy the scriptPubKey. If a [[P2SHScriptPubKey]] is provided, a redeemScript must also be provided.
|
* of [[ECPublicKey]] needed to satisfy the scriptPubKey. If a [[P2SHScriptPubKey]] is provided, a redeemScript must also be provided.
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
def apply(scriptPubKey: ScriptPubKey, sigs : Seq[ECDigitalSignature], pubKeys : Seq[ECPublicKey], redeemScript : Option[ScriptPubKey]) : CSVScriptSignature = scriptPubKey match {
|
def apply(scriptPubKey: ScriptPubKey, sigs : Seq[ECDigitalSignature], pubKeys : Seq[ECPublicKey]) : CSVScriptSignature = scriptPubKey match {
|
||||||
case p2pkScriptPubKey : P2PKScriptPubKey => CSVScriptSignatureImpl(P2PKScriptSignature(sigs.head))
|
case p2pkScriptPubKey : P2PKScriptPubKey => CSVScriptSignature(P2PKScriptSignature(sigs.head))
|
||||||
case p2pkhScriptPubKey : P2PKHScriptPubKey => CSVScriptSignatureImpl(P2PKHScriptSignature(sigs.head, pubKeys.head))
|
case p2pkhScriptPubKey : P2PKHScriptPubKey => CSVScriptSignature(P2PKHScriptSignature(sigs.head, pubKeys.head))
|
||||||
case multiSigScriptPubKey : MultiSignatureScriptPubKey => CSVScriptSignatureImpl(MultiSignatureScriptSignature(sigs))
|
case multiSigScriptPubKey : MultiSignatureScriptPubKey => CSVScriptSignature(MultiSignatureScriptSignature(sigs))
|
||||||
case cltvScriptPubKey : CLTVScriptPubKey => apply(cltvScriptPubKey.scriptPubKeyAfterCLTV, sigs, pubKeys, redeemScript)
|
case cltvScriptPubKey : CLTVScriptPubKey => apply(cltvScriptPubKey.scriptPubKeyAfterCLTV, sigs, pubKeys)
|
||||||
case csvScriptPubKey : CSVScriptPubKey => apply(csvScriptPubKey.scriptPubKeyAfterCSV, sigs, pubKeys, redeemScript)
|
case csvScriptPubKey : CSVScriptPubKey => apply(csvScriptPubKey.scriptPubKeyAfterCSV, sigs, pubKeys)
|
||||||
case p2shScriptPubKey : P2SHScriptPubKey =>
|
case EmptyScriptPubKey => CSVScriptSignature(EmptyScriptSignature)
|
||||||
require(redeemScript.isDefined, "If the underlying scriptSig is a P2SHScriptSignature, a redeemScript must be defined.")
|
case _ : NonStandardScriptPubKey | _ : P2SHScriptPubKey => throw new IllegalArgumentException("A NonStandardScriptSignature or P2SHScriptSignature cannot be" +
|
||||||
val csvScriptSigBeforeRedeemScript = apply(redeemScript.get, sigs, pubKeys, None)
|
"the underlying scriptSig in a CSVScriptSignature. Got: " + this)
|
||||||
CSVScriptSignatureImpl(P2SHScriptSignature(csvScriptSigBeforeRedeemScript, redeemScript.get))
|
|
||||||
case EmptyScriptPubKey => CSVScriptSignatureImpl(EmptyScriptSignature)
|
|
||||||
case nonstandard : NonStandardScriptPubKey => throw new IllegalArgumentException("A NonStandardScriptSignature cannot be" +
|
|
||||||
"the underlying scriptSig in a CSVScriptSignature.")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,7 +31,6 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
||||||
*/
|
*/
|
||||||
@tailrec
|
@tailrec
|
||||||
final def opCheckLockTimeVerify(program : ScriptProgram) : ScriptProgram = {
|
final def opCheckLockTimeVerify(program : ScriptProgram) : ScriptProgram = {
|
||||||
logger.warn("+_+_+_+_!+_+_!!!!+_+_+_+_!+_+_!!!!+_+_+_+_!+_+_!!!!+_+_+_+_!+_+_!!!!+_+_+_+_!+_+_!!!!+_+_+_+_!+_+_!!!!+_+_+_+_!+_+_!!!!+_+_+_+_!+_+_!!!!")
|
|
||||||
require(program.script.headOption.isDefined && program.script.head == OP_CHECKLOCKTIMEVERIFY,
|
require(program.script.headOption.isDefined && program.script.head == OP_CHECKLOCKTIMEVERIFY,
|
||||||
"Script top must be OP_CHECKLOCKTIMEVERIFY")
|
"Script top must be OP_CHECKLOCKTIMEVERIFY")
|
||||||
val input = program.txSignatureComponent.transaction.inputs(program.txSignatureComponent.inputIndex.toInt)
|
val input = program.txSignatureComponent.transaction.inputs(program.txSignatureComponent.inputIndex.toInt)
|
||||||
|
@ -176,7 +175,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
||||||
(txToSequenceMasked >= Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying) &&
|
(txToSequenceMasked >= Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying) &&
|
||||||
nSequenceMasked >= Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying))
|
nSequenceMasked >= Int64(TransactionConstants.sequenceLockTimeTypeFlag.underlying))
|
||||||
)) {
|
)) {
|
||||||
logger.error("The nSequence mask is not the same as it was in the transaction")
|
logger.error("The txSequence and nSequence (OP_CSV value) are not of the same type (timestamp/block-height).")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,7 +215,6 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
||||||
|
|
||||||
// Now that we know we're comparing apples-to-apples, the
|
// Now that we know we're comparing apples-to-apples, the
|
||||||
// comparison is a simple numeric one.
|
// comparison is a simple numeric one.
|
||||||
println("cltvLocktime: " + locktime + " and txLocktime: " + transaction.lockTime)
|
|
||||||
if (locktime > Int64(transaction.lockTime.underlying)) return false
|
if (locktime > Int64(transaction.lockTime.underlying)) return false
|
||||||
|
|
||||||
// Finally the nLockTime feature can be disabled and thus
|
// Finally the nLockTime feature can be disabled and thus
|
||||||
|
@ -231,10 +229,7 @@ trait LockTimeInterpreter extends BitcoinSLogger {
|
||||||
// required to prove correct CHECKLOCKTIMEVERIFY execution.
|
// required to prove correct CHECKLOCKTIMEVERIFY execution.
|
||||||
if (input.sequence == TransactionConstants.sequence) {
|
if (input.sequence == TransactionConstants.sequence) {
|
||||||
false
|
false
|
||||||
} else {
|
} else true
|
||||||
println("it passed")
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.bitcoins.core.crypto
|
package org.bitcoins.core.crypto
|
||||||
|
|
||||||
import org.bitcoins.core.gen.TransactionGenerators
|
import org.bitcoins.core.gen.TransactionGenerators
|
||||||
|
import org.bitcoins.core.number.Int64
|
||||||
import org.bitcoins.core.protocol.script.{CLTVScriptPubKey, P2SHScriptPubKey}
|
import org.bitcoins.core.protocol.script.{CLTVScriptPubKey, P2SHScriptPubKey}
|
||||||
import org.bitcoins.core.script.interpreter.ScriptInterpreter
|
import org.bitcoins.core.script.interpreter.ScriptInterpreter
|
||||||
import org.bitcoins.core.script.result.{ScriptErrorUnsatisfiedLocktime, ScriptErrorPushSize, ScriptOk}
|
import org.bitcoins.core.script.result.{ScriptErrorUnsatisfiedLocktime, ScriptErrorPushSize, ScriptOk}
|
||||||
|
@ -12,59 +13,58 @@ import org.scalacheck.{Prop, Properties}
|
||||||
* Created by chris on 7/25/16.
|
* Created by chris on 7/25/16.
|
||||||
*/
|
*/
|
||||||
class TransactionSignatureCreatorSpec extends Properties("TransactionSignatureCreatorSpec") with BitcoinSLogger {
|
class TransactionSignatureCreatorSpec extends Properties("TransactionSignatureCreatorSpec") with BitcoinSLogger {
|
||||||
// property("Must generate a valid signature for a p2pk transaction") =
|
property("Must generate a valid signature for a p2pk transaction") =
|
||||||
// Prop.forAll(TransactionGenerators.signedP2PKTransaction) {
|
Prop.forAll(TransactionGenerators.signedP2PKTransaction) {
|
||||||
// case (txSignatureComponent: TransactionSignatureComponent, _) =>
|
case (txSignatureComponent: TransactionSignatureComponent, _) =>
|
||||||
// //run it through the interpreter
|
//run it through the interpreter
|
||||||
// val program: PreExecutionScriptProgram = ScriptProgram(txSignatureComponent)
|
val program: PreExecutionScriptProgram = ScriptProgram(txSignatureComponent)
|
||||||
// val result = ScriptInterpreter.run(program)
|
val result = ScriptInterpreter.run(program)
|
||||||
// result == ScriptOk
|
result == ScriptOk
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// property("generate a valid signature for a p2pkh transaction") =
|
property("generate a valid signature for a p2pkh transaction") =
|
||||||
// Prop.forAll(TransactionGenerators.signedP2PKHTransaction) {
|
Prop.forAll(TransactionGenerators.signedP2PKHTransaction) {
|
||||||
// case (txSignatureComponent: TransactionSignatureComponent, _) =>
|
case (txSignatureComponent: TransactionSignatureComponent, _) =>
|
||||||
// //run it through the interpreter
|
//run it through the interpreter
|
||||||
// val program = ScriptProgram(txSignatureComponent)
|
val program = ScriptProgram(txSignatureComponent)
|
||||||
// val result = ScriptInterpreter.run(program)
|
val result = ScriptInterpreter.run(program)
|
||||||
// result == ScriptOk
|
result == ScriptOk
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// property("generate valid signatures for a multisignature transaction") =
|
property("generate valid signatures for a multisignature transaction") =
|
||||||
// Prop.forAllNoShrink(TransactionGenerators.signedMultiSigTransaction) {
|
Prop.forAllNoShrink(TransactionGenerators.signedMultiSigTransaction) {
|
||||||
// case (txSignatureComponent: TransactionSignatureComponent, _) =>
|
case (txSignatureComponent: TransactionSignatureComponent, _) =>
|
||||||
// //run it through the interpreter
|
//run it through the interpreter
|
||||||
// val program = ScriptProgram(txSignatureComponent)
|
val program = ScriptProgram(txSignatureComponent)
|
||||||
//
|
|
||||||
// val result = ScriptInterpreter.run(program)
|
val result = ScriptInterpreter.run(program)
|
||||||
//
|
|
||||||
// result == ScriptOk
|
result == ScriptOk
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// property("generate a valid signature for a p2sh transaction") =
|
property("generate a valid signature for a p2sh transaction") =
|
||||||
// Prop.forAll(TransactionGenerators.signedP2SHTransaction) {
|
Prop.forAll(TransactionGenerators.signedP2SHTransaction) {
|
||||||
// case (txSignatureComponent: TransactionSignatureComponent, _) =>
|
case (txSignatureComponent: TransactionSignatureComponent, _) =>
|
||||||
// //run it through the interpreter
|
//run it through the interpreter
|
||||||
// val program = ScriptProgram(txSignatureComponent)
|
val program = ScriptProgram(txSignatureComponent)
|
||||||
// val result = ScriptInterpreter.run(program)
|
val result = ScriptInterpreter.run(program)
|
||||||
// //can be ScriptErrorPushSize if the redeemScript is larger than 520 bytes
|
//can be ScriptErrorPushSize if the redeemScript is larger than 520 bytes
|
||||||
// Seq(ScriptOk, ScriptErrorPushSize).contains(result)
|
Seq(ScriptOk, ScriptErrorPushSize).contains(result)
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// property("generate a valid signature for a valid and spendable cltv transaction") =
|
property("generate a valid signature for a valid and spendable cltv transaction") =
|
||||||
// Prop.forAllNoShrink(TransactionGenerators.spendableCLTVTransaction :| "cltv_spendable") {
|
Prop.forAllNoShrink(TransactionGenerators.spendableCLTVTransaction :| "cltv_spendable") {
|
||||||
// case (txSignatureComponent: TransactionSignatureComponent, _, scriptNumber) =>
|
case (txSignatureComponent: TransactionSignatureComponent, _, scriptNumber) =>
|
||||||
// //run it through the interpreter
|
//run it through the interpreter
|
||||||
// require(txSignatureComponent.transaction.lockTime.underlying >= scriptNumber.underlying, "TxLocktime must be satisifed so it should be greater than or equal to " +
|
require(txSignatureComponent.transaction.lockTime.underlying >= scriptNumber.underlying, "TxLocktime must be satisifed so it should be greater than or equal to " +
|
||||||
// "the cltv value. Got TxLockTime : " + txSignatureComponent.transaction.lockTime.underlying + " , and cltv Value: " +
|
"the cltv value. Got TxLockTime : " + txSignatureComponent.transaction.lockTime.underlying + " , and cltv Value: " +
|
||||||
// scriptNumber.underlying)
|
scriptNumber.underlying)
|
||||||
// val program = ScriptProgram(txSignatureComponent)
|
val program = ScriptProgram(txSignatureComponent)
|
||||||
// val result = ScriptInterpreter.run(program)
|
val result = ScriptInterpreter.run(program)
|
||||||
// val cltv = CLTVScriptPubKey(txSignatureComponent.scriptPubKey.hex)
|
val cltv = CLTVScriptPubKey(txSignatureComponent.scriptPubKey.hex)
|
||||||
// if (cltv.scriptPubKeyAfterCLTV.isInstanceOf[P2SHScriptPubKey]) Seq(ScriptOk, ScriptErrorPushSize).contains(result)
|
Seq(ScriptOk).contains(result)
|
||||||
// else Seq(ScriptOk).contains(result)
|
}
|
||||||
// }
|
|
||||||
//
|
|
||||||
property("generate a valid signature for a validly constructed, but NOT spendable cltv transaction") =
|
property("generate a valid signature for a validly constructed, but NOT spendable cltv transaction") =
|
||||||
Prop.forAllNoShrink(TransactionGenerators.unspendableCLTVTransaction :| "cltv_unspendable") {
|
Prop.forAllNoShrink(TransactionGenerators.unspendableCLTVTransaction :| "cltv_unspendable") {
|
||||||
case (txSignatureComponent: TransactionSignatureComponent, _, scriptNumber) =>
|
case (txSignatureComponent: TransactionSignatureComponent, _, scriptNumber) =>
|
||||||
|
@ -75,16 +75,25 @@ class TransactionSignatureCreatorSpec extends Properties("TransactionSignatureCr
|
||||||
val program = ScriptProgram(txSignatureComponent)
|
val program = ScriptProgram(txSignatureComponent)
|
||||||
val result = ScriptInterpreter.run(program)
|
val result = ScriptInterpreter.run(program)
|
||||||
val cltv = CLTVScriptPubKey(txSignatureComponent.scriptPubKey.hex)
|
val cltv = CLTVScriptPubKey(txSignatureComponent.scriptPubKey.hex)
|
||||||
println("result: " + result)
|
|
||||||
Seq(ScriptErrorUnsatisfiedLocktime, ScriptErrorPushSize).contains(result)
|
Seq(ScriptErrorUnsatisfiedLocktime, ScriptErrorPushSize).contains(result)
|
||||||
}
|
}
|
||||||
//
|
|
||||||
// property("generate a valid signature for a valid and spendable csv transaction") =
|
property("generate a valid signature for a valid and spendable csv transaction") =
|
||||||
// Prop.forAllNoShrink(TransactionGenerators.spendableCSVTransaction :| "csv") {
|
Prop.forAllNoShrink(TransactionGenerators.spendableCSVTransaction :| "spendable csv") {
|
||||||
// case (txSignatureComponent: TransactionSignatureComponent, keys, scriptNumber, sequence) =>
|
case (txSignatureComponent: TransactionSignatureComponent, keys, scriptNumber, sequence) =>
|
||||||
// //run it through the interpreter
|
//run it through the interpreter
|
||||||
// val program = ScriptProgram(txSignatureComponent)
|
val program = ScriptProgram(txSignatureComponent)
|
||||||
// val result = ScriptInterpreter.run(program)
|
val result = ScriptInterpreter.run(program)
|
||||||
// Seq(ScriptOk, ScriptErrorPushSize).contains(result)
|
Seq(ScriptOk, ScriptErrorPushSize).contains(result)
|
||||||
// }
|
}
|
||||||
|
|
||||||
|
property("generate a valid signature for a validly constructed but unspendable csv transaction") =
|
||||||
|
Prop.forAllNoShrink(TransactionGenerators.unspendableCSVTransaction :| "unspendable csv") {
|
||||||
|
case (txSignatureComponent: TransactionSignatureComponent, keys, scriptNumber, sequence) =>
|
||||||
|
//run it through the interpreter
|
||||||
|
val program = ScriptProgram(txSignatureComponent)
|
||||||
|
val result = ScriptInterpreter.run(program)
|
||||||
|
Seq(ScriptErrorUnsatisfiedLocktime, ScriptErrorPushSize).contains(result)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,17 +15,4 @@ class CLTVScriptPubKeySpec extends Properties("CLTVScriptPubKeySpec") with Bitco
|
||||||
Prop.forAll(ScriptGenerators.cltvScriptPubKey) { case (cltvScriptPubKey, _) =>
|
Prop.forAll(ScriptGenerators.cltvScriptPubKey) { case (cltvScriptPubKey, _) =>
|
||||||
CLTVScriptPubKey(cltvScriptPubKey.hex) == cltvScriptPubKey
|
CLTVScriptPubKey(cltvScriptPubKey.hex) == cltvScriptPubKey
|
||||||
}
|
}
|
||||||
property("a valid unspendable CLTV Transaction's locktime must be less than the script's CLTV value ") =
|
|
||||||
Prop.forAll(TransactionGenerators.unspendableCLTVTransaction) { txSigComponent =>
|
|
||||||
val locktime = txSigComponent._1.transaction.lockTime.underlying
|
|
||||||
val cltvScriptValue = txSigComponent._3.underlying
|
|
||||||
locktime < cltvScriptValue
|
|
||||||
}
|
|
||||||
|
|
||||||
property("a valid spendable CLTV Transaction's locktime must be greater than the script's CLTV value ") =
|
|
||||||
Prop.forAll(TransactionGenerators.spendableCLTVTransaction) { txSigComponent =>
|
|
||||||
val locktime = txSigComponent._1.transaction.lockTime.underlying
|
|
||||||
val cltvScriptValue = txSigComponent._3.underlying
|
|
||||||
locktime > cltvScriptValue
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -122,6 +122,6 @@ class ScriptSignatureTest extends FlatSpec with MustMatchers {
|
||||||
val cltvScriptPubKey = CLTVScriptPubKey("04e71bbe57b17576a914da88dc82530f0a4d1327dcfe75cc60c44277532c88ac")
|
val cltvScriptPubKey = CLTVScriptPubKey("04e71bbe57b17576a914da88dc82530f0a4d1327dcfe75cc60c44277532c88ac")
|
||||||
val pubKey = ECPublicKey("039ba48e162b1f47246f4ce9dc40f197fab7bde11da1b2fe9ac21113959e9f381b")
|
val pubKey = ECPublicKey("039ba48e162b1f47246f4ce9dc40f197fab7bde11da1b2fe9ac21113959e9f381b")
|
||||||
val sig = ECDigitalSignature("3045022100d71cfe32fa4545c5a0fd665b3701eb458a1bacbba868a05fa703fd1fa4b4f5c502204ee706334f976d0bee9b0f0ff919c1dfe9ba027993bf3e39fc03416ba4255b2401")
|
val sig = ECDigitalSignature("3045022100d71cfe32fa4545c5a0fd665b3701eb458a1bacbba868a05fa703fd1fa4b4f5c502204ee706334f976d0bee9b0f0ff919c1dfe9ba027993bf3e39fc03416ba4255b2401")
|
||||||
CLTVScriptSignature(cltvScriptPubKey, Seq(sig), Seq(pubKey), None).scriptSig.isInstanceOf[P2PKHScriptSignature]
|
CLTVScriptSignature(cltvScriptPubKey, Seq(sig), Seq(pubKey)).scriptSig.isInstanceOf[P2PKHScriptSignature]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,6 @@ import scala.io.Source
|
||||||
* Created by chris on 1/6/16.
|
* Created by chris on 1/6/16.
|
||||||
*/
|
*/
|
||||||
class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterpreter with BitcoinSLogger {
|
class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterpreter with BitcoinSLogger {
|
||||||
/*
|
|
||||||
|
|
||||||
"ScriptInterpreter" must "evaluate all the scripts from the bitcoin core script_tests.json" in {
|
"ScriptInterpreter" must "evaluate all the scripts from the bitcoin core script_tests.json" in {
|
||||||
|
|
||||||
|
@ -61,19 +60,4 @@ class ScriptInterpreterTest extends FlatSpec with MustMatchers with ScriptInterp
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*/
|
|
||||||
|
|
||||||
it must "fail CLTVScriptPubKey with nested P2SHScriptPubKey" in {
|
|
||||||
val privKey = ECPrivateKey("8fe79310a9a5400daf4f9690187db1607c668fca9f63a530d67cc7472c9de589")
|
|
||||||
val cltv = CLTVScriptPubKey("010ab175a914c280ffb6c00e2d8b333d84746dc38a807081590287")
|
|
||||||
val p2shScriptSig = P2SHScriptSignature("483045022100d817fbc5a5d71f0859b811c01e251a20ab897c2b07b96149340336183e80d1" +
|
|
||||||
"9e022065e20731db313b31c45b208919a8606f90d390620b65a71085d185618b6742bc0123210338a011f3d144d4af991b27d13bcac38ef312835e64a0971c7f5404e1252a332eac")
|
|
||||||
val cltvScriptSignature = CLTVScriptSignature(p2shScriptSig)
|
|
||||||
val redeemScript = p2shScriptSig.redeemScript
|
|
||||||
val (creditingTx, outputIndex) = TransactionGenerators.buildCreditingTransaction(cltv)
|
|
||||||
val (spendingTx, inputIndex) = TransactionGenerators.buildSpendingTransaction(UInt32.one, creditingTx, cltvScriptSignature, outputIndex, UInt32(5), UInt32.zero)
|
|
||||||
val txSigComp = TransactionSignatureComponent(spendingTx, inputIndex, redeemScript, Policy.standardScriptVerifyFlags)
|
|
||||||
ScriptInterpreter.run(ScriptProgram(txSigComp)) must be (ScriptErrorUnsatisfiedLocktime)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue