v31.1-roots.1 · Commit 2: [PATCH 02/17] feat(policy): preserve Roots parsing and local transaction checks
src/test/transaction_tests.cpp
Before: src/test/transaction_tests.cpp · After: src/test/transaction_tests.cpp
File metadata
index 916f565c04df41b909ad35e50b917cdb04caaa4f..4db01b19c3d6bfe187f78cac51c09f832b335c93 100644
Download original patch · Release notes
Diff rows 1–291 of 291. Line numbers refer to the original before/after files.
+ Added− RemovedUnmarked lines are context.
Scroll the code area horizontally to read long lines. Before is on the left; after is on the right. Unified view fits narrow screens more easily.
src/test/transaction_tests.cpp
CHANGED
|
@@ -14,6 +14,7 @@
|
|
| 14 |
#include <consensus/tx_verify.h>
|
| 15 |
#include <consensus/validation.h>
|
| 16 |
#include <core_io.h>
|
|
|
|
| 17 |
#include <key.h>
|
| 18 |
#include <policy/policy.h>
|
| 19 |
#include <policy/settings.h>
|
|
@@ -49,8 +50,8 @@ using util::ToString;
|
|
| 49 |
|
| 50 |
typedef std::vector<unsigned char> valtype;
|
| 51 |
|
| 52 |
-
static CFeeRate g_dust{DUST_RELAY_TX_FEE};
|
| 53 |
-
static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
|
| 54 |
|
| 55 |
static const std::map<std::string, script_verify_flag_name>& mapFlagNames = ScriptFlagNamesToEnum();
|
| 56 |
|
|
@@ -764,21 +765,30 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|
| 764 |
CKey key = GenerateRandomKey();
|
| 765 |
t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
|
| 766 |
|
| 767 |
-
constexpr auto CheckIsStandard = [](const auto& t, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY) {
|
| 768 |
std::string reason;
|
| 769 |
-
BOOST_CHECK(IsStandardTx(CTransaction{t}, max_op_return_relay, g_bare_multi, g_dust, reason));
|
|
|
|
|
|
|
| 770 |
BOOST_CHECK(reason.empty());
|
| 771 |
};
|
| 772 |
-
constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY) {
|
| 773 |
std::string reason;
|
| 774 |
-
BOOST_CHECK(!IsStandardTx(CTransaction{t}, max_op_return_relay, g_bare_multi, g_dust, reason));
|
|
|
|
|
|
|
| 775 |
BOOST_CHECK_EQUAL(reason_in, reason);
|
| 776 |
};
|
| 777 |
|
|
|
|
| 778 |
CheckIsStandard(t);
|
| 779 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 780 |
// Check dust with default relay fee:
|
| 781 |
-
CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;
|
| 782 |
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
| 783 |
|
| 784 |
// Add dust outputs up to allowed maximum, still standard!
|
|
@@ -813,25 +823,66 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|
| 813 |
|
| 814 |
// Check dust with odd relay fee to verify rounding:
|
| 815 |
// nDustThreshold = 182 * 3702 / 1000
|
| 816 |
-
g_dust = CFeeRate(3702);
|
| 817 |
// dust:
|
| 818 |
t.vout[0].nValue = 674 - 1;
|
| 819 |
CheckIsNotStandard(t, "dust");
|
| 820 |
// not dust:
|
| 821 |
t.vout[0].nValue = 674;
|
| 822 |
CheckIsStandard(t);
|
| 823 |
-
g_dust = CFeeRate{DUST_RELAY_TX_FEE};
|
| 824 |
|
| 825 |
t.vout[0].scriptPubKey = CScript() << OP_1;
|
| 826 |
CheckIsNotStandard(t, "scriptpubkey");
|
| 827 |
|
| 828 |
-
// Custom 83-byte TxoutType::NULL_DATA (standard with max_op_return_relay of 83)
|
| 829 |
-
t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 830 |
-
BOOST_CHECK_EQUAL(83, t.vout[0].scriptPubKey.size());
|
| 831 |
-
CheckIsStandard(t, /*max_op_return_relay=*/83);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 832 |
|
| 833 |
-
// Non-standard if max_op_return_relay datacarrier arg is one less
|
| 834 |
-
CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/82);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 835 |
|
| 836 |
// Data payload can be encoded in any way...
|
| 837 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ""_hex;
|
|
@@ -853,28 +904,40 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|
| 853 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
| 854 |
CheckIsStandard(t);
|
| 855 |
|
| 856 |
-
// Multiple TxoutType::NULL_DATA are permitted
|
| 857 |
t.vout.resize(2);
|
| 858 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 859 |
t.vout[0].nValue = 0;
|
| 860 |
t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 861 |
t.vout[1].nValue = 0;
|
| 862 |
-
CheckIsStandard(t);
|
|
|
|
| 863 |
|
| 864 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 865 |
t.vout[1].scriptPubKey = CScript() << OP_RETURN;
|
| 866 |
-
CheckIsStandard(t);
|
|
|
|
| 867 |
|
| 868 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
| 869 |
t.vout[1].scriptPubKey = CScript() << OP_RETURN;
|
| 870 |
-
CheckIsStandard(t);
|
|
|
|
| 871 |
|
| 872 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 873 |
t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 874 |
const auto datacarrier_size = t.vout[0].scriptPubKey.size() + t.vout[1].scriptPubKey.size();
|
| 875 |
-
CheckIsStandard(t); // Default max relay should never trigger
|
| 876 |
-
CheckIsStandard(t, /*max_op_return_relay=*/datacarrier_size);
|
| 877 |
-
CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/datacarrier_size-1);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 878 |
|
| 879 |
// Check large scriptSig (non-standard if size is >1650 bytes)
|
| 880 |
t.vout.resize(1);
|
|
@@ -937,16 +1000,16 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|
| 937 |
BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
|
| 938 |
CheckIsNotStandard(t, "tx-size");
|
| 939 |
|
| 940 |
-
// Check bare multisig (standard if policy flag g_bare_multi is set)
|
| 941 |
-
g_bare_multi = true;
|
| 942 |
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
|
| 943 |
t.vin.resize(1);
|
| 944 |
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
|
| 945 |
CheckIsStandard(t);
|
| 946 |
|
| 947 |
-
g_bare_multi = false;
|
| 948 |
CheckIsNotStandard(t, "bare-multisig");
|
| 949 |
-
g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;
|
| 950 |
|
| 951 |
// Add dust outputs up to allowed maximum
|
| 952 |
assert(t.vout.size() == 1);
|
|
@@ -1005,6 +1068,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|
| 1005 |
for (int op = OP_1; op <= OP_16; op += 1) {
|
| 1006 |
t.vout[0].scriptPubKey = CScript() << (opcodetype)op << std::vector<unsigned char>(2, 0);
|
| 1007 |
t.vout[0].nValue = 240;
|
|
|
|
|
|
|
|
|
|
| 1008 |
CheckIsStandard(t);
|
| 1009 |
|
| 1010 |
t.vout[0].nValue = 239;
|
|
@@ -1018,6 +1084,34 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
|
|
| 1018 |
CheckIsStandard(t);
|
| 1019 |
t.vout[0].nValue = 239;
|
| 1020 |
CheckIsNotStandard(t, "dust");
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1021 |
}
|
| 1022 |
|
| 1023 |
BOOST_AUTO_TEST_CASE(max_standard_legacy_sigops)
|
|
@@ -1115,55 +1209,6 @@ BOOST_AUTO_TEST_CASE(max_standard_legacy_sigops)
|
|
| 1115 |
BOOST_CHECK(!::AreInputsStandard(CTransaction(tx_max_sigops), coins));
|
| 1116 |
}
|
| 1117 |
|
| 1118 |
-
BOOST_AUTO_TEST_CASE(checktxinputs_invalid_transactions_test)
|
| 1119 |
-
{
|
| 1120 |
-
auto check_invalid{[](CAmount input_value, CAmount output_value, bool coinbase, int spend_height, TxValidationResult expected_result, std::string_view expected_reason) {
|
| 1121 |
-
CCoinsView coins_dummy;
|
| 1122 |
-
CCoinsViewCache inputs(&coins_dummy);
|
| 1123 |
-
|
| 1124 |
-
const COutPoint prevout{Txid::FromUint256(uint256::ONE), 0};
|
| 1125 |
-
inputs.AddCoin(prevout, Coin{{input_value, CScript() << OP_TRUE}, /*nHeightIn=*/1, coinbase}, /*possible_overwrite=*/false);
|
| 1126 |
-
|
| 1127 |
-
CMutableTransaction mtx;
|
| 1128 |
-
mtx.vin.emplace_back(prevout);
|
| 1129 |
-
mtx.vout.emplace_back(output_value, CScript() << OP_TRUE);
|
| 1130 |
-
|
| 1131 |
-
TxValidationState state;
|
| 1132 |
-
CAmount txfee{0};
|
| 1133 |
-
BOOST_CHECK(!Consensus::CheckTxInputs(CTransaction{mtx}, state, inputs, spend_height, txfee));
|
| 1134 |
-
BOOST_CHECK(state.IsInvalid());
|
| 1135 |
-
BOOST_CHECK_EQUAL(state.GetResult(), expected_result);
|
| 1136 |
-
BOOST_CHECK_EQUAL(state.GetRejectReason(), expected_reason);
|
| 1137 |
-
}};
|
| 1138 |
-
|
| 1139 |
-
check_invalid(/*input_value=*/MAX_MONEY + 1,
|
| 1140 |
-
/*output_value=*/0,
|
| 1141 |
-
/*coinbase=*/false,
|
| 1142 |
-
/*spend_height=*/2,
|
| 1143 |
-
TxValidationResult::TX_CONSENSUS, /*expected_reason=*/"bad-txns-inputvalues-outofrange");
|
| 1144 |
-
|
| 1145 |
-
check_invalid(/*input_value=*/1 * COIN,
|
| 1146 |
-
/*output_value=*/2 * COIN,
|
| 1147 |
-
/*coinbase=*/false,
|
| 1148 |
-
/*spend_height=*/2,
|
| 1149 |
-
TxValidationResult::TX_CONSENSUS, /*expected_reason=*/"bad-txns-in-belowout");
|
| 1150 |
-
|
| 1151 |
-
check_invalid(/*input_value=*/1 * COIN,
|
| 1152 |
-
/*output_value=*/0,
|
| 1153 |
-
/*coinbase=*/true,
|
| 1154 |
-
/*spend_height=*/COINBASE_MATURITY,
|
| 1155 |
-
TxValidationResult::TX_PREMATURE_SPEND, /*expected_reason=*/"bad-txns-premature-spend-of-coinbase");
|
| 1156 |
-
}
|
| 1157 |
-
|
| 1158 |
-
BOOST_AUTO_TEST_CASE(getvalueout_out_of_range_throws)
|
| 1159 |
-
{
|
| 1160 |
-
CMutableTransaction mtx;
|
| 1161 |
-
mtx.vout.emplace_back(MAX_MONEY + 1, CScript() << OP_TRUE);
|
| 1162 |
-
|
| 1163 |
-
const CTransaction tx{mtx};
|
| 1164 |
-
BOOST_CHECK_EXCEPTION(tx.GetValueOut(), std::runtime_error, HasReason("GetValueOut: value out of range"));
|
| 1165 |
-
}
|
| 1166 |
-
|
| 1167 |
/** Sanity check the return value of SpendsNonAnchorWitnessProg for various output types. */
|
| 1168 |
BOOST_AUTO_TEST_CASE(spends_witness_prog)
|
| 1169 |
{
|
|
|
|
| 14 |
#include <consensus/tx_verify.h>
|
| 15 |
#include <consensus/validation.h>
|
| 16 |
#include <core_io.h>
|
| 17 |
+
#include <kernel/mempool_options.h>
|
| 18 |
#include <key.h>
|
| 19 |
#include <policy/policy.h>
|
| 20 |
#include <policy/settings.h>
|
|
|
|
| 50 |
|
| 51 |
typedef std::vector<unsigned char> valtype;
|
| 52 |
|
| 53 |
+
|
| 54 |
+
static kernel::MemPoolOptions g_mempool_opts;
|
| 55 |
|
| 56 |
static const std::map<std::string, script_verify_flag_name>& mapFlagNames = ScriptFlagNamesToEnum();
|
| 57 |
|
|
|
|
| 765 |
CKey key = GenerateRandomKey();
|
| 766 |
t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
|
| 767 |
|
| 768 |
+
constexpr auto CheckIsStandard = [](const auto& t, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY, const ignore_rejects_type& ignore_rejects = empty_ignore_rejects) {
|
| 769 |
std::string reason;
|
| 770 |
+
auto opts = g_mempool_opts;
|
| 771 |
+
opts.max_datacarrier_bytes = max_op_return_relay;
|
| 772 |
+
BOOST_CHECK(IsStandardTx(CTransaction{t}, opts, reason, ignore_rejects));
|
| 773 |
BOOST_CHECK(reason.empty());
|
| 774 |
};
|
| 775 |
+
constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY, const ignore_rejects_type& ignore_rejects = empty_ignore_rejects) {
|
| 776 |
std::string reason;
|
| 777 |
+
auto opts = g_mempool_opts;
|
| 778 |
+
opts.max_datacarrier_bytes = max_op_return_relay;
|
| 779 |
+
BOOST_CHECK(!IsStandardTx(CTransaction{t}, opts, reason, ignore_rejects));
|
| 780 |
BOOST_CHECK_EQUAL(reason_in, reason);
|
| 781 |
};
|
| 782 |
|
| 783 |
+
g_mempool_opts.permit_bare_pubkey = true;
|
| 784 |
CheckIsStandard(t);
|
| 785 |
|
| 786 |
+
g_mempool_opts.permitephemeral_anchor = true;
|
| 787 |
+
g_mempool_opts.permitephemeral_dust = true;
|
| 788 |
+
g_mempool_opts.permitephemeral_send = true;
|
| 789 |
+
|
| 790 |
// Check dust with default relay fee:
|
| 791 |
+
CAmount nDustThreshold = 182 * g_mempool_opts.dust_relay_feerate.GetFeePerK() / 1000;
|
| 792 |
BOOST_CHECK_EQUAL(nDustThreshold, 546);
|
| 793 |
|
| 794 |
// Add dust outputs up to allowed maximum, still standard!
|
|
|
|
| 823 |
|
| 824 |
// Check dust with odd relay fee to verify rounding:
|
| 825 |
// nDustThreshold = 182 * 3702 / 1000
|
| 826 |
+
g_mempool_opts.dust_relay_feerate = CFeeRate(3702);
|
| 827 |
// dust:
|
| 828 |
t.vout[0].nValue = 674 - 1;
|
| 829 |
CheckIsNotStandard(t, "dust");
|
| 830 |
// not dust:
|
| 831 |
t.vout[0].nValue = 674;
|
| 832 |
CheckIsStandard(t);
|
| 833 |
+
g_mempool_opts.dust_relay_feerate = CFeeRate{DUST_RELAY_TX_FEE};
|
| 834 |
|
| 835 |
t.vout[0].scriptPubKey = CScript() << OP_1;
|
| 836 |
CheckIsNotStandard(t, "scriptpubkey");
|
| 837 |
|
| 838 |
+
// Test rejectparasites
|
| 839 |
+
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
| 840 |
+
t.vout.emplace_back(674, GetScriptForDestination(PKHash(key.GetPubKey())));
|
| 841 |
+
t.nLockTime = PARASITE_CAT21_LOCKTIME;
|
| 842 |
+
g_mempool_opts.reject_parasites = false;
|
| 843 |
+
CheckIsStandard(t);
|
| 844 |
+
g_mempool_opts.reject_parasites = true;
|
| 845 |
+
CheckIsNotStandard(t, "parasite-cat21");
|
| 846 |
+
t.nLockTime = 0;
|
| 847 |
+
CheckIsStandard(t);
|
| 848 |
+
g_mempool_opts.reject_parasites = false;
|
| 849 |
|
| 850 |
+
// Test rejecttokens
|
| 851 |
+
t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_13 << OP_FALSE;
|
| 852 |
+
g_mempool_opts.reject_tokens = false;
|
| 853 |
+
CheckIsStandard(t);
|
| 854 |
+
g_mempool_opts.reject_tokens = true;
|
| 855 |
+
CheckIsNotStandard(t, "tokens-runes");
|
| 856 |
+
// At least one data push is needed after OP_13 to match
|
| 857 |
+
t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_13;
|
| 858 |
+
CheckIsStandard(t);
|
| 859 |
+
// Test rejecttokens applying to OLGA
|
| 860 |
+
const auto olga_header = CScript() << OP_0 << "003e7374616d703a000000000000000000000000000000000000000000000000"_hex;
|
| 861 |
+
t.vout[0].scriptPubKey = olga_header;
|
| 862 |
+
t.vout.resize(1);
|
| 863 |
+
// Missing a second output, so not OLGA
|
| 864 |
+
CheckIsStandard(t);
|
| 865 |
+
t.vout.emplace_back(1000, olga_header);
|
| 866 |
+
CheckIsNotStandard(t, "tokens-olga");
|
| 867 |
+
t.vout.emplace_back(1000, olga_header);
|
| 868 |
+
CheckIsNotStandard(t, "tokens-olga");
|
| 869 |
+
g_mempool_opts.reject_tokens = false;
|
| 870 |
+
CheckIsStandard(t);
|
| 871 |
+
t.vout.resize(1);
|
| 872 |
+
|
| 873 |
+
// MAX_OP_RETURN_RELAY-byte TxoutType::NULL_DATA (standard)
|
| 874 |
+
g_mempool_opts.permitbaredatacarrier = true;
|
| 875 |
+
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
| 876 |
+
while (t.vout[0].scriptPubKey.size() < MAX_OP_RETURN_RELAY) {
|
| 877 |
+
t.vout[0].scriptPubKey << OP_0;
|
| 878 |
+
}
|
| 879 |
+
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
|
| 880 |
+
CheckIsStandard(t);
|
| 881 |
+
|
| 882 |
+
// MAX_OP_RETURN_RELAY+1-byte TxoutType::NULL_DATA (non-standard)
|
| 883 |
+
t.vout[0].scriptPubKey << OP_0;
|
| 884 |
+
BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
|
| 885 |
+
CheckIsNotStandard(t, "datacarrier");
|
| 886 |
|
| 887 |
// Data payload can be encoded in any way...
|
| 888 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN << ""_hex;
|
|
|
|
| 904 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
| 905 |
CheckIsStandard(t);
|
| 906 |
|
| 907 |
+
// Multiple carriers require an explicit local policy relaxation
|
| 908 |
t.vout.resize(2);
|
| 909 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 910 |
t.vout[0].nValue = 0;
|
| 911 |
t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 912 |
t.vout[1].nValue = 0;
|
| 913 |
+
CheckIsNotStandard(t, "multi-op-return", MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR);
|
| 914 |
+
CheckIsStandard(t, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR, {"multi-op-return"});
|
| 915 |
|
| 916 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 917 |
t.vout[1].scriptPubKey = CScript() << OP_RETURN;
|
| 918 |
+
CheckIsNotStandard(t, "multi-op-return", MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR);
|
| 919 |
+
CheckIsStandard(t, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR, {"multi-op-return"});
|
| 920 |
|
| 921 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
| 922 |
t.vout[1].scriptPubKey = CScript() << OP_RETURN;
|
| 923 |
+
CheckIsNotStandard(t, "multi-op-return", MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR);
|
| 924 |
+
CheckIsStandard(t, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR, {"multi-op-return"});
|
| 925 |
|
| 926 |
t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 927 |
t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
|
| 928 |
const auto datacarrier_size = t.vout[0].scriptPubKey.size() + t.vout[1].scriptPubKey.size();
|
| 929 |
+
CheckIsNotStandard(t, "datacarrier");
|
| 930 |
+
CheckIsStandard(t, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR, {"multi-op-return"}); // Explicit generous aggregate limit
|
| 931 |
+
CheckIsStandard(t, /*max_op_return_relay=*/datacarrier_size, {"multi-op-return"});
|
| 932 |
+
CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/datacarrier_size-1, {"multi-op-return"});
|
| 933 |
+
|
| 934 |
+
// Bare carrier transactions still require explicit permission.
|
| 935 |
+
t.vout.resize(1);
|
| 936 |
+
t.vout[0].scriptPubKey = CScript() << OP_RETURN;
|
| 937 |
+
g_mempool_opts.permitbaredatacarrier = false;
|
| 938 |
+
CheckIsNotStandard(t, "bare-datacarrier");
|
| 939 |
+
g_mempool_opts.permitbaredatacarrier = true;
|
| 940 |
+
CheckIsStandard(t);
|
| 941 |
|
| 942 |
// Check large scriptSig (non-standard if size is >1650 bytes)
|
| 943 |
t.vout.resize(1);
|
|
|
|
| 1000 |
BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
|
| 1001 |
CheckIsNotStandard(t, "tx-size");
|
| 1002 |
|
| 1003 |
+
// Check bare multisig (standard if the policy flag is set)
|
| 1004 |
+
g_mempool_opts.permit_bare_multisig = true;
|
| 1005 |
t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
|
| 1006 |
t.vin.resize(1);
|
| 1007 |
t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
|
| 1008 |
CheckIsStandard(t);
|
| 1009 |
|
| 1010 |
+
g_mempool_opts.permit_bare_multisig = false;
|
| 1011 |
CheckIsNotStandard(t, "bare-multisig");
|
| 1012 |
+
g_mempool_opts.permit_bare_multisig = true;
|
| 1013 |
|
| 1014 |
// Add dust outputs up to allowed maximum
|
| 1015 |
assert(t.vout.size() == 1);
|
|
|
|
| 1068 |
for (int op = OP_1; op <= OP_16; op += 1) {
|
| 1069 |
t.vout[0].scriptPubKey = CScript() << (opcodetype)op << std::vector<unsigned char>(2, 0);
|
| 1070 |
t.vout[0].nValue = 240;
|
| 1071 |
+
g_mempool_opts.acceptunknownwitness = false;
|
| 1072 |
+
CheckIsNotStandard(t, "scriptpubkey-unknown-witnessversion");
|
| 1073 |
+
g_mempool_opts.acceptunknownwitness = true;
|
| 1074 |
CheckIsStandard(t);
|
| 1075 |
|
| 1076 |
t.vout[0].nValue = 239;
|
|
|
|
| 1084 |
CheckIsStandard(t);
|
| 1085 |
t.vout[0].nValue = 239;
|
| 1086 |
CheckIsNotStandard(t, "dust");
|
| 1087 |
+
|
| 1088 |
+
// Test permitbareanchor
|
| 1089 |
+
g_mempool_opts.permitbareanchor = false;
|
| 1090 |
+
t.vout[1].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
|
| 1091 |
+
t.vout[1].nValue = COIN;
|
| 1092 |
+
CheckIsStandard(t);
|
| 1093 |
+
t.vout.resize(1);
|
| 1094 |
+
CheckIsNotStandard(t, "bare-anchor");
|
| 1095 |
+
g_mempool_opts.permitbareanchor = true;
|
| 1096 |
+
CheckIsStandard(t);
|
| 1097 |
+
|
| 1098 |
+
// Test permitephemeral
|
| 1099 |
+
g_mempool_opts.permitephemeral_anchor = false;
|
| 1100 |
+
CheckIsNotStandard(t, "anchor");
|
| 1101 |
+
t.vout[0].nValue = 0;
|
| 1102 |
+
CheckIsNotStandard(t, "anchor");
|
| 1103 |
+
g_mempool_opts.permitephemeral_anchor = true;
|
| 1104 |
+
g_mempool_opts.permitephemeral_dust = false;
|
| 1105 |
+
CheckIsStandard(t);
|
| 1106 |
+
t.vout[0].nValue = 1;
|
| 1107 |
+
CheckIsNotStandard(t, "dust-nonzero");
|
| 1108 |
+
g_mempool_opts.permitephemeral_dust = true;
|
| 1109 |
+
g_mempool_opts.permitephemeral_send = false;
|
| 1110 |
+
CheckIsStandard(t);
|
| 1111 |
+
t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
|
| 1112 |
+
CheckIsNotStandard(t, "dust-nonanchor");
|
| 1113 |
+
g_mempool_opts.permitephemeral_send = true;
|
| 1114 |
+
CheckIsStandard(t);
|
| 1115 |
}
|
| 1116 |
|
| 1117 |
BOOST_AUTO_TEST_CASE(max_standard_legacy_sigops)
|
|
|
|
| 1209 |
BOOST_CHECK(!::AreInputsStandard(CTransaction(tx_max_sigops), coins));
|
| 1210 |
}
|
| 1211 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1212 |
/** Sanity check the return value of SpendsNonAnchorWitnessProg for various output types. */
|
| 1213 |
BOOST_AUTO_TEST_CASE(spends_witness_prog)
|
| 1214 |
{
|