mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-19 05:43:51 +01:00
2024 01 20 Fix bug in parsing OP_CLTV
and OP_CSV
(#5363)
* Get test case setup for tx 1c1f50e * Fix bug in OP_CHECKLOCKTIMEVERIFY.isValidAsm(), check that the ScriptNumber is lessthan or equal to 5 bytes in size * Fix bug in OP_CHECKSEQUENCEVERIFY.isValidAsm(), check that the ScriptNumber is lessthan or equal to 5 bytes in size * Fix bug to check <= rather than < * Revert Constants.scala, ScriptNumberUtil.scala, remove superflous 'return'
This commit is contained in:
parent
618e1ca2d2
commit
73785706d8
@ -405,6 +405,13 @@ class TransactionTest extends BitcoinSUnitTest {
|
|||||||
assert(tx.hex == hex)
|
assert(tx.hex == hex)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it must "parse 1c1f50eb03c28c56ea0f2abdff483e836a8110f365cd678af1ae892a550f71eb" in {
|
||||||
|
val hex =
|
||||||
|
"0100000001c5b9f89aeebb94f6838d9e8b0c0876dd7b62249a14f7c3acd466a4a6682c2530010000006b483045022068d7ba61ae4670fe857ca4617413e2a8f666c7a30dbee9ad52a77406f62fd4bb0221009ed0034c8005b17b8e85e5b5d9cd35a79914665863c1ea85201ff0b42ec1f48b01210291b3da73ea3ce05d942315135d10532b58175568092116da909da0cb42006a54ffffffff0248cf9700000000001976a91452b5f62ff6a34dc0937baa262314649b22caebec88ace8030000000000001714e41346a0f116a7d04984c2780a396b18b0e47ea7b17500000000"
|
||||||
|
val tx = Transaction.fromHex(hex)
|
||||||
|
assert(tx.hex == hex)
|
||||||
|
}
|
||||||
|
|
||||||
private def findInput(
|
private def findInput(
|
||||||
tx: Transaction,
|
tx: Transaction,
|
||||||
outPoint: TransactionOutPoint): Option[(TransactionInput, Int)] = {
|
outPoint: TransactionOutPoint): Option[(TransactionInput, Int)] = {
|
||||||
|
@ -418,7 +418,7 @@ sealed trait LockTimeScriptPubKey extends RawScriptPubKey {
|
|||||||
asm.head match {
|
asm.head match {
|
||||||
case scriptNumOp: ScriptNumberOperation =>
|
case scriptNumOp: ScriptNumberOperation =>
|
||||||
ScriptNumber(scriptNumOp.toLong)
|
ScriptNumber(scriptNumOp.toLong)
|
||||||
case _: BytesToPushOntoStack => ScriptNumber(asm(1).hex)
|
case _: BytesToPushOntoStack => ScriptNumber(asm(1).bytes)
|
||||||
case _: ScriptConstant | _: ScriptOperation =>
|
case _: ScriptConstant | _: ScriptOperation =>
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"In a LockTimeScriptPubKey, " +
|
"In a LockTimeScriptPubKey, " +
|
||||||
@ -496,26 +496,35 @@ object CLTVScriptPubKey extends ScriptFactory[CLTVScriptPubKey] {
|
|||||||
if (
|
if (
|
||||||
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
||||||
.contains(OP_CHECKLOCKTIMEVERIFY)
|
.contains(OP_CHECKLOCKTIMEVERIFY)
|
||||||
) return false
|
) {
|
||||||
asm.slice(0, 4) match {
|
false
|
||||||
case Seq(_: BytesToPushOntoStack,
|
} else {
|
||||||
_: ScriptConstant,
|
asm.slice(0, 4) match {
|
||||||
OP_CHECKLOCKTIMEVERIFY,
|
case Seq(_: BytesToPushOntoStack,
|
||||||
OP_DROP) =>
|
s: ScriptConstant,
|
||||||
validScriptAfterLockTime(tailTokens)
|
OP_CHECKLOCKTIMEVERIFY,
|
||||||
case _ => false
|
OP_DROP) =>
|
||||||
|
//can only have up to 5 byte numbers for CLTV
|
||||||
|
s.byteSize <= 5 && validScriptAfterLockTime(tailTokens)
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val tailTokens = asm.slice(3, asm.length)
|
val tailTokens = asm.slice(3, asm.length)
|
||||||
if (
|
if (
|
||||||
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
||||||
.contains(OP_CHECKLOCKTIMEVERIFY)
|
.contains(OP_CHECKLOCKTIMEVERIFY)
|
||||||
) return false
|
) {
|
||||||
asm.slice(0, 3) match {
|
false
|
||||||
case Seq(_: ScriptNumberOperation, OP_CHECKLOCKTIMEVERIFY, OP_DROP) =>
|
} else {
|
||||||
validScriptAfterLockTime(tailTokens)
|
asm.slice(0, 3) match {
|
||||||
case _ => false
|
case Seq(_: ScriptNumberOperation, OP_CHECKLOCKTIMEVERIFY, OP_DROP) =>
|
||||||
|
validScriptAfterLockTime(tailTokens)
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -587,25 +596,35 @@ object CSVScriptPubKey extends ScriptFactory[CSVScriptPubKey] {
|
|||||||
if (
|
if (
|
||||||
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
||||||
.contains(OP_CHECKSEQUENCEVERIFY)
|
.contains(OP_CHECKSEQUENCEVERIFY)
|
||||||
) return false
|
) {
|
||||||
asm.slice(0, 4) match {
|
false
|
||||||
case Seq(_: BytesToPushOntoStack,
|
} else {
|
||||||
_: ScriptConstant,
|
asm.slice(0, 4) match {
|
||||||
OP_CHECKSEQUENCEVERIFY,
|
case Seq(_: BytesToPushOntoStack,
|
||||||
OP_DROP) =>
|
s: ScriptConstant,
|
||||||
CLTVScriptPubKey.validScriptAfterLockTime(tailTokens)
|
OP_CHECKSEQUENCEVERIFY,
|
||||||
case _ => false
|
OP_DROP) =>
|
||||||
|
//check that the byteSize of the ScriptNum is less than or equal to 5
|
||||||
|
//as per BIP112
|
||||||
|
s.byteSize <= 5 &&
|
||||||
|
CLTVScriptPubKey.validScriptAfterLockTime(tailTokens)
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
val tailTokens = asm.slice(3, asm.length)
|
val tailTokens = asm.slice(3, asm.length)
|
||||||
if (
|
if (
|
||||||
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens
|
||||||
.contains(OP_CHECKSEQUENCEVERIFY)
|
.contains(OP_CHECKSEQUENCEVERIFY)
|
||||||
) return false
|
) {
|
||||||
asm.slice(0, 3) match {
|
false
|
||||||
case Seq(_: ScriptNumberOperation, OP_CHECKSEQUENCEVERIFY, OP_DROP) =>
|
} else {
|
||||||
CLTVScriptPubKey.validScriptAfterLockTime(tailTokens)
|
asm.slice(0, 3) match {
|
||||||
case _ => false
|
case Seq(_: ScriptNumberOperation, OP_CHECKSEQUENCEVERIFY, OP_DROP) =>
|
||||||
|
CLTVScriptPubKey.validScriptAfterLockTime(tailTokens)
|
||||||
|
case _ => false
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user