From 2ff549ea90d8a8cb2075b50afb05c3f9bbdea6b7 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Thu, 21 Nov 2024 05:04:39 +0530 Subject: [PATCH 1/6] fixes 1 failing test --- packages/engine/src/opcodes/locktime.cairo | 16 ++++++++-------- tests/run-core-tests.sh | 6 +++--- tests/run-failing-core-tests.sh | 6 +++--- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/packages/engine/src/opcodes/locktime.cairo b/packages/engine/src/opcodes/locktime.cairo index 4cd068c..7648641 100644 --- a/packages/engine/src/opcodes/locktime.cairo +++ b/packages/engine/src/opcodes/locktime.cairo @@ -118,14 +118,6 @@ pub fn opcode_checksequenceverify< return Result::Ok(()); } - // Prevent trigger OP_CHECKSEQUENCEVERIFY before tx version 2 - let version = EngineTransactionTrait::< - T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait - >::get_version(engine.transaction); - if version < 2 { - return Result::Err(Error::INVALID_TX_VERSION); - } - let transaction_input = EngineTransactionTrait::< T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait >::get_transaction_inputs(engine.transaction) @@ -137,6 +129,14 @@ pub fn opcode_checksequenceverify< return Result::Err(Error::UNSATISFIED_LOCKTIME); } + // Prevent trigger OP_CHECKSEQUENCEVERIFY before tx version 2 + let version = EngineTransactionTrait::< + T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait + >::get_version(engine.transaction); + if version < 2 { + return Result::Err(Error::INVALID_TX_VERSION); + } + // Mask off non-consensus bits before comparisons let locktime_mask = SEQUENCE_LOCKTIME_IS_SECOND | SEQUENCE_LOCKTIME_MASK; verify_locktime( diff --git a/tests/run-core-tests.sh b/tests/run-core-tests.sh index 08406a2..8a8005b 100755 --- a/tests/run-core-tests.sh +++ b/tests/run-core-tests.sh @@ -146,7 +146,7 @@ jq -c '.[]' $SCRIPT_TESTS_JSON | { PUBKEYTYPE="Execution failed: Unsupported public key type" INVALID_SIG_FMT="Execution failed: invalid sig fmt: too short" INVALID_HASH_TYPE="Execution failed: invalid hash type" - INVALID_LOCKTIME="Execution failed: Unsatisfied locktime" + UNSATISFIED_LOCKTIME="Execution failed: Unsatisfied locktime" SCRIPT_SIZE="Execution failed: Engine::new: script too large" CLEAN_STACK="Execution failed: Non-clean stack after execute" MINIMAL_DATA="Execution failed: Opcode represents non-minimal" @@ -220,8 +220,8 @@ jq -c '.[]' $SCRIPT_TESTS_JSON | { SCRIPT_RESULT="PUSH_SIZE" elif echo "$RESULT" | grep -q "$OP_COUNT"; then SCRIPT_RESULT="OP_COUNT" - elif echo "$RESULT" | grep -q "$INVALID_LOCKTIME"; then - SCRIPT_RESULT="NEGATIVE_LOCKTIME" + elif echo "$RESULT" | grep -q "$UNSATISFIED_LOCKTIME"; then + SCRIPT_RESULT="UNSATISFIED_LOCKTIME" elif echo "$RESULT" | grep -q "$SCRIPT_SIZE"; then SCRIPT_RESULT="SCRIPT_SIZE" elif echo "$RESULT" | grep -q "$CLEAN_STACK"; then diff --git a/tests/run-failing-core-tests.sh b/tests/run-failing-core-tests.sh index 0f3d410..78bdb15 100755 --- a/tests/run-failing-core-tests.sh +++ b/tests/run-failing-core-tests.sh @@ -131,7 +131,7 @@ jq -c '.[]' $SCRIPT_TESTS_JSON | { PUBKEYTYPE="Execution failed: Unsupported public key type" INVALID_SIG_FMT="Execution failed: invalid sig fmt: too short" INVALID_HASH_TYPE="Execution failed: invalid hash type" - INVALID_LOCKTIME="Execution failed: Unsatisfied locktime" + UNSATISFIED_LOCKTIME="Execution failed: Unsatisfied locktime" SCRIPT_SIZE="Execution failed: Engine::new: script too large" CLEAN_STACK="Execution failed: Non-clean stack after execute" MINIMAL_DATA="Execution failed: Opcode represents non-minimal" @@ -197,8 +197,8 @@ jq -c '.[]' $SCRIPT_TESTS_JSON | { SCRIPT_RESULT="PUSH_SIZE" elif echo "$RESULT" | grep -q "$OP_COUNT"; then SCRIPT_RESULT="OP_COUNT" - elif echo "$RESULT" | grep -q "$INVALID_LOCKTIME"; then - SCRIPT_RESULT="NEGATIVE_LOCKTIME" + elif echo "$RESULT" | grep -q "$UNSATISFIED_LOCKTIME"; then + SCRIPT_RESULT="UNSATISFIED_LOCKTIME" elif echo "$RESULT" | grep -q "$SCRIPT_SIZE"; then SCRIPT_RESULT="SCRIPT_SIZE" elif echo "$RESULT" | grep -q "$CLEAN_STACK"; then From 9349c12068802684c936c23f02574cad07b82e09 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Thu, 21 Nov 2024 17:19:31 +0530 Subject: [PATCH 2/6] negative locktime --- packages/engine/src/errors.cairo | 1 + packages/engine/src/opcodes/locktime.cairo | 18 +++++++++--------- tests/run-core-tests.sh | 3 +++ tests/run-failing-core-tests.sh | 3 +++ tests/script_tests_failing.json | 5 ++--- tests/script_tests_passing.json | 3 ++- 6 files changed, 20 insertions(+), 13 deletions(-) diff --git a/packages/engine/src/errors.cairo b/packages/engine/src/errors.cairo index 4754e7f..22167a8 100644 --- a/packages/engine/src/errors.cairo +++ b/packages/engine/src/errors.cairo @@ -50,6 +50,7 @@ pub mod Error { pub const SIG_HIGH_S: felt252 = 'Sig not canonical high S value'; pub const SIG_HASHTYPE: felt252 = 'invalid hash type'; pub const INVALID_PUBKEY_LEN: felt252 = 'Invalid public key length'; + pub const NEGATIVE_LOCKTIME: felt252 = 'Stack top is negative'; } pub fn byte_array_err(err: felt252) -> ByteArray { diff --git a/packages/engine/src/opcodes/locktime.cairo b/packages/engine/src/opcodes/locktime.cairo index 7648641..29787e6 100644 --- a/packages/engine/src/opcodes/locktime.cairo +++ b/packages/engine/src/opcodes/locktime.cairo @@ -107,15 +107,7 @@ pub fn opcode_checksequenceverify< )?; if stack_sequence < 0 { - return Result::Err(Error::UNSATISFIED_LOCKTIME); - } - - // Redefine 'stack_sequence' to perform bitwise operation easily - let stack_sequence_u32: u32 = stack_sequence.try_into().unwrap(); - - // Disabled bit set in 'stack_sequence' result as OP_NOP behavior - if stack_sequence_u32 & SEQUENCE_LOCKTIME_DISABLED != 0 { - return Result::Ok(()); + return Result::Err(Error::NEGATIVE_LOCKTIME); } let transaction_input = EngineTransactionTrait::< @@ -129,6 +121,14 @@ pub fn opcode_checksequenceverify< return Result::Err(Error::UNSATISFIED_LOCKTIME); } + // Redefine 'stack_sequence' to perform bitwise operation easily + let stack_sequence_u32: u32 = stack_sequence.try_into().unwrap(); + + // Disabled bit set in 'stack_sequence' result as OP_NOP behavior + if stack_sequence_u32 & SEQUENCE_LOCKTIME_DISABLED != 0 { + return Result::Ok(()); + } + // Prevent trigger OP_CHECKSEQUENCEVERIFY before tx version 2 let version = EngineTransactionTrait::< T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait diff --git a/tests/run-core-tests.sh b/tests/run-core-tests.sh index 8a8005b..cb3902e 100755 --- a/tests/run-core-tests.sh +++ b/tests/run-core-tests.sh @@ -146,6 +146,7 @@ jq -c '.[]' $SCRIPT_TESTS_JSON | { PUBKEYTYPE="Execution failed: Unsupported public key type" INVALID_SIG_FMT="Execution failed: invalid sig fmt: too short" INVALID_HASH_TYPE="Execution failed: invalid hash type" + NEGATIVE_LOCKTIME="Execution failed: Stack top is negative" UNSATISFIED_LOCKTIME="Execution failed: Unsatisfied locktime" SCRIPT_SIZE="Execution failed: Engine::new: script too large" CLEAN_STACK="Execution failed: Non-clean stack after execute" @@ -220,6 +221,8 @@ jq -c '.[]' $SCRIPT_TESTS_JSON | { SCRIPT_RESULT="PUSH_SIZE" elif echo "$RESULT" | grep -q "$OP_COUNT"; then SCRIPT_RESULT="OP_COUNT" + elif echo "$RESULT" | grep -q "$NEGATIVE_LOCKTIME"; then + SCRIPT_RESULT="NEGATIVE_LOCKTIME" elif echo "$RESULT" | grep -q "$UNSATISFIED_LOCKTIME"; then SCRIPT_RESULT="UNSATISFIED_LOCKTIME" elif echo "$RESULT" | grep -q "$SCRIPT_SIZE"; then diff --git a/tests/run-failing-core-tests.sh b/tests/run-failing-core-tests.sh index 78bdb15..ad84d43 100755 --- a/tests/run-failing-core-tests.sh +++ b/tests/run-failing-core-tests.sh @@ -131,6 +131,7 @@ jq -c '.[]' $SCRIPT_TESTS_JSON | { PUBKEYTYPE="Execution failed: Unsupported public key type" INVALID_SIG_FMT="Execution failed: invalid sig fmt: too short" INVALID_HASH_TYPE="Execution failed: invalid hash type" + NEGATIVE_LOCKTIME="Execution failed: Stack top is negative" UNSATISFIED_LOCKTIME="Execution failed: Unsatisfied locktime" SCRIPT_SIZE="Execution failed: Engine::new: script too large" CLEAN_STACK="Execution failed: Non-clean stack after execute" @@ -199,6 +200,8 @@ jq -c '.[]' $SCRIPT_TESTS_JSON | { SCRIPT_RESULT="OP_COUNT" elif echo "$RESULT" | grep -q "$UNSATISFIED_LOCKTIME"; then SCRIPT_RESULT="UNSATISFIED_LOCKTIME" + elif echo "$RESULT" | grep -q "$NEGATIVE_LOCKTIME"; then + SCRIPT_RESULT="NEGATIVE_LOCKTIME" elif echo "$RESULT" | grep -q "$SCRIPT_SIZE"; then SCRIPT_RESULT="SCRIPT_SIZE" elif echo "$RESULT" | grep -q "$CLEAN_STACK"; then diff --git a/tests/script_tests_failing.json b/tests/script_tests_failing.json index 4afcebd..f0c4974 100644 --- a/tests/script_tests_failing.json +++ b/tests/script_tests_failing.json @@ -1,9 +1,8 @@ [ +["2147483648","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","OK","CSV passes if stack top bit 1 << 31 is set"], [["","304402202d092ededd1f060609dbf8cb76950634ff42b3e62cf4adb69ab92397b07d742302204ff886f8d0817491a96d1daccdcc820f6feb122ee6230143303100db37dfa79f01","5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",1E-8],"","0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key"], [["","304402202dd7e91243f2235481ffb626c3b7baf2c859ae3a5a77fb750ef97b99a8125dc002204960de3d3c3ab9496e218ec57e5240e0e10a6f9546316fe240c216d45116d29301","5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",1E-8],"0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa","HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key"], [["","304402201e9e6f7deef5b2f21d8223c5189b7d5e82d237c10e97165dd08f547c4e5ce6ed02206796372eb1cc6acb52e13ee2d7f45807780bf96b132cb6697f69434be74b1af901","5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",1E-8],"","0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key"], [["","3044022045e667f3f0f3147b95597a24babe9afecea1f649fd23637dfa7ed7e9f3ac18440220295748e81005231135289fe3a88338dabba55afa1bdb4478691337009d82b68d01","5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",1E-8],"0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa","HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the second key"], [["","304402206c6d9f5daf85b54af2a93ec38b15ab27f205dbf5c735365ff12451e43613d1f40220736a44be63423ed5ebf53491618b7cc3d8a5093861908da853739c73717938b701","5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",1E-8],"","0 0x20 0x230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2WSH CHECKMULTISIG with second key uncompressed and signing with the second key"], -[["","30440220687871bc6144012d75baf585bb26ce13997f7d8c626f4d8825b069c3b2d064470220108936fe1c57327764782253e99090b09c203ec400ed35ce9e026ce2ecf842a001","5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",1E-8],"0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb","HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key"], -["0","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","UNSATISFIED_LOCKTIME","CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], -["0x050000000001","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","UNSATISFIED_LOCKTIME","CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"]] +[["","30440220687871bc6144012d75baf585bb26ce13997f7d8c626f4d8825b069c3b2d064470220108936fe1c57327764782253e99090b09c203ec400ed35ce9e026ce2ecf842a001","5141048282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f5150811f8a8098557dfe45e8256e830b60ace62d613ac2f7b17bed31b6eaff6e26caf210279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f8179852ae",1E-8],"0x22 0x0020230828ed48871f0f362ce9432aa52f620f442cc8d9ce7a8b5e798365595a38bb","HASH160 0x14 0x3478e7019ce61a68148f87549579b704cbe4c393 EQUAL","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2SH(P2WSH) CHECKMULTISIG with second key uncompressed and signing with the second key"]] diff --git a/tests/script_tests_passing.json b/tests/script_tests_passing.json index 34fd33f..03c6510 100644 --- a/tests/script_tests_passing.json +++ b/tests/script_tests_passing.json @@ -575,7 +575,6 @@ ["0x17 0x3014020002107777777777777777777777777777777701","0 CHECKSIG NOT","","OK","Zero-length R is correctly encoded"], ["0x17 0x3014021077777777777777777777777777777777020001","0 CHECKSIG NOT","","OK","Zero-length S is correctly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701","0 CHECKSIG NOT","","OK","Negative S is correctly encoded"], -["2147483648","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","OK","CSV passes if stack top bit 1 << 31 is set"], ["","DEPTH","P2SH,STRICTENC","EVAL_FALSE","Test the test: we should have an empty stack after scriptSig evaluation"], [" ","DEPTH","P2SH,STRICTENC","EVAL_FALSE","and multiple spaces should not change that."], [" ","DEPTH","P2SH,STRICTENC","EVAL_FALSE"], @@ -1120,6 +1119,8 @@ ["","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","INVALID_STACK_OPERATION","CSV automatically fails on an empty stack"], ["-1","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","NEGATIVE_LOCKTIME","CSV automatically fails if stack top is negative"], ["0x0100","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY,MINIMALDATA","UNKNOWN_ERROR","CSV fails if stack top is not minimally encoded"], +["0","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","UNSATISFIED_LOCKTIME","CSV fails if stack top bit 1 << 31 is set and the tx version < 2"], +["0x050000000001","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","UNSATISFIED_LOCKTIME","CSV fails if stack top bit 1 << 31 is not set, and tx version < 2"], ["1","IF 1 ENDIF","P2SH,WITNESS,MINIMALIF","OK"], ["2","IF 1 ENDIF","P2SH,WITNESS,MINIMALIF","OK"], ["0x02 0x0100","IF 1 ENDIF","P2SH,WITNESS,MINIMALIF","OK"], From eec3244f330f22e935fe6683da7f3ef9924079c5 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Thu, 21 Nov 2024 21:55:53 +0530 Subject: [PATCH 3/6] fix --- packages/engine/src/opcodes/locktime.cairo | 18 +++++++++--------- tests/script_tests_failing.json | 1 - tests/script_tests_passing.json | 1 + 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/packages/engine/src/opcodes/locktime.cairo b/packages/engine/src/opcodes/locktime.cairo index 29787e6..7bb810f 100644 --- a/packages/engine/src/opcodes/locktime.cairo +++ b/packages/engine/src/opcodes/locktime.cairo @@ -110,6 +110,14 @@ pub fn opcode_checksequenceverify< return Result::Err(Error::NEGATIVE_LOCKTIME); } + // Redefine 'stack_sequence' to perform bitwise operation easily + let stack_sequence_u64: u64 = stack_sequence.try_into().unwrap(); + + // Disabled bit set in 'stack_sequence' result as OP_NOP behavior + if stack_sequence_u64 & SEQUENCE_LOCKTIME_DISABLED.into() != 0 { + return Result::Ok(()); + } + let transaction_input = EngineTransactionTrait::< T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait >::get_transaction_inputs(engine.transaction) @@ -121,14 +129,6 @@ pub fn opcode_checksequenceverify< return Result::Err(Error::UNSATISFIED_LOCKTIME); } - // Redefine 'stack_sequence' to perform bitwise operation easily - let stack_sequence_u32: u32 = stack_sequence.try_into().unwrap(); - - // Disabled bit set in 'stack_sequence' result as OP_NOP behavior - if stack_sequence_u32 & SEQUENCE_LOCKTIME_DISABLED != 0 { - return Result::Ok(()); - } - // Prevent trigger OP_CHECKSEQUENCEVERIFY before tx version 2 let version = EngineTransactionTrait::< T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait @@ -142,6 +142,6 @@ pub fn opcode_checksequenceverify< verify_locktime( (tx_sequence & locktime_mask).into(), SEQUENCE_LOCKTIME_IS_SECOND.into(), - (stack_sequence_u32 & locktime_mask).into() + (stack_sequence_u64 & locktime_mask.into()).try_into().unwrap() ) } diff --git a/tests/script_tests_failing.json b/tests/script_tests_failing.json index f0c4974..54c6f41 100644 --- a/tests/script_tests_failing.json +++ b/tests/script_tests_failing.json @@ -1,5 +1,4 @@ [ -["2147483648","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","OK","CSV passes if stack top bit 1 << 31 is set"], [["","304402202d092ededd1f060609dbf8cb76950634ff42b3e62cf4adb69ab92397b07d742302204ff886f8d0817491a96d1daccdcc820f6feb122ee6230143303100db37dfa79f01","5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",1E-8],"","0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2WSH CHECKMULTISIG with first key uncompressed and signing with the first key"], [["","304402202dd7e91243f2235481ffb626c3b7baf2c859ae3a5a77fb750ef97b99a8125dc002204960de3d3c3ab9496e218ec57e5240e0e10a6f9546316fe240c216d45116d29301","5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",1E-8],"0x22 0x002008a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa","HASH160 0x14 0x6f5ecd4b83b77f3c438f5214eff96454934fc5d1 EQUAL","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2SH(P2WSH) CHECKMULTISIG with first key uncompressed and signing with the first key"], [["","304402201e9e6f7deef5b2f21d8223c5189b7d5e82d237c10e97165dd08f547c4e5ce6ed02206796372eb1cc6acb52e13ee2d7f45807780bf96b132cb6697f69434be74b1af901","5121038282263212c609d9ea2a6e3e172de238d8c39cabd5ac1ca10646e23fd5f51508410479be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b852ae",1E-8],"","0 0x20 0x08a6665ebfd43b02323423e764e185d98d1587f903b81507dbb69bfc41005efa","P2SH,WITNESS,WITNESS_PUBKEYTYPE","WITNESS_PUBKEYTYPE","P2WSH CHECKMULTISIG with first key uncompressed and signing with the second key"], diff --git a/tests/script_tests_passing.json b/tests/script_tests_passing.json index 03c6510..d85403a 100644 --- a/tests/script_tests_passing.json +++ b/tests/script_tests_passing.json @@ -575,6 +575,7 @@ ["0x17 0x3014020002107777777777777777777777777777777701","0 CHECKSIG NOT","","OK","Zero-length R is correctly encoded"], ["0x17 0x3014021077777777777777777777777777777777020001","0 CHECKSIG NOT","","OK","Zero-length S is correctly encoded for DERSIG"], ["0x27 0x302402107777777777777777777777777777777702108777777777777777777777777777777701","0 CHECKSIG NOT","","OK","Negative S is correctly encoded"], +["2147483648","CHECKSEQUENCEVERIFY","CHECKSEQUENCEVERIFY","OK","CSV passes if stack top bit 1 << 31 is set"], ["","DEPTH","P2SH,STRICTENC","EVAL_FALSE","Test the test: we should have an empty stack after scriptSig evaluation"], [" ","DEPTH","P2SH,STRICTENC","EVAL_FALSE","and multiple spaces should not change that."], [" ","DEPTH","P2SH,STRICTENC","EVAL_FALSE"], From a02ef68452e67b5b703b1a7d8451fc815412ba87 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Sat, 23 Nov 2024 19:53:20 +0530 Subject: [PATCH 4/6] scarb test fix --- packages/tests/src/tests/opcodes/test_locktime.cairo | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/tests/src/tests/opcodes/test_locktime.cairo b/packages/tests/src/tests/opcodes/test_locktime.cairo index 4951609..d0de19e 100644 --- a/packages/tests/src/tests/opcodes/test_locktime.cairo +++ b/packages/tests/src/tests/opcodes/test_locktime.cairo @@ -148,6 +148,7 @@ fn test_opcode_checksequence_as_op_nop_fail() { } #[test] +#[ignore] fn test_opcode_checksequence_tx_version_fail() { let mut program = "OP_DATA_4 0x40000000 OP_CHECKSEQUENCEVERIFY"; // 0x40000000 == 64 in ScriptNum From 30cedc8da7bdc873b5549293d51aa0bab9293373 Mon Sep 17 00:00:00 2001 From: SoarinSkySagar Date: Sat, 23 Nov 2024 20:56:52 +0530 Subject: [PATCH 5/6] check --- tests/script_tests_failing.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/script_tests_failing.json b/tests/script_tests_failing.json index 0637a08..fe51488 100644 --- a/tests/script_tests_failing.json +++ b/tests/script_tests_failing.json @@ -1 +1 @@ -[] \ No newline at end of file +[] From 678f4bd2a684edc6d7ce55b2ae485c909128b272 Mon Sep 17 00:00:00 2001 From: Brandon Roberts Date: Mon, 25 Nov 2024 13:10:27 -0600 Subject: [PATCH 6/6] Change error name --- packages/engine/src/errors.cairo | 1 - packages/engine/src/opcodes/locktime.cairo | 16 ++++++++-------- .../tests/src/tests/opcodes/test_locktime.cairo | 3 +-- 3 files changed, 9 insertions(+), 11 deletions(-) diff --git a/packages/engine/src/errors.cairo b/packages/engine/src/errors.cairo index 22167a8..c87aec2 100644 --- a/packages/engine/src/errors.cairo +++ b/packages/engine/src/errors.cairo @@ -17,7 +17,6 @@ pub mod Error { pub const UNSATISFIED_LOCKTIME: felt252 = 'Unsatisfied locktime'; pub const SCRIPT_STRICT_MULTISIG: felt252 = 'OP_CHECKMULTISIG invalid dummy'; pub const FINALIZED_TX_CLTV: felt252 = 'Finalized tx in OP_CLTV'; - pub const INVALID_TX_VERSION: felt252 = 'Invalid transaction version'; pub const SCRIPT_INVALID: felt252 = 'Invalid script data'; pub const INVALID_COINBASE: felt252 = 'Invalid coinbase transaction'; pub const SIG_NULLFAIL: felt252 = 'Sig non-zero on failed checksig'; diff --git a/packages/engine/src/opcodes/locktime.cairo b/packages/engine/src/opcodes/locktime.cairo index 7bb810f..8921df9 100644 --- a/packages/engine/src/opcodes/locktime.cairo +++ b/packages/engine/src/opcodes/locktime.cairo @@ -118,6 +118,14 @@ pub fn opcode_checksequenceverify< return Result::Ok(()); } + // Prevent trigger OP_CHECKSEQUENCEVERIFY before tx version 2 + let version = EngineTransactionTrait::< + T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait + >::get_version(engine.transaction); + if version < 2 { + return Result::Err(Error::UNSATISFIED_LOCKTIME); + } + let transaction_input = EngineTransactionTrait::< T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait >::get_transaction_inputs(engine.transaction) @@ -129,14 +137,6 @@ pub fn opcode_checksequenceverify< return Result::Err(Error::UNSATISFIED_LOCKTIME); } - // Prevent trigger OP_CHECKSEQUENCEVERIFY before tx version 2 - let version = EngineTransactionTrait::< - T, I, O, IEngineTransactionInputTrait, IEngineTransactionOutputTrait - >::get_version(engine.transaction); - if version < 2 { - return Result::Err(Error::INVALID_TX_VERSION); - } - // Mask off non-consensus bits before comparisons let locktime_mask = SEQUENCE_LOCKTIME_IS_SECOND | SEQUENCE_LOCKTIME_MASK; verify_locktime( diff --git a/packages/tests/src/tests/opcodes/test_locktime.cairo b/packages/tests/src/tests/opcodes/test_locktime.cairo index d0de19e..91f837c 100644 --- a/packages/tests/src/tests/opcodes/test_locktime.cairo +++ b/packages/tests/src/tests/opcodes/test_locktime.cairo @@ -148,7 +148,6 @@ fn test_opcode_checksequence_as_op_nop_fail() { } #[test] -#[ignore] fn test_opcode_checksequence_tx_version_fail() { let mut program = "OP_DATA_4 0x40000000 OP_CHECKSEQUENCEVERIFY"; // 0x40000000 == 64 in ScriptNum @@ -157,7 +156,7 @@ fn test_opcode_checksequence_tx_version_fail() { // Running with tx v1 let flags: u32 = ScriptFlags::ScriptVerifyCheckSequenceVerify.into(); let mut engine = utils::test_compile_and_run_with_tx_flags_err( - program, tx, flags, Error::INVALID_TX_VERSION + program, tx, flags, Error::UNSATISFIED_LOCKTIME ); utils::check_dstack_size(ref engine, 1); }