@@ -67,6 +67,10 @@ bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
67
67
return (txout.nValue < GetDustThreshold (txout, dustRelayFeeIn));
68
68
}
69
69
70
+ /* *
71
+ * Note this must assign whichType even if returning false, in case
72
+ * IsStandardTx ignores the "scriptpubkey" rejection.
73
+ */
70
74
bool IsStandard (const CScript& scriptPubKey, const std::optional<unsigned >& max_datacarrier_bytes, TxoutType& whichType)
71
75
{
72
76
std::vector<std::vector<unsigned char > > vSolutions;
@@ -91,11 +95,27 @@ bool IsStandard(const CScript& scriptPubKey, const std::optional<unsigned>& max_
91
95
return true ;
92
96
}
93
97
94
- bool IsStandardTx (const CTransaction& tx, const std::optional<unsigned >& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
98
+ static inline bool MaybeReject_ (std::string& out_reason, const std::string& reason, const std::string& reason_prefix, const ignore_rejects_type& ignore_rejects) {
99
+ if (ignore_rejects.count (reason_prefix + reason)) {
100
+ return false ;
101
+ }
102
+
103
+ out_reason = reason_prefix + reason;
104
+ return true ;
105
+ }
106
+
107
+ #define MaybeReject (reason ) do { \
108
+ if (MaybeReject_ (out_reason, reason, reason_prefix, ignore_rejects)) { \
109
+ return false ; \
110
+ } \
111
+ } while (0 )
112
+
113
+ bool IsStandardTx (const CTransaction& tx, const std::optional<unsigned >& max_datacarrier_bytes, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& out_reason, const ignore_rejects_type& ignore_rejects)
95
114
{
115
+ const std::string reason_prefix;
116
+
96
117
if (tx.version > TX_MAX_STANDARD_VERSION || tx.version < 1 ) {
97
- reason = " version" ;
98
- return false ;
118
+ MaybeReject (" version" );
99
119
}
100
120
101
121
// Extremely large transactions with lots of inputs can cost the network
@@ -104,8 +124,7 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
104
124
// to MAX_STANDARD_TX_WEIGHT mitigates CPU exhaustion attacks.
105
125
unsigned int sz = GetTransactionWeight (tx);
106
126
if (sz > MAX_STANDARD_TX_WEIGHT) {
107
- reason = " tx-size" ;
108
- return false ;
127
+ MaybeReject (" tx-size" );
109
128
}
110
129
111
130
for (const CTxIn& txin : tx.vin )
@@ -119,41 +138,39 @@ bool IsStandardTx(const CTransaction& tx, const std::optional<unsigned>& max_dat
119
138
// 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey
120
139
// is not considered standard.
121
140
if (txin.scriptSig .size () > MAX_STANDARD_SCRIPTSIG_SIZE) {
122
- reason = " scriptsig-size" ;
123
- return false ;
141
+ MaybeReject (" scriptsig-size" );
124
142
}
125
143
if (!txin.scriptSig .IsPushOnly ()) {
126
- reason = " scriptsig-not-pushonly" ;
127
- return false ;
144
+ MaybeReject (" scriptsig-not-pushonly" );
128
145
}
129
146
}
130
147
131
148
unsigned int nDataOut = 0 ;
132
149
TxoutType whichType;
133
150
for (const CTxOut& txout : tx.vout ) {
134
151
if (!::IsStandard (txout.scriptPubKey , max_datacarrier_bytes, whichType)) {
135
- reason = " scriptpubkey" ;
136
152
if (whichType == TxoutType::WITNESS_UNKNOWN) {
137
- reason += " -unknown-witnessversion" ;
153
+ MaybeReject (" scriptpubkey-unknown-witnessversion" );
154
+ } else {
155
+ MaybeReject (" scriptpubkey" );
138
156
}
139
- return false ;
140
157
}
141
158
142
- if (whichType == TxoutType::NULL_DATA)
159
+ if (whichType == TxoutType::NULL_DATA) {
143
160
nDataOut++;
161
+ continue ;
162
+ }
144
163
else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
145
- reason = " bare-multisig" ;
146
- return false ;
147
- } else if (IsDust (txout, dust_relay_fee)) {
148
- reason = " dust" ;
149
- return false ;
164
+ MaybeReject (" bare-multisig" );
165
+ }
166
+ if (IsDust (txout, dust_relay_fee)) {
167
+ MaybeReject (" dust" );
150
168
}
151
169
}
152
170
153
171
// only one OP_RETURN txout is permitted
154
172
if (nDataOut > 1 ) {
155
- reason = " multi-op-return" ;
156
- return false ;
173
+ MaybeReject (" multi-op-return" );
157
174
}
158
175
159
176
return true ;
0 commit comments