Changeset View
Changeset View
Standalone View
Standalone View
src/test/script_pushonly_tests.cpp
Show All 18 Lines | BOOST_AUTO_TEST_CASE(invalid_scripts) { | ||||
// IsPushOnly returns false when given a script containing only pushes that | // IsPushOnly returns false when given a script containing only pushes that | ||||
// are invalid due to truncation. IsPushOnly() is consensus critical because | // are invalid due to truncation. IsPushOnly() is consensus critical because | ||||
// P2SH evaluation uses it, although this specific behavior should not be | // P2SH evaluation uses it, although this specific behavior should not be | ||||
// consensus critical as the P2SH evaluation would fail first due to the | // consensus critical as the P2SH evaluation would fail first due to the | ||||
// invalid push. Still, it doesn't hurt to test it explicitly. | // invalid push. Still, it doesn't hurt to test it explicitly. | ||||
{ | { | ||||
CScript script = script_from_raw({0x01}); | CScript script = script_from_raw({0x01}); | ||||
BOOST_CHECK(!script.IsPushOnly()); | BOOST_CHECK(!script.IsPushOnly()); | ||||
// Also test IsMinimalPushOnly | |||||
BOOST_CHECK(!script.IsMinimalPushOnly()); | |||||
} | } | ||||
// Additional tests | // Additional tests | ||||
{ | { | ||||
// PUSHDATA1 truncated before size | // PUSHDATA1 truncated before size | ||||
CScript script = script_from_raw({0x4c}); | CScript script = script_from_raw({0x4c}); | ||||
BOOST_CHECK(!script.IsPushOnly()); | BOOST_CHECK(!script.IsPushOnly()); | ||||
BOOST_CHECK(!script.IsMinimalPushOnly()); | |||||
} | } | ||||
{ | { | ||||
// PUSHDATA1 truncated mid-data | // PUSHDATA1 truncated mid-data | ||||
CScript script = script_from_raw({0x4c, 0x02, 0x00}); | CScript script = script_from_raw({0x4c, 0x02, 0x00}); | ||||
BOOST_CHECK(!script.IsPushOnly()); | BOOST_CHECK(!script.IsPushOnly()); | ||||
BOOST_CHECK(!script.IsMinimalPushOnly()); | |||||
} | } | ||||
{ | { | ||||
// PUSHDATA2 truncated mid-size | // PUSHDATA2 truncated mid-size | ||||
CScript script = script_from_raw({0x4d, 0x01}); | CScript script = script_from_raw({0x4d, 0x01}); | ||||
BOOST_CHECK(!script.IsPushOnly()); | BOOST_CHECK(!script.IsPushOnly()); | ||||
BOOST_CHECK(!script.IsMinimalPushOnly()); | |||||
} | } | ||||
{ | { | ||||
// PUSHDATA2 truncated mid-data | // PUSHDATA2 truncated mid-data | ||||
CScript script = script_from_raw({0x4d, 0x02, 0x00, 0x00}); | CScript script = script_from_raw({0x4d, 0x02, 0x00, 0x00}); | ||||
BOOST_CHECK(!script.IsPushOnly()); | BOOST_CHECK(!script.IsPushOnly()); | ||||
BOOST_CHECK(!script.IsMinimalPushOnly()); | |||||
} | } | ||||
{ | { | ||||
// PUSHDATA4 truncated mid-size | // PUSHDATA4 truncated mid-size | ||||
CScript script = script_from_raw({0x4e, 0x01}); | CScript script = script_from_raw({0x4e, 0x01}); | ||||
BOOST_CHECK(!script.IsPushOnly()); | BOOST_CHECK(!script.IsPushOnly()); | ||||
BOOST_CHECK(!script.IsMinimalPushOnly()); | |||||
} | } | ||||
{ | { | ||||
// PUSHDATA4 truncated mid-data | // PUSHDATA4 truncated mid-data | ||||
CScript script = script_from_raw({0x4e, 0x02, 0x00, 0x00, 0x00, 0x00}); | CScript script = script_from_raw({0x4e, 0x02, 0x00, 0x00, 0x00, 0x00}); | ||||
BOOST_CHECK(!script.IsPushOnly()); | BOOST_CHECK(!script.IsPushOnly()); | ||||
BOOST_CHECK(!script.IsMinimalPushOnly()); | |||||
} | } | ||||
{ | { | ||||
// PUSHDATA4 with massive size (4 GB), truncated | // PUSHDATA4 with massive size (4 GB), truncated | ||||
CScript script = | CScript script = | ||||
script_from_raw({0x4e, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00}); | script_from_raw({0x4e, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00}); | ||||
BOOST_CHECK(!script.IsPushOnly()); | BOOST_CHECK(!script.IsPushOnly()); | ||||
BOOST_CHECK(!script.IsMinimalPushOnly()); | |||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(singlebyteopcodes) { | BOOST_AUTO_TEST_CASE(singlebyteopcodes) { | ||||
// OP_0 and OP_1NEGATE and OP_1 through OP_16 are push-only. | // OP_0 and OP_1NEGATE and OP_1 through OP_16 are push-only and minimal. | ||||
CScript onebytepushes = CScript() << OP_0 << OP_1NEGATE << OP_1 << OP_2 | CScript onebytepushes = CScript() << OP_0 << OP_1NEGATE << OP_1 << OP_2 | ||||
<< OP_3 << OP_4 << OP_5 << OP_6 << OP_7 | << OP_3 << OP_4 << OP_5 << OP_6 << OP_7 | ||||
<< OP_8 << OP_9 << OP_10 << OP_11 << OP_12 | << OP_8 << OP_9 << OP_10 << OP_11 << OP_12 | ||||
<< OP_13 << OP_14 << OP_15 << OP_16; | << OP_13 << OP_14 << OP_15 << OP_16; | ||||
BOOST_CHECK(onebytepushes.IsPushOnly()); | BOOST_CHECK(onebytepushes.IsPushOnly()); | ||||
// OP_0 and OP_1NEGATE through to OP_16 (incl OP_RESERVED) are "PushOnly". | BOOST_CHECK(onebytepushes.IsMinimalPushOnly()); | ||||
// OP_0 and OP_1NEGATE through to OP_16 (incl OP_RESERVED) are "PushOnly" | |||||
// but not actually push-only. | |||||
CScript withreserved = onebytepushes << OP_RESERVED; | CScript withreserved = onebytepushes << OP_RESERVED; | ||||
BOOST_CHECK(withreserved.IsPushOnly()); | BOOST_CHECK(withreserved.IsPushOnly()); | ||||
BOOST_CHECK(!withreserved.IsMinimalPushOnly()); | |||||
// Do all single-byte opcodes, except OP_0. | // Do all single-byte opcodes, except OP_0. | ||||
for (uint8_t op = 0xff; op > OP_PUSHDATA4; op--) { | for (uint8_t op = 0xff; op > OP_PUSHDATA4; op--) { | ||||
CScript script = CScript() << OP_5 << opcodetype(op) << OP_11; | CScript script = CScript() << OP_5 << opcodetype(op) << OP_11; | ||||
BOOST_CHECK_EQUAL(script.IsPushOnly(), op <= OP_16); | BOOST_CHECK_EQUAL(script.IsPushOnly(), op <= OP_16); | ||||
BOOST_CHECK_EQUAL(script.IsMinimalPushOnly(), | |||||
op <= OP_16 && op != OP_RESERVED); | |||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_CASE(byteforms) { | BOOST_AUTO_TEST_CASE(byteforms) { | ||||
// Test various ways of pushing the same thing. | // Test various ways of pushing the same thing. | ||||
// Do 0-byte (null) push in all four forms. | // Do 0-byte (null) push in all four forms. | ||||
{ | { | ||||
CScript scriptPUSH = CScript() << OP_0; | CScript scriptPUSH = CScript() << OP_0; | ||||
BOOST_CHECK(scriptPUSH.IsPushOnly()); | BOOST_CHECK(scriptPUSH.IsPushOnly()); | ||||
BOOST_CHECK(scriptPUSH.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA1 = script_from_raw({0x4c, 0x00}); | CScript scriptPUSHDATA1 = script_from_raw({0x4c, 0x00}); | ||||
BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA1.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA2 = script_from_raw({0x4d, 0x00, 0x00}); | CScript scriptPUSHDATA2 = script_from_raw({0x4d, 0x00, 0x00}); | ||||
BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA2.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA4 = | CScript scriptPUSHDATA4 = | ||||
script_from_raw({0x4e, 0x00, 0x00, 0x00, 0x00}); | script_from_raw({0x4e, 0x00, 0x00, 0x00, 0x00}); | ||||
BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA4.IsMinimalPushOnly()); | |||||
} | } | ||||
// Do all possible 1-byte pushes in all four forms. | // Do all possible 1-byte pushes in all four forms. | ||||
for (int i = 0; i < 256; i++) { | for (int i = 0; i < 256; i++) { | ||||
// [0x01] to [0x10] and [0x81] all have special forms. | |||||
bool hasSpecialOpCode = ((i > 0 && i <= 16) || i == 0x81); | |||||
CScript scriptPUSH = script_from_raw({0x01, uint8_t(i)}); | CScript scriptPUSH = script_from_raw({0x01, uint8_t(i)}); | ||||
BOOST_CHECK(scriptPUSH.IsPushOnly()); | BOOST_CHECK(scriptPUSH.IsPushOnly()); | ||||
BOOST_CHECK_EQUAL(scriptPUSH.IsMinimalPushOnly(), !hasSpecialOpCode); | |||||
CScript scriptPUSHDATA1 = script_from_raw({0x4c, 0x01, uint8_t(i)}); | CScript scriptPUSHDATA1 = script_from_raw({0x4c, 0x01, uint8_t(i)}); | ||||
BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA1.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA2 = | CScript scriptPUSHDATA2 = | ||||
script_from_raw({0x4d, 0x01, 0x00, uint8_t(i)}); | script_from_raw({0x4d, 0x01, 0x00, uint8_t(i)}); | ||||
BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA2.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA4 = | CScript scriptPUSHDATA4 = | ||||
script_from_raw({0x4e, 0x01, 0x00, 0x00, 0x00, uint8_t(i)}); | script_from_raw({0x4e, 0x01, 0x00, 0x00, 0x00, uint8_t(i)}); | ||||
BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA4.IsMinimalPushOnly()); | |||||
} | } | ||||
// Do various longer pushes. | // Do various longer pushes. | ||||
// two bytes: [0x00, 0x00] | // two bytes: [0x00, 0x00] | ||||
{ | { | ||||
CScript scriptPUSH = script_from_raw({0x02, 0x00, 0x00}); | CScript scriptPUSH = script_from_raw({0x02, 0x00, 0x00}); | ||||
BOOST_CHECK(scriptPUSH.IsPushOnly()); | BOOST_CHECK(scriptPUSH.IsPushOnly()); | ||||
BOOST_CHECK(scriptPUSH.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA1 = script_from_raw({0x4c, 0x02, 0x00, 0x00}); | CScript scriptPUSHDATA1 = script_from_raw({0x4c, 0x02, 0x00, 0x00}); | ||||
BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA1.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA2 = | CScript scriptPUSHDATA2 = | ||||
script_from_raw({0x4d, 0x02, 0x00, 0x00, 0x00}); | script_from_raw({0x4d, 0x02, 0x00, 0x00, 0x00}); | ||||
BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA2.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA4 = | CScript scriptPUSHDATA4 = | ||||
script_from_raw({0x4e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}); | script_from_raw({0x4e, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00}); | ||||
BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA4.IsMinimalPushOnly()); | |||||
} | } | ||||
// 75 zero bytes | // 75 zero bytes | ||||
{ | { | ||||
CScript scriptPUSH = script_from_raw({75}); | CScript scriptPUSH = script_from_raw({75}); | ||||
scriptPUSH.resize(scriptPUSH.size() + 75); | scriptPUSH.resize(scriptPUSH.size() + 75); | ||||
BOOST_CHECK(scriptPUSH.IsPushOnly()); | BOOST_CHECK(scriptPUSH.IsPushOnly()); | ||||
BOOST_CHECK(scriptPUSH.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA1 = script_from_raw({0x4c, 75}); | CScript scriptPUSHDATA1 = script_from_raw({0x4c, 75}); | ||||
scriptPUSHDATA1.resize(scriptPUSHDATA1.size() + 75); | scriptPUSHDATA1.resize(scriptPUSHDATA1.size() + 75); | ||||
BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA1.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA2 = script_from_raw({ | CScript scriptPUSHDATA2 = script_from_raw({ | ||||
0x4d, | 0x4d, | ||||
75, | 75, | ||||
0x00, | 0x00, | ||||
}); | }); | ||||
scriptPUSHDATA2.resize(scriptPUSHDATA2.size() + 75); | scriptPUSHDATA2.resize(scriptPUSHDATA2.size() + 75); | ||||
BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA2.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA4 = script_from_raw({0x4e, 75, 0x00, 0x00, 0x00}); | CScript scriptPUSHDATA4 = script_from_raw({0x4e, 75, 0x00, 0x00, 0x00}); | ||||
scriptPUSHDATA4.resize(scriptPUSHDATA4.size() + 75); | scriptPUSHDATA4.resize(scriptPUSHDATA4.size() + 75); | ||||
BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA4.IsMinimalPushOnly()); | |||||
} | } | ||||
// 255 zero bytes | // 255 zero bytes | ||||
{ | { | ||||
CScript scriptPUSHDATA1 = script_from_raw({0x4c, 255}); | CScript scriptPUSHDATA1 = script_from_raw({0x4c, 255}); | ||||
scriptPUSHDATA1.resize(scriptPUSHDATA1.size() + 255); | scriptPUSHDATA1.resize(scriptPUSHDATA1.size() + 255); | ||||
BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA1.IsPushOnly()); | ||||
BOOST_CHECK(scriptPUSHDATA1.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA2 = script_from_raw({ | CScript scriptPUSHDATA2 = script_from_raw({ | ||||
0x4d, | 0x4d, | ||||
255, | 255, | ||||
0x00, | 0x00, | ||||
}); | }); | ||||
scriptPUSHDATA2.resize(scriptPUSHDATA2.size() + 255); | scriptPUSHDATA2.resize(scriptPUSHDATA2.size() + 255); | ||||
BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA2.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA4 = | CScript scriptPUSHDATA4 = | ||||
script_from_raw({0x4e, 255, 0x00, 0x00, 0x00}); | script_from_raw({0x4e, 255, 0x00, 0x00, 0x00}); | ||||
scriptPUSHDATA4.resize(scriptPUSHDATA4.size() + 255); | scriptPUSHDATA4.resize(scriptPUSHDATA4.size() + 255); | ||||
BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA4.IsMinimalPushOnly()); | |||||
} | } | ||||
// 0xffff zero bytes | // 0xffff zero bytes | ||||
{ | { | ||||
CScript scriptPUSHDATA2 = script_from_raw({ | CScript scriptPUSHDATA2 = script_from_raw({ | ||||
0x4d, | 0x4d, | ||||
0xff, | 0xff, | ||||
0xff, | 0xff, | ||||
}); | }); | ||||
scriptPUSHDATA2.resize(scriptPUSHDATA2.size() + 0xffff); | scriptPUSHDATA2.resize(scriptPUSHDATA2.size() + 0xffff); | ||||
BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA2.IsPushOnly()); | ||||
BOOST_CHECK(scriptPUSHDATA2.IsMinimalPushOnly()); | |||||
CScript scriptPUSHDATA4 = | CScript scriptPUSHDATA4 = | ||||
script_from_raw({0x4e, 0xff, 0xff, 0x00, 0x00}); | script_from_raw({0x4e, 0xff, 0xff, 0x00, 0x00}); | ||||
scriptPUSHDATA4.resize(scriptPUSHDATA4.size() + 0xffff); | scriptPUSHDATA4.resize(scriptPUSHDATA4.size() + 0xffff); | ||||
BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | ||||
BOOST_CHECK(!scriptPUSHDATA4.IsMinimalPushOnly()); | |||||
} | } | ||||
// 0x10000 zero bytes | // 0x10000 zero bytes | ||||
{ | { | ||||
CScript scriptPUSHDATA4 = | CScript scriptPUSHDATA4 = | ||||
script_from_raw({0x4e, 0x00, 0x00, 0x01, 0x00}); | script_from_raw({0x4e, 0x00, 0x00, 0x01, 0x00}); | ||||
scriptPUSHDATA4.resize(scriptPUSHDATA4.size() + 0x10000); | scriptPUSHDATA4.resize(scriptPUSHDATA4.size() + 0x10000); | ||||
BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | BOOST_CHECK(scriptPUSHDATA4.IsPushOnly()); | ||||
BOOST_CHECK(scriptPUSHDATA4.IsMinimalPushOnly()); | |||||
} | } | ||||
} | } | ||||
BOOST_AUTO_TEST_SUITE_END() | BOOST_AUTO_TEST_SUITE_END() |