Skip to content

Commit 5196ab1

Browse files
committed
Merge branch 'match_more_datacarrier-28+knots' into datacarriercost-28+knots
2 parents b6ebbae + 424bf6a commit 5196ab1

File tree

10 files changed

+389
-5
lines changed

10 files changed

+389
-5
lines changed

src/init.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -644,9 +644,9 @@ void SetupServerArgs(ArgsManager& argsman)
644644
argsman.AddArg("-bytespersigop", strprintf("Equivalent bytes per sigop in transactions for relay and mining (default: %u)", DEFAULT_BYTES_PER_SIGOP), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
645645
argsman.AddArg("-bytespersigopstrict", strprintf("Minimum bytes per sigop in transactions we relay and mine (default: %u)", DEFAULT_BYTES_PER_SIGOP_STRICT), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
646646
argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
647+
argsman.AddArg("-datacarrierfullcount", strprintf("Apply datacarriersize limit to all known datacarrier methods (default: %u)", DEFAULT_DATACARRIER_FULLCOUNT), ArgsManager::ALLOW_ANY | (DEFAULT_DATACARRIER_FULLCOUNT ? uint32_t{ArgsManager::DEBUG_ONLY} : 0), OptionsCategory::NODE_RELAY);
647648
argsman.AddArg("-datacarriersize",
648-
strprintf("Relay and mine transactions whose data-carrying raw scriptPubKey "
649-
"is of this size or less (default: %u)",
649+
strprintf("Maximum size of data in data carrier transactions we relay and mine, in bytes (default: %u)",
650650
MAX_OP_RETURN_RELAY),
651651
ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
652652
argsman.AddArg("-mempoolfullrbf", strprintf("Accept transaction replace-by-fee without requiring replaceability signaling (default: %u)", (DEFAULT_MEMPOOL_RBF_POLICY == RBFPolicy::Always)), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);

src/kernel/mempool_options.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ struct MemPoolOptions {
5858
* If nullopt, any size is nonstandard.
5959
*/
6060
std::optional<unsigned> max_datacarrier_bytes{DEFAULT_ACCEPT_DATACARRIER ? std::optional{MAX_OP_RETURN_RELAY} : std::nullopt};
61+
bool datacarrier_fullcount{DEFAULT_DATACARRIER_FULLCOUNT};
6162
bool permit_bare_pubkey{DEFAULT_PERMIT_BAREPUBKEY};
6263
bool permit_bare_multisig{DEFAULT_PERMIT_BAREMULTISIG};
6364
bool require_standard{true};

src/node/mempool_args.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ util::Result<void> ApplyArgsManOptions(const ArgsManager& argsman, const CChainP
9090
} else {
9191
mempool_opts.max_datacarrier_bytes = std::nullopt;
9292
}
93+
mempool_opts.datacarrier_fullcount = argsman.GetBoolArg("-datacarrierfullcount", DEFAULT_DATACARRIER_FULLCOUNT);
9394

9495
mempool_opts.require_standard = !argsman.GetBoolArg("-acceptnonstdtxn", DEFAULT_ACCEPT_NON_STD_TXN);
9596
if (!chainparams.IsTestChain() && !mempool_opts.require_standard) {

src/policy/policy.cpp

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,66 @@ int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost, un
372372
{
373373
return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost, bytes_per_sigop);
374374
}
375+
376+
std::pair<CScript, unsigned int> GetScriptForTransactionInput(CScript prevScript, const CTxIn& txin)
377+
{
378+
bool p2sh = false;
379+
if (prevScript.IsPayToScriptHash()) {
380+
std::vector <std::vector<unsigned char> > stack;
381+
if (!EvalScript(stack, txin.scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE)) {
382+
return std::make_pair(CScript(), 0);
383+
}
384+
if (stack.empty()) {
385+
return std::make_pair(CScript(), 0);
386+
}
387+
prevScript = CScript(stack.back().begin(), stack.back().end());
388+
p2sh = true;
389+
}
390+
391+
int witnessversion = 0;
392+
std::vector<unsigned char> witnessprogram;
393+
394+
if (!prevScript.IsWitnessProgram(witnessversion, witnessprogram)) {
395+
// For P2SH, scriptSig is always push-only, so the actual script is only the last stack item
396+
// For non-P2SH, prevScript is likely the real script, but not part of this transaction, and scriptSig could very well be executable, so return the latter instead
397+
return std::make_pair(p2sh ? prevScript : txin.scriptSig, WITNESS_SCALE_FACTOR);
398+
}
399+
400+
Span stack{txin.scriptWitness.stack};
401+
402+
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
403+
if (stack.empty()) return std::make_pair(CScript(), 0); // invalid
404+
auto& script_data = stack.back();
405+
prevScript = CScript(script_data.begin(), script_data.end());
406+
return std::make_pair(prevScript, 1);
407+
}
408+
409+
if (witnessversion == 1 && witnessprogram.size() == WITNESS_V1_TAPROOT_SIZE && !p2sh) {
410+
if (stack.size() >= 2 && !stack.back().empty() && stack.back()[0] == ANNEX_TAG) {
411+
SpanPopBack(stack);
412+
}
413+
if (stack.size() >= 2) {
414+
SpanPopBack(stack); // Ignore control block
415+
prevScript = CScript(stack.back().begin(), stack.back().end());
416+
return std::make_pair(prevScript, 1);
417+
}
418+
}
419+
420+
return std::make_pair(CScript(), 0);
421+
}
422+
423+
size_t DatacarrierBytes(const CTransaction& tx, const CCoinsViewCache& view)
424+
{
425+
size_t ret{0};
426+
427+
for (const CTxIn& txin : tx.vin) {
428+
const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
429+
auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
430+
ret += script.DatacarrierBytes();
431+
}
432+
for (const CTxOut& txout : tx.vout) {
433+
ret += txout.scriptPubKey.DatacarrierBytes();
434+
}
435+
436+
return ret;
437+
}

src/policy/policy.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include <cstdint>
1616
#include <string>
1717
#include <unordered_set>
18+
#include <utility>
1819

1920
class CCoinsViewCache;
2021
class CFeeRate;
@@ -78,6 +79,8 @@ static const bool DEFAULT_ACCEPT_DATACARRIER = true;
7879
* +2 for the pushdata opcodes.
7980
*/
8081
static const unsigned int MAX_OP_RETURN_RELAY = 83;
82+
/** Default for -datacarrierfullcount */
83+
static constexpr bool DEFAULT_DATACARRIER_FULLCOUNT{false};
8184
/**
8285
* An extra transaction can be added to a package, as long as it only has one
8386
* ancestor and is no larger than this. Not really any reason to make this
@@ -185,4 +188,8 @@ static inline int64_t GetVirtualTransactionInputSize(const CTxIn& tx)
185188
return GetVirtualTransactionInputSize(tx, 0, 0);
186189
}
187190

191+
std::pair<CScript, unsigned int> GetScriptForTransactionInput(CScript prevScript, const CTxIn&);
192+
193+
size_t DatacarrierBytes(const CTransaction& tx, const CCoinsViewCache& view);
194+
188195
#endif // BITCOIN_POLICY_POLICY_H

src/script/script.cpp

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,56 @@ bool CScript::HasValidOps() const
303303
return true;
304304
}
305305

306+
size_t CScript::DatacarrierBytes() const
307+
{
308+
size_t counted{0};
309+
opcodetype opcode, last_opcode{OP_INVALIDOPCODE};
310+
std::vector<unsigned char> push_data;
311+
unsigned int inside_noop{0}, inside_conditional{0};
312+
CScript::const_iterator opcode_it = begin(), data_began = begin();
313+
for (CScript::const_iterator it = begin(); it < end(); last_opcode = opcode) {
314+
opcode_it = it;
315+
if (!GetOp(it, opcode, push_data)) {
316+
// Invalid scripts are necessarily all data
317+
return size();
318+
}
319+
320+
if (opcode == OP_IF || opcode == OP_NOTIF) {
321+
++inside_conditional;
322+
} else if (opcode == OP_ENDIF) {
323+
if (!inside_conditional) return size(); // invalid
324+
--inside_conditional;
325+
} else if (opcode == OP_RETURN && !inside_conditional) {
326+
// unconditional OP_RETURN is unspendable
327+
return size();
328+
}
329+
330+
// Match OP_FALSE OP_IF
331+
if (inside_noop) {
332+
switch (opcode) {
333+
case OP_IF: case OP_NOTIF:
334+
++inside_noop;
335+
break;
336+
case OP_ENDIF:
337+
if (0 == --inside_noop) {
338+
counted += it - data_began + 1;
339+
}
340+
break;
341+
default: /* do nothing */;
342+
}
343+
} else if (opcode == OP_IF && last_opcode == OP_FALSE) {
344+
inside_noop = 1;
345+
data_began = opcode_it;
346+
// Match <data> OP_DROP
347+
} else if (opcode <= OP_PUSHDATA4) {
348+
data_began = opcode_it;
349+
} else if (opcode == OP_DROP && last_opcode <= OP_PUSHDATA4) {
350+
counted += it - data_began;
351+
}
352+
}
353+
return counted;
354+
}
355+
306356
bool GetScriptOp(CScriptBase::const_iterator& pc, CScriptBase::const_iterator end, opcodetype& opcodeRet, std::vector<unsigned char>* pvchRet)
307357
{
308358
opcodeRet = OP_INVALIDOPCODE;

src/script/script.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,8 @@ class CScript : public CScriptBase
562562
return (size() > 0 && *begin() == OP_RETURN) || (size() > MAX_SCRIPT_SIZE);
563563
}
564564

565+
size_t DatacarrierBytes() const;
566+
565567
void clear()
566568
{
567569
// The default prevector::clear() does not release memory

0 commit comments

Comments
 (0)