Skip to content
Bitcoin Roots

v30.3-roots.1 · Commit 3: [PATCH 03/68] feat(policy): preserve Roots relay and network controls on Core 30.3

src/test/transaction_tests.cpp

Before: src/test/transaction_tests.cpp · After: src/test/transaction_tests.cpp

File metadata
index c0443f3a0a45ef611448379d8d4f026bc83a91a3..c54c13bdbb74ea5e8e1ecfed47aee776714d4047 100644

Download original patch · Release notes

Diff rows 1–235 of 235. 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
@@ -13,6 +13,7 @@
13
  #include <consensus/tx_verify.h>
14
  #include <consensus/validation.h>
15
  #include <core_io.h>
 
16
  #include <key.h>
17
  #include <policy/policy.h>
18
  #include <policy/settings.h>
@@ -46,8 +47,7 @@ using util::ToString;
46
 
47
  typedef std::vector<unsigned char> valtype;
48
 
49
- static CFeeRate g_dust{DUST_RELAY_TX_FEE};
50
- static bool g_bare_multi{DEFAULT_PERMIT_BAREMULTISIG};
51
 
52
  static std::map<std::string, unsigned int> mapFlagNames = {
53
  {std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
@@ -798,21 +798,30 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
798
  CKey key = GenerateRandomKey();
799
  t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
800
 
801
- constexpr auto CheckIsStandard = [](const auto& t, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY) {
802
  std::string reason;
803
- BOOST_CHECK(IsStandardTx(CTransaction{t}, max_op_return_relay, g_bare_multi, g_dust, reason));
 
 
804
  BOOST_CHECK(reason.empty());
805
  };
806
- constexpr auto CheckIsNotStandard = [](const auto& t, const std::string& reason_in, const unsigned int max_op_return_relay = MAX_OP_RETURN_RELAY) {
807
  std::string reason;
808
- BOOST_CHECK(!IsStandardTx(CTransaction{t}, max_op_return_relay, g_bare_multi, g_dust, reason));
 
 
809
  BOOST_CHECK_EQUAL(reason_in, reason);
810
  };
811
 
 
812
  CheckIsStandard(t);
813
 
 
 
 
 
814
  // Check dust with default relay fee:
815
- CAmount nDustThreshold = 182 * g_dust.GetFeePerK() / 1000;
816
  BOOST_CHECK_EQUAL(nDustThreshold, 546);
817
 
818
  // Add dust outputs up to allowed maximum, still standard!
@@ -847,25 +856,66 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
847
 
848
  // Check dust with odd relay fee to verify rounding:
849
  // nDustThreshold = 182 * 3702 / 1000
850
- g_dust = CFeeRate(3702);
851
  // dust:
852
  t.vout[0].nValue = 674 - 1;
853
  CheckIsNotStandard(t, "dust");
854
  // not dust:
855
  t.vout[0].nValue = 674;
856
  CheckIsStandard(t);
857
- g_dust = CFeeRate{DUST_RELAY_TX_FEE};
858
 
859
  t.vout[0].scriptPubKey = CScript() << OP_1;
860
  CheckIsNotStandard(t, "scriptpubkey");
861
 
862
- // Custom 83-byte TxoutType::NULL_DATA (standard with max_op_return_relay of 83)
863
- t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
864
- BOOST_CHECK_EQUAL(83, t.vout[0].scriptPubKey.size());
865
- CheckIsStandard(t, /*max_op_return_relay=*/83);
 
 
 
 
 
 
 
866
 
867
- // Non-standard if max_op_return_relay datacarrier arg is one less
868
- CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/82);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
869
 
870
  // Data payload can be encoded in any way...
871
  t.vout[0].scriptPubKey = CScript() << OP_RETURN << ""_hex;
@@ -887,28 +937,40 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
887
  t.vout[0].scriptPubKey = CScript() << OP_RETURN;
888
  CheckIsStandard(t);
889
 
890
- // Multiple TxoutType::NULL_DATA are permitted
891
  t.vout.resize(2);
892
  t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
893
  t.vout[0].nValue = 0;
894
  t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
895
  t.vout[1].nValue = 0;
896
- CheckIsStandard(t);
 
897
 
898
  t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
899
  t.vout[1].scriptPubKey = CScript() << OP_RETURN;
900
- CheckIsStandard(t);
 
901
 
902
  t.vout[0].scriptPubKey = CScript() << OP_RETURN;
903
  t.vout[1].scriptPubKey = CScript() << OP_RETURN;
904
- CheckIsStandard(t);
 
905
 
906
  t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
907
  t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
908
  const auto datacarrier_size = t.vout[0].scriptPubKey.size() + t.vout[1].scriptPubKey.size();
909
- CheckIsStandard(t); // Default max relay should never trigger
910
- CheckIsStandard(t, /*max_op_return_relay=*/datacarrier_size);
911
- CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/datacarrier_size-1);
 
 
 
 
 
 
 
 
 
912
 
913
  // Check large scriptSig (non-standard if size is >1650 bytes)
914
  t.vout.resize(1);
@@ -971,16 +1033,16 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
971
  BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
972
  CheckIsNotStandard(t, "tx-size");
973
 
974
- // Check bare multisig (standard if policy flag g_bare_multi is set)
975
- g_bare_multi = true;
976
  t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
977
  t.vin.resize(1);
978
  t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
979
  CheckIsStandard(t);
980
 
981
- g_bare_multi = false;
982
  CheckIsNotStandard(t, "bare-multisig");
983
- g_bare_multi = DEFAULT_PERMIT_BAREMULTISIG;
984
 
985
  // Add dust outputs up to allowed maximum
986
  assert(t.vout.size() == 1);
@@ -1039,6 +1101,9 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
1039
  for (int op = OP_1; op <= OP_16; op += 1) {
1040
  t.vout[0].scriptPubKey = CScript() << (opcodetype)op << std::vector<unsigned char>(2, 0);
1041
  t.vout[0].nValue = 240;
 
 
 
1042
  CheckIsStandard(t);
1043
 
1044
  t.vout[0].nValue = 239;
@@ -1052,6 +1117,34 @@ BOOST_AUTO_TEST_CASE(test_IsStandard)
1052
  CheckIsStandard(t);
1053
  t.vout[0].nValue = 239;
1054
  CheckIsNotStandard(t, "dust");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1055
  }
1056
 
1057
  BOOST_AUTO_TEST_CASE(max_standard_legacy_sigops)
 
13
  #include <consensus/tx_verify.h>
14
  #include <consensus/validation.h>
15
  #include <core_io.h>
16
+ #include <kernel/mempool_options.h>
17
  #include <key.h>
18
  #include <policy/policy.h>
19
  #include <policy/settings.h>
 
47
 
48
  typedef std::vector<unsigned char> valtype;
49
 
50
+ static kernel::MemPoolOptions g_mempool_opts;
 
51
 
52
  static std::map<std::string, unsigned int> mapFlagNames = {
53
  {std::string("P2SH"), (unsigned int)SCRIPT_VERIFY_P2SH},
 
798
  CKey key = GenerateRandomKey();
799
  t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
800
 
801
+ 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) {
802
  std::string reason;
803
+ auto opts = g_mempool_opts;
804
+ opts.max_datacarrier_bytes = max_op_return_relay;
805
+ BOOST_CHECK(IsStandardTx(CTransaction{t}, opts, reason, ignore_rejects));
806
  BOOST_CHECK(reason.empty());
807
  };
808
+ 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) {
809
  std::string reason;
810
+ auto opts = g_mempool_opts;
811
+ opts.max_datacarrier_bytes = max_op_return_relay;
812
+ BOOST_CHECK(!IsStandardTx(CTransaction{t}, opts, reason, ignore_rejects));
813
  BOOST_CHECK_EQUAL(reason_in, reason);
814
  };
815
 
816
+ g_mempool_opts.permit_bare_pubkey = true;
817
  CheckIsStandard(t);
818
 
819
+ g_mempool_opts.permitephemeral_anchor = true;
820
+ g_mempool_opts.permitephemeral_dust = true;
821
+ g_mempool_opts.permitephemeral_send = true;
822
+
823
  // Check dust with default relay fee:
824
+ CAmount nDustThreshold = 182 * g_mempool_opts.dust_relay_feerate.GetFeePerK() / 1000;
825
  BOOST_CHECK_EQUAL(nDustThreshold, 546);
826
 
827
  // Add dust outputs up to allowed maximum, still standard!
 
856
 
857
  // Check dust with odd relay fee to verify rounding:
858
  // nDustThreshold = 182 * 3702 / 1000
859
+ g_mempool_opts.dust_relay_feerate = CFeeRate(3702);
860
  // dust:
861
  t.vout[0].nValue = 674 - 1;
862
  CheckIsNotStandard(t, "dust");
863
  // not dust:
864
  t.vout[0].nValue = 674;
865
  CheckIsStandard(t);
866
+ g_mempool_opts.dust_relay_feerate = CFeeRate{DUST_RELAY_TX_FEE};
867
 
868
  t.vout[0].scriptPubKey = CScript() << OP_1;
869
  CheckIsNotStandard(t, "scriptpubkey");
870
 
871
+ // Test rejectparasites
872
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN;
873
+ t.vout.emplace_back(674, GetScriptForDestination(PKHash(key.GetPubKey())));
874
+ t.nLockTime = 21;
875
+ g_mempool_opts.reject_parasites = false;
876
+ CheckIsStandard(t);
877
+ g_mempool_opts.reject_parasites = true;
878
+ CheckIsNotStandard(t, "parasite-cat21");
879
+ t.nLockTime = 0;
880
+ CheckIsStandard(t);
881
+ g_mempool_opts.reject_parasites = false;
882
 
883
+ // Test rejecttokens
884
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_13 << OP_FALSE;
885
+ g_mempool_opts.reject_tokens = false;
886
+ CheckIsStandard(t);
887
+ g_mempool_opts.reject_tokens = true;
888
+ CheckIsNotStandard(t, "tokens-runes");
889
+ // At least one data push is needed after OP_13 to match
890
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN << OP_13;
891
+ CheckIsStandard(t);
892
+ // Test rejecttokens applying to OLGA
893
+ const auto olga_header = CScript() << OP_0 << "003e7374616d703a000000000000000000000000000000000000000000000000"_hex;
894
+ t.vout[0].scriptPubKey = olga_header;
895
+ t.vout.resize(1);
896
+ // Missing a second output, so not OLGA
897
+ CheckIsStandard(t);
898
+ t.vout.emplace_back(1000, olga_header);
899
+ CheckIsNotStandard(t, "tokens-olga");
900
+ t.vout.emplace_back(1000, olga_header);
901
+ CheckIsNotStandard(t, "tokens-olga");
902
+ g_mempool_opts.reject_tokens = false;
903
+ CheckIsStandard(t);
904
+ t.vout.resize(1);
905
+
906
+ // MAX_OP_RETURN_RELAY-byte TxoutType::NULL_DATA (standard)
907
+ g_mempool_opts.permitbaredatacarrier = true;
908
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN;
909
+ while (t.vout[0].scriptPubKey.size() < MAX_OP_RETURN_RELAY) {
910
+ t.vout[0].scriptPubKey << OP_0;
911
+ }
912
+ BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY, t.vout[0].scriptPubKey.size());
913
+ CheckIsStandard(t);
914
+
915
+ // MAX_OP_RETURN_RELAY+1-byte TxoutType::NULL_DATA (non-standard)
916
+ t.vout[0].scriptPubKey << OP_0;
917
+ BOOST_CHECK_EQUAL(MAX_OP_RETURN_RELAY + 1, t.vout[0].scriptPubKey.size());
918
+ CheckIsNotStandard(t, "datacarrier");
919
 
920
  // Data payload can be encoded in any way...
921
  t.vout[0].scriptPubKey = CScript() << OP_RETURN << ""_hex;
 
937
  t.vout[0].scriptPubKey = CScript() << OP_RETURN;
938
  CheckIsStandard(t);
939
 
940
+ // Multiple carriers require an explicit local policy relaxation
941
  t.vout.resize(2);
942
  t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
943
  t.vout[0].nValue = 0;
944
  t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
945
  t.vout[1].nValue = 0;
946
+ CheckIsNotStandard(t, "multi-op-return", MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR);
947
+ CheckIsStandard(t, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR, {"multi-op-return"});
948
 
949
  t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
950
  t.vout[1].scriptPubKey = CScript() << OP_RETURN;
951
+ CheckIsNotStandard(t, "multi-op-return", MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR);
952
+ CheckIsStandard(t, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR, {"multi-op-return"});
953
 
954
  t.vout[0].scriptPubKey = CScript() << OP_RETURN;
955
  t.vout[1].scriptPubKey = CScript() << OP_RETURN;
956
+ CheckIsNotStandard(t, "multi-op-return", MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR);
957
+ CheckIsStandard(t, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR, {"multi-op-return"});
958
 
959
  t.vout[0].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
960
  t.vout[1].scriptPubKey = CScript() << OP_RETURN << "04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef3804678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38"_hex;
961
  const auto datacarrier_size = t.vout[0].scriptPubKey.size() + t.vout[1].scriptPubKey.size();
962
+ CheckIsNotStandard(t, "datacarrier");
963
+ CheckIsStandard(t, MAX_STANDARD_TX_WEIGHT / WITNESS_SCALE_FACTOR, {"multi-op-return"}); // Explicit generous aggregate limit
964
+ CheckIsStandard(t, /*max_op_return_relay=*/datacarrier_size, {"multi-op-return"});
965
+ CheckIsNotStandard(t, "datacarrier", /*max_op_return_relay=*/datacarrier_size-1, {"multi-op-return"});
966
+
967
+ // Bare carrier transactions still require explicit permission.
968
+ t.vout.resize(1);
969
+ t.vout[0].scriptPubKey = CScript() << OP_RETURN;
970
+ g_mempool_opts.permitbaredatacarrier = false;
971
+ CheckIsNotStandard(t, "bare-datacarrier");
972
+ g_mempool_opts.permitbaredatacarrier = true;
973
+ CheckIsStandard(t);
974
 
975
  // Check large scriptSig (non-standard if size is >1650 bytes)
976
  t.vout.resize(1);
 
1033
  BOOST_CHECK_EQUAL(GetTransactionWeight(CTransaction(t)), 400004);
1034
  CheckIsNotStandard(t, "tx-size");
1035
 
1036
+ // Check bare multisig (standard if the policy flag is set)
1037
+ g_mempool_opts.permit_bare_multisig = true;
1038
  t.vout[0].scriptPubKey = GetScriptForMultisig(1, {key.GetPubKey()}); // simple 1-of-1
1039
  t.vin.resize(1);
1040
  t.vin[0].scriptSig = CScript() << std::vector<unsigned char>(65, 0);
1041
  CheckIsStandard(t);
1042
 
1043
+ g_mempool_opts.permit_bare_multisig = false;
1044
  CheckIsNotStandard(t, "bare-multisig");
1045
+ g_mempool_opts.permit_bare_multisig = true;
1046
 
1047
  // Add dust outputs up to allowed maximum
1048
  assert(t.vout.size() == 1);
 
1101
  for (int op = OP_1; op <= OP_16; op += 1) {
1102
  t.vout[0].scriptPubKey = CScript() << (opcodetype)op << std::vector<unsigned char>(2, 0);
1103
  t.vout[0].nValue = 240;
1104
+ g_mempool_opts.acceptunknownwitness = false;
1105
+ CheckIsNotStandard(t, "scriptpubkey-unknown-witnessversion");
1106
+ g_mempool_opts.acceptunknownwitness = true;
1107
  CheckIsStandard(t);
1108
 
1109
  t.vout[0].nValue = 239;
 
1117
  CheckIsStandard(t);
1118
  t.vout[0].nValue = 239;
1119
  CheckIsNotStandard(t, "dust");
1120
+
1121
+ // Test permitbareanchor
1122
+ g_mempool_opts.permitbareanchor = false;
1123
+ t.vout[1].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
1124
+ t.vout[1].nValue = COIN;
1125
+ CheckIsStandard(t);
1126
+ t.vout.resize(1);
1127
+ CheckIsNotStandard(t, "bare-anchor");
1128
+ g_mempool_opts.permitbareanchor = true;
1129
+ CheckIsStandard(t);
1130
+
1131
+ // Test permitephemeral
1132
+ g_mempool_opts.permitephemeral_anchor = false;
1133
+ CheckIsNotStandard(t, "anchor");
1134
+ t.vout[0].nValue = 0;
1135
+ CheckIsNotStandard(t, "anchor");
1136
+ g_mempool_opts.permitephemeral_anchor = true;
1137
+ g_mempool_opts.permitephemeral_dust = false;
1138
+ CheckIsStandard(t);
1139
+ t.vout[0].nValue = 1;
1140
+ CheckIsNotStandard(t, "dust-nonzero");
1141
+ g_mempool_opts.permitephemeral_dust = true;
1142
+ g_mempool_opts.permitephemeral_send = false;
1143
+ CheckIsStandard(t);
1144
+ t.vout[0].scriptPubKey = GetScriptForDestination(PKHash(key.GetPubKey()));
1145
+ CheckIsNotStandard(t, "dust-nonanchor");
1146
+ g_mempool_opts.permitephemeral_send = true;
1147
+ CheckIsStandard(t);
1148
  }
1149
 
1150
  BOOST_AUTO_TEST_CASE(max_standard_legacy_sigops)