mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 15:02:17 +01:00
Creating LockTimeScriptPubKey type to generecize different locktime types, refactoring EscrowTimeout to accept LockTimeScriptPubKeys instead of only CSVScriptPubKeys
This commit is contained in:
parent
365c0a698b
commit
13c8960a04
7 changed files with 99 additions and 98 deletions
|
@ -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))
|
||||
}
|
||||
}
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Add table
Reference in a new issue