Skip to content

Commit 5212150

Browse files
committed
test: assert CScript allocation characteristics
Verifies that script types are correctly allocated using prevector's direct or indirect storage based on their size: Direct allocated script types (size ≤ 28 bytes): * OP_RETURN (small) * P2WPKH * P2SH * P2PKH Indirect allocated script types (size > 28 bytes): * P2WSH * P2TR * P2PK * MULTISIG (small) This test provides a baseline for verifying changes to prevector's inline capacity. The `CHECK_SCRIPT_STATIC_SIZE` and `CHECK_SCRIPT_DYNAMIC_SIZE` macros were added to differentiate the two cases - while preserving the correct source code line in case of failure.
1 parent 65ac7f6 commit 5212150

File tree

1 file changed

+101
-0
lines changed

1 file changed

+101
-0
lines changed

src/test/script_tests.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1151,6 +1151,107 @@ BOOST_AUTO_TEST_CASE(script_CHECKMULTISIG23)
11511151
BOOST_CHECK_MESSAGE(err == SCRIPT_ERR_INVALID_STACK_OPERATION, ScriptErrorString(err));
11521152
}
11531153

1154+
/** Return the TxoutType of a script without exposing Solver details. */
1155+
static TxoutType GetTxoutType(const CScript& output_script)
1156+
{
1157+
std::vector<std::vector<uint8_t>> unused;
1158+
return Solver(output_script, unused);
1159+
}
1160+
1161+
#define CHECK_SCRIPT_STATIC_SIZE(script, expected_size) \
1162+
do { \
1163+
BOOST_CHECK_EQUAL((script).size(), (expected_size)); \
1164+
BOOST_CHECK_EQUAL((script).capacity(), CScriptBase::STATIC_SIZE); \
1165+
BOOST_CHECK_EQUAL((script).allocated_memory(), 0); \
1166+
} while (0)
1167+
1168+
#define CHECK_SCRIPT_DYNAMIC_SIZE(script, expected_size, expected_extra) \
1169+
do { \
1170+
BOOST_CHECK_EQUAL((script).size(), (expected_size)); \
1171+
BOOST_CHECK_EQUAL((script).capacity(), (expected_extra)); \
1172+
BOOST_CHECK_EQUAL((script).allocated_memory(), (expected_extra)); \
1173+
} while (0)
1174+
1175+
BOOST_AUTO_TEST_CASE(script_size_and_capacity_test)
1176+
{
1177+
BOOST_CHECK_EQUAL(sizeof(CompressedScript), 40);
1178+
BOOST_CHECK_EQUAL(sizeof(CScriptBase), 32);
1179+
BOOST_CHECK_NE(sizeof(CScriptBase), sizeof(prevector<CScriptBase::STATIC_SIZE + 1, uint8_t>)); // CScriptBase size should be set to avoid wasting space in padding
1180+
BOOST_CHECK_EQUAL(sizeof(CScript), 32);
1181+
BOOST_CHECK_EQUAL(sizeof(CTxOut), 40);
1182+
1183+
CKey dummy_key;
1184+
dummy_key.MakeNewKey(/*fCompressed=*/true);
1185+
const CPubKey dummy_pubkey{dummy_key.GetPubKey()};
1186+
1187+
// Small OP_RETURN has direct allocation
1188+
{
1189+
const auto script{CScript() << OP_RETURN << std::vector<uint8_t>(10, 0xaa)};
1190+
BOOST_CHECK_EQUAL(GetTxoutType(script), TxoutType::NULL_DATA);
1191+
CHECK_SCRIPT_STATIC_SIZE(script, 12);
1192+
}
1193+
1194+
// P2WPKH has direct allocation
1195+
{
1196+
const auto script{GetScriptForDestination(WitnessV0KeyHash{PKHash{dummy_pubkey}})};
1197+
BOOST_CHECK_EQUAL(GetTxoutType(script), TxoutType::WITNESS_V0_KEYHASH);
1198+
CHECK_SCRIPT_STATIC_SIZE(script, 22);
1199+
}
1200+
1201+
// P2SH has direct allocation
1202+
{
1203+
const auto script{GetScriptForDestination(ScriptHash{CScript{} << OP_TRUE})};
1204+
BOOST_CHECK(script.IsPayToScriptHash());
1205+
CHECK_SCRIPT_STATIC_SIZE(script, 23);
1206+
}
1207+
1208+
// P2PKH has direct allocation
1209+
{
1210+
const auto script{GetScriptForDestination(PKHash{dummy_pubkey})};
1211+
BOOST_CHECK_EQUAL(GetTxoutType(script), TxoutType::PUBKEYHASH);
1212+
CHECK_SCRIPT_STATIC_SIZE(script, 25);
1213+
}
1214+
1215+
// P2WSH needs extra allocation
1216+
{
1217+
const auto script{GetScriptForDestination(WitnessV0ScriptHash{CScript{} << OP_TRUE})};
1218+
BOOST_CHECK(script.IsPayToWitnessScriptHash());
1219+
CHECK_SCRIPT_DYNAMIC_SIZE(script, 34, 34);
1220+
}
1221+
1222+
// P2TR needs extra allocation
1223+
{
1224+
const auto script{GetScriptForDestination(WitnessV1Taproot{XOnlyPubKey{dummy_pubkey}})};
1225+
BOOST_CHECK_EQUAL(GetTxoutType(script), TxoutType::WITNESS_V1_TAPROOT);
1226+
CHECK_SCRIPT_DYNAMIC_SIZE(script, 34, 34);
1227+
}
1228+
1229+
// Compressed P2PK needs extra allocation
1230+
{
1231+
const auto script{GetScriptForRawPubKey(dummy_pubkey)};
1232+
BOOST_CHECK_EQUAL(GetTxoutType(script), TxoutType::PUBKEY);
1233+
CHECK_SCRIPT_DYNAMIC_SIZE(script, 35, 35);
1234+
}
1235+
1236+
// Uncompressed P2PK needs extra allocation
1237+
{
1238+
CKey uncompressed_key;
1239+
uncompressed_key.MakeNewKey(/*fCompressed=*/false);
1240+
const CPubKey uncompressed_pubkey{uncompressed_key.GetPubKey()};
1241+
1242+
const auto script{GetScriptForRawPubKey(uncompressed_pubkey)};
1243+
BOOST_CHECK_EQUAL(GetTxoutType(script), TxoutType::PUBKEY);
1244+
CHECK_SCRIPT_DYNAMIC_SIZE(script, 67, 67);
1245+
}
1246+
1247+
// Bare multisig needs extra allocation
1248+
{
1249+
const auto script{GetScriptForMultisig(1, std::vector{2, dummy_pubkey})};
1250+
BOOST_CHECK_EQUAL(GetTxoutType(script), TxoutType::MULTISIG);
1251+
CHECK_SCRIPT_DYNAMIC_SIZE(script, 71, 103);
1252+
}
1253+
}
1254+
11541255
/* Wrapper around ProduceSignature to combine two scriptsigs */
11551256
SignatureData CombineSignatures(const CTxOut& txout, const CMutableTransaction& tx, const SignatureData& scriptSig1, const SignatureData& scriptSig2)
11561257
{

0 commit comments

Comments
 (0)