mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-24 06:57:51 +01:00
revise locktime values for CLTV/CSVScriptPubKeys, refactor minimalScriptNumberRepresentation to return a ScriptNumber
This commit is contained in:
parent
18745d58e0
commit
563d901ac6
5 changed files with 32 additions and 38 deletions
|
@ -336,6 +336,7 @@ object P2PKScriptPubKey extends Factory[P2PKScriptPubKey] {
|
|||
sealed trait CLTVScriptPubKey extends ScriptPubKey {
|
||||
/**
|
||||
* Determines the nested ScriptPubKey inside the CLTVScriptPubKey
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def scriptPubKeyAfterCLTV : ScriptPubKey = {
|
||||
|
@ -348,17 +349,15 @@ sealed trait CLTVScriptPubKey extends ScriptPubKey {
|
|||
|
||||
/**
|
||||
* The absolute CLTV-LockTime value (i.e. the output will remain unspendable until this timestamp or block height)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def locktime : ScriptNumber = {
|
||||
val bool = asm.head.isInstanceOf[ScriptNumberOperation]
|
||||
bool match {
|
||||
case true =>
|
||||
val op = ScriptNumberOperation(asm.head.hex)
|
||||
ScriptNumber(op.get.underlying)
|
||||
case false =>
|
||||
val hex = BitcoinSUtil.flipEndianess(asm(1).hex)
|
||||
ScriptNumber(hex)
|
||||
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, " +
|
||||
"the first asm must be either a ScriptNumberOperation (i.e. OP_5), or the BytesToPushOntoStack for the proceeding ScriptConstant.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -381,8 +380,8 @@ object CLTVScriptPubKey extends Factory[CLTVScriptPubKey] {
|
|||
def apply(locktime : ScriptNumber, scriptPubKey : ScriptPubKey) : CLTVScriptPubKey = {
|
||||
val scriptOp = BitcoinScriptUtil.minimalScriptNumberRepresentation(locktime)
|
||||
|
||||
val scriptNum : Seq[ScriptToken] = if (scriptOp.isDefined) {
|
||||
Seq(scriptOp.get)
|
||||
val scriptNum : Seq[ScriptToken] = if (scriptOp.isInstanceOf[ScriptNumberOperation]) {
|
||||
Seq(scriptOp)
|
||||
} else {
|
||||
val pushOpsLockTime= BitcoinScriptUtil.calculatePushOp(locktime.bytes)
|
||||
pushOpsLockTime ++ Seq(ScriptConstant(locktime.bytes))
|
||||
|
@ -422,6 +421,7 @@ object CLTVScriptPubKey extends Factory[CLTVScriptPubKey] {
|
|||
sealed trait CSVScriptPubKey extends ScriptPubKey {
|
||||
/**
|
||||
* Determines the nested ScriptPubKey inside the CSVScriptPubKey
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def scriptPubKeyAfterCSV : ScriptPubKey = {
|
||||
|
@ -434,17 +434,15 @@ sealed trait CSVScriptPubKey extends ScriptPubKey {
|
|||
|
||||
/**
|
||||
* The relative CSV-LockTime value (i.e. the amount of time the output should remain unspendable)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
def locktime : ScriptNumber = {
|
||||
val bool = asm.head.isInstanceOf[ScriptNumberOperation]
|
||||
bool match {
|
||||
case true =>
|
||||
val op = ScriptNumberOperation(asm.head.hex)
|
||||
ScriptNumber(op.get.underlying)
|
||||
case false =>
|
||||
val hex = BitcoinSUtil.flipEndianess(asm(1).hex)
|
||||
ScriptNumber(hex)
|
||||
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.")
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -469,8 +467,8 @@ object CSVScriptPubKey extends Factory[CSVScriptPubKey] {
|
|||
def apply(relativeLockTime : ScriptNumber, scriptPubKey : ScriptPubKey) : CSVScriptPubKey = {
|
||||
val scriptOp = BitcoinScriptUtil.minimalScriptNumberRepresentation(relativeLockTime)
|
||||
|
||||
val scriptNum : Seq[ScriptToken] = if (scriptOp.isDefined) {
|
||||
Seq(scriptOp.get)
|
||||
val scriptNum : Seq[ScriptToken] = if (scriptOp.isInstanceOf[ScriptNumberOperation]) {
|
||||
Seq(scriptOp)
|
||||
} else {
|
||||
val pushOpsLockTime= BitcoinScriptUtil.calculatePushOp(relativeLockTime.bytes)
|
||||
pushOpsLockTime ++ Seq(ScriptConstant(relativeLockTime.bytes))
|
||||
|
|
|
@ -521,8 +521,7 @@ object ScriptSignature extends Factory[ScriptSignature] with BitcoinSLogger {
|
|||
case s : NonStandardScriptPubKey => NonStandardScriptSignature.fromAsm(tokens)
|
||||
case s : CLTVScriptPubKey => fromScriptPubKey(tokens, s.scriptPubKeyAfterCLTV)
|
||||
case s : CSVScriptPubKey => fromScriptPubKey(tokens, s.scriptPubKeyAfterCSV)
|
||||
case EmptyScriptPubKey if (tokens.size == 0) => EmptyScriptSignature
|
||||
case EmptyScriptPubKey => NonStandardScriptSignature.fromAsm(tokens)
|
||||
case EmptyScriptPubKey => if (tokens.isEmpty) EmptyScriptSignature else NonStandardScriptSignature.fromAsm(tokens)
|
||||
}
|
||||
|
||||
def apply(tokens : Seq[ScriptToken], scriptPubKey : ScriptPubKey) : ScriptSignature = fromScriptPubKey(tokens, scriptPubKey)
|
||||
|
|
|
@ -309,10 +309,9 @@ trait BitcoinScriptUtil {
|
|||
return true
|
||||
}
|
||||
|
||||
def minimalScriptNumberRepresentation(num : ScriptNumber) : Option[ScriptOperation] = {
|
||||
val str = num.underlying.toInt.toString
|
||||
val op = Try(ScriptOperation.fromString(str))
|
||||
op.get
|
||||
def minimalScriptNumberRepresentation(num : ScriptNumber) : ScriptNumber = {
|
||||
val op = ScriptNumberOperation.fromNumber(num.toInt)
|
||||
if (op.isDefined) op.get else num
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -38,13 +38,11 @@ class ScriptPubKeyTest extends FlatSpec with MustMatchers {
|
|||
val pubKey = ECPrivateKey().publicKey
|
||||
val p2pkh = P2PKHScriptPubKey(pubKey)
|
||||
|
||||
it must "determine the correct underlying scriptPubKey inside a CLTVScriptPubKey" in {
|
||||
it must "determine the correct underlying scriptPubKey, and locktime inside a CLTVScriptPubKey" in {
|
||||
CLTVScriptPubKey(scriptNum17, p2pkh).scriptPubKeyAfterCLTV must be (p2pkh)
|
||||
CLTVScriptPubKey(scriptNum5, p2pkh).scriptPubKeyAfterCLTV must be (p2pkh)
|
||||
CLTVScriptPubKey(negativeOne, p2pkh).scriptPubKeyAfterCLTV must be (p2pkh)
|
||||
}
|
||||
|
||||
it must "determine the correct locktime for the CLTVScriptPubKey" in {
|
||||
CLTVScriptPubKey(scriptNum17, p2pkh).locktime must be (scriptNum17)
|
||||
CLTVScriptPubKey(scriptNum5, p2pkh).locktime must be (scriptNum5)
|
||||
}
|
||||
|
@ -56,14 +54,13 @@ class ScriptPubKeyTest extends FlatSpec with MustMatchers {
|
|||
csv.asm must be (expectedCSVAsm)
|
||||
}
|
||||
|
||||
it must "determine the correct underlying scriptPubKey inside a CLTVScriptPubKey" in {
|
||||
it must "determine the correct underlying scriptPubKey, and locktime inside a CSVScriptPubKey" in {
|
||||
CSVScriptPubKey(scriptNum17, p2pkh).scriptPubKeyAfterCSV must be (p2pkh)
|
||||
CSVScriptPubKey(scriptNum5, p2pkh).scriptPubKeyAfterCSV must be (p2pkh)
|
||||
CSVScriptPubKey(negativeOne, p2pkh).scriptPubKeyAfterCSV must be (p2pkh)
|
||||
}
|
||||
|
||||
it must "determine the correct locktime for the CLTVScriptPubKey" in {
|
||||
CSVScriptPubKey(scriptNum17, p2pkh).locktime must be (scriptNum17)
|
||||
CSVScriptPubKey(scriptNum5, p2pkh).locktime must be (scriptNum5)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -190,11 +190,12 @@ class BitcoinScriptUtilTest extends FlatSpec with MustMatchers {
|
|||
val scriptNumZero = ScriptNumber(0)
|
||||
val scriptNum16 = ScriptNumber(16)
|
||||
val scriptNum17 = ScriptNumber(17)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNum100) must be (None)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNum10) must be (Some(OP_10))
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNumZero) must be (Some(OP_0))
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNum16) must be (Some(OP_16))
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNum17) must be (None)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(ScriptNumber(-1)) must be (None)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNum100) must be (scriptNum100)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNum10) must be (OP_10)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNumZero) must be (OP_0)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNum16) must be (OP_16)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(scriptNum17) must be (scriptNum17)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(ScriptNumber(-1)) must be (OP_1NEGATE)
|
||||
BitcoinScriptUtil.minimalScriptNumberRepresentation(ScriptNumber(-2)) must be (ScriptNumber(-2))
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue