Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions doc/release-notes-dead-branch-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
Policy
------

- Data in a conditional part that constants make unreachable now counts as
data carrier bytes, so under the default settings a transaction carrying it
is rejected with `txn-datacarrier-nonstandard`. This already applied to the
`OP_FALSE OP_IF ... OP_ENDIF` inscription envelope; it now also covers
`OP_1 OP_NOTIF ... OP_ENDIF`, guards computed from constants, and the dead
part of an `OP_ELSE`. Scripts that branch on witness data or a signature
check, which is how spendable scripts branch, are unaffected. The new
`-rejectdeadbranches` option (default: 1, reset by `-corepolicy`) turns the
wider rule off and leaves only the envelope counted.
4 changes: 4 additions & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -721,6 +721,7 @@ void SetupServerArgs(ArgsManager& argsman, bool can_listen_ipc)
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);
argsman.AddArg("-datacarrier", strprintf("Relay and mine data carrier transactions (default: %u)", DEFAULT_ACCEPT_DATACARRIER), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-datacarriercost", strprintf("Treat extra data in transactions as at least N vbytes per actual byte (default: %s)", DEFAULT_WEIGHT_PER_DATA_BYTE / 4.0), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
argsman.AddArg("-rejectdeadbranches", strprintf("Count data in a conditional branch that a pushed constant makes unreachable as data carrier bytes; the OP_FALSE OP_IF envelope is counted either way (default: %u)", DEFAULT_REJECT_DEAD_BRANCHES), ArgsManager::ALLOW_ANY, OptionsCategory::NODE_RELAY);
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);
argsman.AddArg("-datacarriersize",
strprintf("Maximum size of data in data carrier transactions we relay and mine, in bytes (default: %u)",
Expand Down Expand Up @@ -873,6 +874,7 @@ void InitParameterInteraction(ArgsManager& args)
args.SoftSetArg("-subdustfeepenalty", "0");
args.SoftSetArg("-datacarriercost", "0.25");
args.SoftSetArg("-datacarrierfullcount", "0");
args.SoftSetArg("-rejectdeadbranches", "0");
args.SoftSetArg("-maxtxlegacysigops", strprintf("%s", std::numeric_limits<unsigned int>::max()));
args.SoftSetArg("-maxscriptsize", strprintf("%s", std::numeric_limits<unsigned int>::max()));
args.SoftSetArg("-mempooltruc", "enforce");
Expand Down Expand Up @@ -1213,6 +1215,8 @@ bool AppInitParameterInteraction(const ArgsManager& args)

g_script_size_policy_limit = args.GetIntArg("-maxscriptsize", g_script_size_policy_limit);

g_reject_dead_branches = args.GetBoolArg("-rejectdeadbranches", g_reject_dead_branches);

nBytesPerSigOp = args.GetIntArg("-bytespersigop", nBytesPerSigOp);
nBytesPerSigOpStrict = args.GetIntArg("-bytespersigopstrict", nBytesPerSigOpStrict);

Expand Down
15 changes: 13 additions & 2 deletions src/policy/policy.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include <vector>

unsigned int g_script_size_policy_limit{DEFAULT_SCRIPT_SIZE_POLICY_LIMIT};
bool g_reject_dead_branches{DEFAULT_REJECT_DEAD_BRANCHES};

CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
{
Expand Down Expand Up @@ -633,14 +634,24 @@ std::pair<CScript, unsigned int> GetScriptForTransactionInput(CScript prevScript
return std::make_pair(CScript(), 0);
}

/**
* Whether to look for dead branches in this input. A witness over the script size
* limit fails IsWitnessStandard right after, so following its constants would be
* work spent on a transaction that is rejected anyway.
*/
static bool FollowDeadBranches(const CTxIn& txin)
{
return ::g_reject_dead_branches && GetSerializeSize(txin.scriptWitness.stack) <= g_script_size_policy_limit;
}

std::pair<size_t, size_t> DatacarrierBytes(const CTransaction& tx, const CCoinsViewCache& view)
{
std::pair<size_t, size_t> ret{0, 0};

for (const CTxIn& txin : tx.vin) {
const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
const auto dcb = script.DatacarrierBytes(0, &txin.scriptWitness);
const auto dcb = script.DatacarrierBytes(0, &txin.scriptWitness, FollowDeadBranches(txin));
ret.first += dcb.first;
ret.second += dcb.second;
}
Expand All @@ -664,7 +675,7 @@ int32_t CalculateExtraTxWeight(const CTransaction& tx, const CCoinsViewCache& vi
const CTxOut &utxo = view.AccessCoin(txin.prevout).out;
auto[script, consensus_weight_per_byte] = GetScriptForTransactionInput(utxo.scriptPubKey, txin);
if (weight_per_data_byte > consensus_weight_per_byte) {
const auto dcb = script.DatacarrierBytes(0, &txin.scriptWitness);
const auto dcb = script.DatacarrierBytes(0, &txin.scriptWitness, FollowDeadBranches(txin));
mod_weight += int64_t(dcb.first + dcb.second) * (weight_per_data_byte - consensus_weight_per_byte);
}
}
Expand Down
2 changes: 2 additions & 0 deletions src/policy/policy.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP{20};
static constexpr unsigned int DEFAULT_BYTES_PER_SIGOP_STRICT{20};
/** Default for -datacarriercost (multiplied by WITNESS_SCALE_FACTOR) */
static constexpr unsigned int DEFAULT_WEIGHT_PER_DATA_BYTE{4};
/** Default for -rejectdeadbranches */
static constexpr bool DEFAULT_REJECT_DEAD_BRANCHES{true};
/** Default for -rejecttokens */
static constexpr bool DEFAULT_REJECT_TOKENS{true};
/** Default for -subdustfeepenalty */
Expand Down
1 change: 1 addition & 0 deletions src/policy/settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ extern unsigned int g_script_size_policy_limit;
extern unsigned int nBytesPerSigOp;
extern unsigned int nBytesPerSigOpStrict;
extern unsigned int g_weight_per_data_byte;
extern bool g_reject_dead_branches;

#endif // BITCOIN_POLICY_SETTINGS_H
Loading