diff --git a/core-test/src/test/scala/org/bitcoins/core/protocol/transaction/TransactionTest.scala b/core-test/src/test/scala/org/bitcoins/core/protocol/transaction/TransactionTest.scala index 17bd95ae19..b3a8aff911 100644 --- a/core-test/src/test/scala/org/bitcoins/core/protocol/transaction/TransactionTest.scala +++ b/core-test/src/test/scala/org/bitcoins/core/protocol/transaction/TransactionTest.scala @@ -405,6 +405,13 @@ class TransactionTest extends BitcoinSUnitTest { assert(tx.hex == hex) } + it must "parse 1c1f50eb03c28c56ea0f2abdff483e836a8110f365cd678af1ae892a550f71eb" in { + val hex = + "0100000001c5b9f89aeebb94f6838d9e8b0c0876dd7b62249a14f7c3acd466a4a6682c2530010000006b483045022068d7ba61ae4670fe857ca4617413e2a8f666c7a30dbee9ad52a77406f62fd4bb0221009ed0034c8005b17b8e85e5b5d9cd35a79914665863c1ea85201ff0b42ec1f48b01210291b3da73ea3ce05d942315135d10532b58175568092116da909da0cb42006a54ffffffff0248cf9700000000001976a91452b5f62ff6a34dc0937baa262314649b22caebec88ace8030000000000001714e41346a0f116a7d04984c2780a396b18b0e47ea7b17500000000" + val tx = Transaction.fromHex(hex) + assert(tx.hex == hex) + } + private def findInput( tx: Transaction, outPoint: TransactionOutPoint): Option[(TransactionInput, Int)] = { diff --git a/core/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala b/core/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala index 0b9edf190f..c979c151da 100644 --- a/core/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala +++ b/core/src/main/scala/org/bitcoins/core/protocol/script/ScriptPubKey.scala @@ -418,7 +418,7 @@ sealed trait LockTimeScriptPubKey extends RawScriptPubKey { asm.head match { case scriptNumOp: ScriptNumberOperation => ScriptNumber(scriptNumOp.toLong) - case _: BytesToPushOntoStack => ScriptNumber(asm(1).hex) + case _: BytesToPushOntoStack => ScriptNumber(asm(1).bytes) case _: ScriptConstant | _: ScriptOperation => throw new IllegalArgumentException( "In a LockTimeScriptPubKey, " + @@ -496,26 +496,35 @@ object CLTVScriptPubKey extends ScriptFactory[CLTVScriptPubKey] { if ( P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens .contains(OP_CHECKLOCKTIMEVERIFY) - ) return false - asm.slice(0, 4) match { - case Seq(_: BytesToPushOntoStack, - _: ScriptConstant, - OP_CHECKLOCKTIMEVERIFY, - OP_DROP) => - validScriptAfterLockTime(tailTokens) - case _ => false + ) { + false + } else { + asm.slice(0, 4) match { + case Seq(_: BytesToPushOntoStack, + s: ScriptConstant, + OP_CHECKLOCKTIMEVERIFY, + OP_DROP) => + //can only have up to 5 byte numbers for CLTV + s.byteSize <= 5 && validScriptAfterLockTime(tailTokens) + case _ => false + } } + } else { val tailTokens = asm.slice(3, asm.length) if ( P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens .contains(OP_CHECKLOCKTIMEVERIFY) - ) return false - asm.slice(0, 3) match { - case Seq(_: ScriptNumberOperation, OP_CHECKLOCKTIMEVERIFY, OP_DROP) => - validScriptAfterLockTime(tailTokens) - case _ => false + ) { + false + } else { + asm.slice(0, 3) match { + case Seq(_: ScriptNumberOperation, OP_CHECKLOCKTIMEVERIFY, OP_DROP) => + validScriptAfterLockTime(tailTokens) + case _ => false + } } + } } @@ -587,25 +596,35 @@ object CSVScriptPubKey extends ScriptFactory[CSVScriptPubKey] { if ( P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens .contains(OP_CHECKSEQUENCEVERIFY) - ) return false - asm.slice(0, 4) match { - case Seq(_: BytesToPushOntoStack, - _: ScriptConstant, - OP_CHECKSEQUENCEVERIFY, - OP_DROP) => - CLTVScriptPubKey.validScriptAfterLockTime(tailTokens) - case _ => false + ) { + false + } else { + asm.slice(0, 4) match { + case Seq(_: BytesToPushOntoStack, + s: ScriptConstant, + OP_CHECKSEQUENCEVERIFY, + 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 { val tailTokens = asm.slice(3, asm.length) if ( P2SHScriptPubKey.isValidAsm(tailTokens) || tailTokens .contains(OP_CHECKSEQUENCEVERIFY) - ) return false - asm.slice(0, 3) match { - case Seq(_: ScriptNumberOperation, OP_CHECKSEQUENCEVERIFY, OP_DROP) => - CLTVScriptPubKey.validScriptAfterLockTime(tailTokens) - case _ => false + ) { + false + } else { + asm.slice(0, 3) match { + case Seq(_: ScriptNumberOperation, OP_CHECKSEQUENCEVERIFY, OP_DROP) => + CLTVScriptPubKey.validScriptAfterLockTime(tailTokens) + case _ => false + } } } }