Initial Vexta Core v0.1.0 release
This commit is contained in:
commit
25c454329d
2481 changed files with 689289 additions and 0 deletions
43
src/policy/feerate.cpp
Normal file
43
src/policy/feerate.cpp
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2020 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <policy/feerate.h>
|
||||
|
||||
#include <tinyformat.h>
|
||||
#include <cmath>
|
||||
|
||||
CFeeRate::CFeeRate(const CAmount& nFeePaid, uint32_t num_bytes)
|
||||
{
|
||||
const int64_t nSize{num_bytes};
|
||||
|
||||
if (nSize > 0) {
|
||||
nSatoshisPerK = nFeePaid * 1000 / nSize;
|
||||
} else {
|
||||
nSatoshisPerK = 0;
|
||||
}
|
||||
}
|
||||
|
||||
CAmount CFeeRate::GetFee(uint32_t num_bytes) const
|
||||
{
|
||||
const int64_t nSize{num_bytes};
|
||||
|
||||
CAmount nFee{static_cast<CAmount>(std::ceil(nSatoshisPerK * nSize / 1000.0))};
|
||||
|
||||
if (nFee == 0 && nSize != 0) {
|
||||
if (nSatoshisPerK > 0) nFee = CAmount(1);
|
||||
if (nSatoshisPerK < 0) nFee = CAmount(-1);
|
||||
}
|
||||
|
||||
return nFee;
|
||||
}
|
||||
|
||||
std::string CFeeRate::ToString(const FeeEstimateMode& fee_estimate_mode) const
|
||||
{
|
||||
switch (fee_estimate_mode) {
|
||||
case FeeEstimateMode::SAT_VB: return strprintf("%d.%03d %s/vB", nSatoshisPerK / 1000, nSatoshisPerK % 1000, CURRENCY_ATOM);
|
||||
default: return strprintf("%d.%08d %s/kvB", nSatoshisPerK / COIN, nSatoshisPerK % COIN, CURRENCY_UNIT);
|
||||
}
|
||||
}
|
||||
71
src/policy/feerate.h
Normal file
71
src/policy/feerate.h
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2020 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef DIGIBYTE_POLICY_FEERATE_H
|
||||
#define DIGIBYTE_POLICY_FEERATE_H
|
||||
|
||||
#include <amount.h>
|
||||
#include <serialize.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
const std::string CURRENCY_UNIT = "DGB"; // One formatted unit
|
||||
const std::string CURRENCY_ATOM = "sat"; // One indivisible minimum value unit
|
||||
|
||||
/* Used to determine type of fee estimation requested */
|
||||
enum class FeeEstimateMode {
|
||||
UNSET, //!< Use default settings based on other criteria
|
||||
ECONOMICAL, //!< Force estimateSmartFee to use non-conservative estimates
|
||||
CONSERVATIVE, //!< Force estimateSmartFee to use conservative estimates
|
||||
DGB_KVB, //!< Use VTX/kvB fee rate unit
|
||||
SAT_VB, //!< Use sat/vB fee rate unit
|
||||
};
|
||||
|
||||
/**
|
||||
* Fee rate in satoshis per kilobyte: CAmount / kB
|
||||
*/
|
||||
class CFeeRate
|
||||
{
|
||||
private:
|
||||
CAmount nSatoshisPerK; // unit is satoshis-per-1,000-bytes
|
||||
|
||||
public:
|
||||
/** Fee rate of 0 satoshis per kB */
|
||||
CFeeRate() : nSatoshisPerK(0) { }
|
||||
template<typename I>
|
||||
explicit CFeeRate(const I _nSatoshisPerK): nSatoshisPerK(_nSatoshisPerK) {
|
||||
// We've previously had bugs creep in from silent double->int conversion...
|
||||
static_assert(std::is_integral<I>::value, "CFeeRate should be used without floats");
|
||||
}
|
||||
/** Constructor for a fee rate in satoshis per kvB (sat/kvB).
|
||||
*
|
||||
* Passing a num_bytes value of COIN (1e8) returns a fee rate in satoshis per vB (sat/vB),
|
||||
* e.g. (nFeePaid * 1e8 / 1e3) == (nFeePaid / 1e5),
|
||||
* where 1e5 is the ratio to convert from VTX/kvB to sat/vB.
|
||||
*/
|
||||
CFeeRate(const CAmount& nFeePaid, uint32_t num_bytes);
|
||||
/**
|
||||
* Return the fee in satoshis for the given size in bytes.
|
||||
* If the calculated fee would have fractional satoshis, then the returned fee will always be rounded up to the nearest satoshi.
|
||||
*/
|
||||
CAmount GetFee(uint32_t num_bytes) const;
|
||||
/**
|
||||
* Return the fee in satoshis for a size of 1000 bytes
|
||||
*/
|
||||
CAmount GetFeePerK() const { return GetFee(1000); }
|
||||
friend bool operator<(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK < b.nSatoshisPerK; }
|
||||
friend bool operator>(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK > b.nSatoshisPerK; }
|
||||
friend bool operator==(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK == b.nSatoshisPerK; }
|
||||
friend bool operator<=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK <= b.nSatoshisPerK; }
|
||||
friend bool operator>=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK >= b.nSatoshisPerK; }
|
||||
friend bool operator!=(const CFeeRate& a, const CFeeRate& b) { return a.nSatoshisPerK != b.nSatoshisPerK; }
|
||||
CFeeRate& operator+=(const CFeeRate& a) { nSatoshisPerK += a.nSatoshisPerK; return *this; }
|
||||
std::string ToString(const FeeEstimateMode& fee_estimate_mode = FeeEstimateMode::DGB_KVB) const;
|
||||
|
||||
SERIALIZE_METHODS(CFeeRate, obj) { READWRITE(obj.nSatoshisPerK); }
|
||||
};
|
||||
|
||||
#endif // DIGIBYTE_POLICY_FEERATE_H
|
||||
1011
src/policy/fees.cpp
Normal file
1011
src/policy/fees.cpp
Normal file
File diff suppressed because it is too large
Load diff
295
src/policy/fees.h
Normal file
295
src/policy/fees.h
Normal file
|
|
@ -0,0 +1,295 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2020 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
#ifndef DIGIBYTE_POLICY_FEES_H
|
||||
#define DIGIBYTE_POLICY_FEES_H
|
||||
|
||||
#include <amount.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <uint256.h>
|
||||
#include <random.h>
|
||||
#include <sync.h>
|
||||
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CAutoFile;
|
||||
class CFeeRate;
|
||||
class CTxMemPoolEntry;
|
||||
class CTxMemPool;
|
||||
class TxConfirmStats;
|
||||
|
||||
/* Identifier for each of the 3 different TxConfirmStats which will track
|
||||
* history over different time horizons. */
|
||||
enum class FeeEstimateHorizon {
|
||||
SHORT_HALFLIFE,
|
||||
MED_HALFLIFE,
|
||||
LONG_HALFLIFE,
|
||||
};
|
||||
|
||||
static constexpr auto ALL_FEE_ESTIMATE_HORIZONS = std::array{
|
||||
FeeEstimateHorizon::SHORT_HALFLIFE,
|
||||
FeeEstimateHorizon::MED_HALFLIFE,
|
||||
FeeEstimateHorizon::LONG_HALFLIFE,
|
||||
};
|
||||
|
||||
std::string StringForFeeEstimateHorizon(FeeEstimateHorizon horizon);
|
||||
|
||||
/* Enumeration of reason for returned fee estimate */
|
||||
enum class FeeReason {
|
||||
NONE,
|
||||
HALF_ESTIMATE,
|
||||
FULL_ESTIMATE,
|
||||
DOUBLE_ESTIMATE,
|
||||
CONSERVATIVE,
|
||||
MEMPOOL_MIN,
|
||||
PAYTXFEE,
|
||||
FALLBACK,
|
||||
REQUIRED,
|
||||
};
|
||||
|
||||
/* Used to return detailed information about a feerate bucket */
|
||||
struct EstimatorBucket
|
||||
{
|
||||
double start = -1;
|
||||
double end = -1;
|
||||
double withinTarget = 0;
|
||||
double totalConfirmed = 0;
|
||||
double inMempool = 0;
|
||||
double leftMempool = 0;
|
||||
};
|
||||
|
||||
/* Used to return detailed information about a fee estimate calculation */
|
||||
struct EstimationResult
|
||||
{
|
||||
EstimatorBucket pass;
|
||||
EstimatorBucket fail;
|
||||
double decay = 0;
|
||||
unsigned int scale = 0;
|
||||
};
|
||||
|
||||
struct FeeCalculation
|
||||
{
|
||||
EstimationResult est;
|
||||
FeeReason reason = FeeReason::NONE;
|
||||
int desiredTarget = 0;
|
||||
int returnedTarget = 0;
|
||||
};
|
||||
|
||||
/** \class CBlockPolicyEstimator
|
||||
* The BlockPolicyEstimator is used for estimating the feerate needed
|
||||
* for a transaction to be included in a block within a certain number of
|
||||
* blocks.
|
||||
*
|
||||
* At a high level the algorithm works by grouping transactions into buckets
|
||||
* based on having similar feerates and then tracking how long it
|
||||
* takes transactions in the various buckets to be mined. It operates under
|
||||
* the assumption that in general transactions of higher feerate will be
|
||||
* included in blocks before transactions of lower feerate. So for
|
||||
* example if you wanted to know what feerate you should put on a transaction to
|
||||
* be included in a block within the next 5 blocks, you would start by looking
|
||||
* at the bucket with the highest feerate transactions and verifying that a
|
||||
* sufficiently high percentage of them were confirmed within 5 blocks and
|
||||
* then you would look at the next highest feerate bucket, and so on, stopping at
|
||||
* the last bucket to pass the test. The average feerate of transactions in this
|
||||
* bucket will give you an indication of the lowest feerate you can put on a
|
||||
* transaction and still have a sufficiently high chance of being confirmed
|
||||
* within your desired 5 blocks.
|
||||
*
|
||||
* Here is a brief description of the implementation:
|
||||
* When a transaction enters the mempool, we track the height of the block chain
|
||||
* at entry. All further calculations are conducted only on this set of "seen"
|
||||
* transactions. Whenever a block comes in, we count the number of transactions
|
||||
* in each bucket and the total amount of feerate paid in each bucket. Then we
|
||||
* calculate how many blocks Y it took each transaction to be mined. We convert
|
||||
* from a number of blocks to a number of periods Y' each encompassing "scale"
|
||||
* blocks. This is tracked in 3 different data sets each up to a maximum
|
||||
* number of periods. Within each data set we have an array of counters in each
|
||||
* feerate bucket and we increment all the counters from Y' up to max periods
|
||||
* representing that a tx was successfully confirmed in less than or equal to
|
||||
* that many periods. We want to save a history of this information, so at any
|
||||
* time we have a counter of the total number of transactions that happened in a
|
||||
* given feerate bucket and the total number that were confirmed in each of the
|
||||
* periods or less for any bucket. We save this history by keeping an
|
||||
* exponentially decaying moving average of each one of these stats. This is
|
||||
* done for a different decay in each of the 3 data sets to keep relevant data
|
||||
* from different time horizons. Furthermore we also keep track of the number
|
||||
* unmined (in mempool or left mempool without being included in a block)
|
||||
* transactions in each bucket and for how many blocks they have been
|
||||
* outstanding and use both of these numbers to increase the number of transactions
|
||||
* we've seen in that feerate bucket when calculating an estimate for any number
|
||||
* of confirmations below the number of blocks they've been outstanding.
|
||||
*
|
||||
* We want to be able to estimate feerates that are needed on tx's to be included in
|
||||
* a certain number of blocks. Every time a block is added to the best chain, this class records
|
||||
* stats on the transactions included in that block
|
||||
*/
|
||||
class CBlockPolicyEstimator
|
||||
{
|
||||
private:
|
||||
/** Track confirm delays up to 12 blocks for short horizon */
|
||||
static constexpr unsigned int SHORT_BLOCK_PERIODS = 12;
|
||||
static constexpr unsigned int SHORT_SCALE = 1;
|
||||
/** Track confirm delays up to 48 blocks for medium horizon */
|
||||
static constexpr unsigned int MED_BLOCK_PERIODS = 24;
|
||||
static constexpr unsigned int MED_SCALE = 2;
|
||||
/** Track confirm delays up to 1008 blocks for long horizon */
|
||||
static constexpr unsigned int LONG_BLOCK_PERIODS = 42;
|
||||
static constexpr unsigned int LONG_SCALE = 24;
|
||||
/** Historical estimates that are older than this aren't valid */
|
||||
static const unsigned int OLDEST_ESTIMATE_HISTORY = 6 * 1008;
|
||||
|
||||
/** Decay of .962 is a half-life of 18 blocks or about 3 hours */
|
||||
static constexpr double SHORT_DECAY = .962;
|
||||
/** Decay of .9952 is a half-life of 144 blocks or about 1 day */
|
||||
static constexpr double MED_DECAY = .9952;
|
||||
/** Decay of .99931 is a half-life of 1008 blocks or about 1 week */
|
||||
static constexpr double LONG_DECAY = .99931;
|
||||
|
||||
/** Require greater than 60% of X feerate transactions to be confirmed within Y/2 blocks*/
|
||||
static constexpr double HALF_SUCCESS_PCT = .6;
|
||||
/** Require greater than 85% of X feerate transactions to be confirmed within Y blocks*/
|
||||
static constexpr double SUCCESS_PCT = .85;
|
||||
/** Require greater than 95% of X feerate transactions to be confirmed within 2 * Y blocks*/
|
||||
static constexpr double DOUBLE_SUCCESS_PCT = .95;
|
||||
|
||||
/** Require an avg of 0.1 tx in the combined feerate bucket per block to have stat significance */
|
||||
static constexpr double SUFFICIENT_FEETXS = 0.1;
|
||||
/** Require an avg of 0.5 tx when using short decay since there are fewer blocks considered*/
|
||||
static constexpr double SUFFICIENT_TXS_SHORT = 0.5;
|
||||
|
||||
/** Minimum and Maximum values for tracking feerates
|
||||
* The MIN_BUCKET_FEERATE should just be set to the lowest reasonable feerate we
|
||||
* might ever want to track. Historically this has been 1000 since it was
|
||||
* inheriting DEFAULT_MIN_RELAY_TX_FEE and changing it is disruptive as it
|
||||
* invalidates old estimates files. So leave it at 1000 unless it becomes
|
||||
* necessary to lower it, and then lower it substantially.
|
||||
*/
|
||||
static constexpr double MIN_BUCKET_FEERATE = 1000;
|
||||
static constexpr double MAX_BUCKET_FEERATE = 1e10;
|
||||
|
||||
/** Spacing of FeeRate buckets
|
||||
* We have to lump transactions into buckets based on feerate, but we want to be able
|
||||
* to give accurate estimates over a large range of potential feerates
|
||||
* Therefore it makes sense to exponentially space the buckets
|
||||
*/
|
||||
static constexpr double FEE_SPACING = 1.05;
|
||||
|
||||
public:
|
||||
/** Create new BlockPolicyEstimator and initialize stats tracking classes with default values */
|
||||
CBlockPolicyEstimator();
|
||||
~CBlockPolicyEstimator();
|
||||
|
||||
/** Process all the transactions that have been included in a block */
|
||||
void processBlock(unsigned int nBlockHeight,
|
||||
std::vector<const CTxMemPoolEntry*>& entries);
|
||||
|
||||
/** Process a transaction accepted to the mempool*/
|
||||
void processTransaction(const CTxMemPoolEntry& entry, bool validFeeEstimate);
|
||||
|
||||
/** Remove a transaction from the mempool tracking stats*/
|
||||
bool removeTx(uint256 hash, bool inBlock);
|
||||
|
||||
/** DEPRECATED. Return a feerate estimate */
|
||||
CFeeRate estimateFee(int confTarget) const;
|
||||
|
||||
/** Estimate feerate needed to get be included in a block within confTarget
|
||||
* blocks. If no answer can be given at confTarget, return an estimate at
|
||||
* the closest target where one can be given. 'conservative' estimates are
|
||||
* valid over longer time horizons also.
|
||||
*/
|
||||
CFeeRate estimateSmartFee(int confTarget, FeeCalculation *feeCalc, bool conservative) const;
|
||||
|
||||
/** Return a specific fee estimate calculation with a given success
|
||||
* threshold and time horizon, and optionally return detailed data about
|
||||
* calculation
|
||||
*/
|
||||
CFeeRate estimateRawFee(int confTarget, double successThreshold, FeeEstimateHorizon horizon, EstimationResult *result = nullptr) const;
|
||||
|
||||
/** Write estimation data to a file */
|
||||
bool Write(CAutoFile& fileout) const;
|
||||
|
||||
/** Read estimation data from a file */
|
||||
bool Read(CAutoFile& filein);
|
||||
|
||||
/** Empty mempool transactions on shutdown to record failure to confirm for txs still in mempool */
|
||||
void FlushUnconfirmed();
|
||||
|
||||
/** Calculation of highest target that estimates are tracked for */
|
||||
unsigned int HighestTargetTracked(FeeEstimateHorizon horizon) const;
|
||||
|
||||
/** Drop still unconfirmed transactions and record current estimations, if the fee estimation file is present. */
|
||||
void Flush();
|
||||
|
||||
private:
|
||||
mutable RecursiveMutex m_cs_fee_estimator;
|
||||
|
||||
unsigned int nBestSeenHeight GUARDED_BY(m_cs_fee_estimator);
|
||||
unsigned int firstRecordedHeight GUARDED_BY(m_cs_fee_estimator);
|
||||
unsigned int historicalFirst GUARDED_BY(m_cs_fee_estimator);
|
||||
unsigned int historicalBest GUARDED_BY(m_cs_fee_estimator);
|
||||
|
||||
struct TxStatsInfo
|
||||
{
|
||||
unsigned int blockHeight;
|
||||
unsigned int bucketIndex;
|
||||
TxStatsInfo() : blockHeight(0), bucketIndex(0) {}
|
||||
};
|
||||
|
||||
// map of txids to information about that transaction
|
||||
std::map<uint256, TxStatsInfo> mapMemPoolTxs GUARDED_BY(m_cs_fee_estimator);
|
||||
|
||||
/** Classes to track historical data on transaction confirmations */
|
||||
std::unique_ptr<TxConfirmStats> feeStats PT_GUARDED_BY(m_cs_fee_estimator);
|
||||
std::unique_ptr<TxConfirmStats> shortStats PT_GUARDED_BY(m_cs_fee_estimator);
|
||||
std::unique_ptr<TxConfirmStats> longStats PT_GUARDED_BY(m_cs_fee_estimator);
|
||||
|
||||
unsigned int trackedTxs GUARDED_BY(m_cs_fee_estimator);
|
||||
unsigned int untrackedTxs GUARDED_BY(m_cs_fee_estimator);
|
||||
|
||||
std::vector<double> buckets GUARDED_BY(m_cs_fee_estimator); // The upper-bound of the range for the bucket (inclusive)
|
||||
std::map<double, unsigned int> bucketMap GUARDED_BY(m_cs_fee_estimator); // Map of bucket upper-bound to index into all vectors by bucket
|
||||
|
||||
/** Process a transaction confirmed in a block*/
|
||||
bool processBlockTx(unsigned int nBlockHeight, const CTxMemPoolEntry* entry) EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
|
||||
|
||||
/** Helper for estimateSmartFee */
|
||||
double estimateCombinedFee(unsigned int confTarget, double successThreshold, bool checkShorterHorizon, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
|
||||
/** Helper for estimateSmartFee */
|
||||
double estimateConservativeFee(unsigned int doubleTarget, EstimationResult *result) const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
|
||||
/** Number of blocks of data recorded while fee estimates have been running */
|
||||
unsigned int BlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
|
||||
/** Number of blocks of recorded fee estimate data represented in saved data file */
|
||||
unsigned int HistoricalBlockSpan() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
|
||||
/** Calculation of highest target that reasonable estimate can be provided for */
|
||||
unsigned int MaxUsableEstimate() const EXCLUSIVE_LOCKS_REQUIRED(m_cs_fee_estimator);
|
||||
};
|
||||
|
||||
class FeeFilterRounder
|
||||
{
|
||||
private:
|
||||
static constexpr double MAX_FILTER_FEERATE = 1e10;
|
||||
/** FEE_FILTER_SPACING is just used to provide some quantization of fee
|
||||
* filter results. Historically it reused FEE_SPACING, but it is completely
|
||||
* unrelated, and was made a separate constant so the two concepts are not
|
||||
* tied together */
|
||||
static constexpr double FEE_FILTER_SPACING = 1.1;
|
||||
|
||||
public:
|
||||
/** Create new FeeFilterRounder */
|
||||
explicit FeeFilterRounder(const CFeeRate& minIncrementalFee);
|
||||
|
||||
/** Quantize a minimum fee for privacy purpose before broadcast. Not thread-safe due to use of FastRandomContext */
|
||||
CAmount round(CAmount currentMinFee);
|
||||
|
||||
private:
|
||||
std::set<double> feeset;
|
||||
FastRandomContext insecure_rand;
|
||||
};
|
||||
|
||||
#endif // DIGIBYTE_POLICY_FEES_H
|
||||
62
src/policy/packages.cpp
Normal file
62
src/policy/packages.cpp
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
// Copyright (c) 2021 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <consensus/validation.h>
|
||||
#include <policy/packages.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <uint256.h>
|
||||
#include <util/hasher.h>
|
||||
|
||||
#include <numeric>
|
||||
#include <unordered_set>
|
||||
|
||||
bool CheckPackage(const Package& txns, PackageValidationState& state)
|
||||
{
|
||||
const unsigned int package_count = txns.size();
|
||||
|
||||
if (package_count > MAX_PACKAGE_COUNT) {
|
||||
return state.Invalid(PackageValidationResult::PCKG_POLICY, "package-too-many-transactions");
|
||||
}
|
||||
|
||||
const int64_t total_size = std::accumulate(txns.cbegin(), txns.cend(), 0,
|
||||
[](int64_t sum, const auto& tx) { return sum + GetVirtualTransactionSize(*tx); });
|
||||
// If the package only contains 1 tx, it's better to report the policy violation on individual tx size.
|
||||
if (package_count > 1 && total_size > MAX_PACKAGE_SIZE * 1000) {
|
||||
return state.Invalid(PackageValidationResult::PCKG_POLICY, "package-too-large");
|
||||
}
|
||||
|
||||
// Require the package to be sorted in order of dependency, i.e. parents appear before children.
|
||||
// An unsorted package will fail anyway on missing-inputs, but it's better to quit earlier and
|
||||
// fail on something less ambiguous (missing-inputs could also be an orphan or trying to
|
||||
// spend nonexistent coins).
|
||||
std::unordered_set<uint256, SaltedTxidHasher> later_txids;
|
||||
std::transform(txns.cbegin(), txns.cend(), std::inserter(later_txids, later_txids.end()),
|
||||
[](const auto& tx) { return tx->GetHash(); });
|
||||
for (const auto& tx : txns) {
|
||||
for (const auto& input : tx->vin) {
|
||||
if (later_txids.find(input.prevout.hash) != later_txids.end()) {
|
||||
// The parent is a subsequent transaction in the package.
|
||||
return state.Invalid(PackageValidationResult::PCKG_POLICY, "package-not-sorted");
|
||||
}
|
||||
}
|
||||
later_txids.erase(tx->GetHash());
|
||||
}
|
||||
|
||||
// Don't allow any conflicting transactions, i.e. spending the same inputs, in a package.
|
||||
std::unordered_set<COutPoint, SaltedOutpointHasher> inputs_seen;
|
||||
for (const auto& tx : txns) {
|
||||
for (const auto& input : tx->vin) {
|
||||
if (inputs_seen.find(input.prevout) != inputs_seen.end()) {
|
||||
// This input is also present in another tx in the package.
|
||||
return state.Invalid(PackageValidationResult::PCKG_POLICY, "conflict-in-package");
|
||||
}
|
||||
}
|
||||
// Batch-add all the inputs for a tx at a time. If we added them 1 at a time, we could
|
||||
// catch duplicate inputs within a single tx. This is a more severe, consensus error,
|
||||
// and we want to report that from CheckTransaction instead.
|
||||
std::transform(tx->vin.cbegin(), tx->vin.cend(), std::inserter(inputs_seen, inputs_seen.end()),
|
||||
[](const auto& input) { return input.prevout; });
|
||||
}
|
||||
return true;
|
||||
}
|
||||
44
src/policy/packages.h
Normal file
44
src/policy/packages.h
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
// Copyright (c) 2021 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef DIGIBYTE_POLICY_PACKAGES_H
|
||||
#define DIGIBYTE_POLICY_PACKAGES_H
|
||||
|
||||
#include <consensus/validation.h>
|
||||
#include <policy/policy.h>
|
||||
#include <primitives/transaction.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
/** Default maximum number of transactions in a package. */
|
||||
static constexpr uint32_t MAX_PACKAGE_COUNT{25};
|
||||
/** Default maximum total virtual size of transactions in a package in KvB. */
|
||||
static constexpr uint32_t MAX_PACKAGE_SIZE{101};
|
||||
static_assert(MAX_PACKAGE_SIZE * WITNESS_SCALE_FACTOR * 1000 >= MAX_STANDARD_TX_WEIGHT);
|
||||
|
||||
/** A "reason" why a package was invalid. It may be that one or more of the included
|
||||
* transactions is invalid or the package itself violates our rules.
|
||||
* We don't distinguish between consensus and policy violations right now.
|
||||
*/
|
||||
enum class PackageValidationResult {
|
||||
PCKG_RESULT_UNSET = 0, //!< Initial value. The package has not yet been rejected.
|
||||
PCKG_POLICY, //!< The package itself is invalid (e.g. too many transactions).
|
||||
PCKG_TX, //!< At least one tx is invalid.
|
||||
};
|
||||
|
||||
/** A package is an ordered list of transactions. The transactions cannot conflict with (spend the
|
||||
* same inputs as) one another. */
|
||||
using Package = std::vector<CTransactionRef>;
|
||||
|
||||
class PackageValidationState : public ValidationState<PackageValidationResult> {};
|
||||
|
||||
/** Context-free package policy checks:
|
||||
* 1. The number of transactions cannot exceed MAX_PACKAGE_COUNT.
|
||||
* 2. The total virtual size cannot exceed MAX_PACKAGE_SIZE.
|
||||
* 3. If any dependencies exist between transactions, parents must appear before children.
|
||||
* 4. Transactions cannot conflict, i.e., spend the same inputs.
|
||||
*/
|
||||
bool CheckPackage(const Package& txns, PackageValidationState& state);
|
||||
|
||||
#endif // DIGIBYTE_POLICY_PACKAGES_H
|
||||
294
src/policy/policy.cpp
Normal file
294
src/policy/policy.cpp
Normal file
|
|
@ -0,0 +1,294 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2020 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
// NOTE: This file is intended to be customised by the end user, and includes only local node policy logic
|
||||
|
||||
#include <policy/policy.h>
|
||||
|
||||
#include <consensus/validation.h>
|
||||
#include <coins.h>
|
||||
#include <span.h>
|
||||
|
||||
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
|
||||
{
|
||||
// "Dust" is defined in terms of dustRelayFee,
|
||||
// which has units satoshis-per-kilobyte.
|
||||
// If you'd pay more in fees than the value of the output
|
||||
// to spend something, then we consider it dust.
|
||||
// A typical spendable non-segwit txout is 34 bytes big, and will
|
||||
// need a CTxIn of at least 148 bytes to spend:
|
||||
// so dust is a spendable txout less than
|
||||
// 182*dustRelayFee/1000 (in satoshis).
|
||||
// 546 satoshis at the default rate of 3000 sat/kvB.
|
||||
// A typical spendable segwit txout is 31 bytes big, and will
|
||||
// need a CTxIn of at least 67 bytes to spend:
|
||||
// so dust is a spendable txout less than
|
||||
// 98*dustRelayFee/1000 (in satoshis).
|
||||
// 294 satoshis at the default rate of 3000 sat/kvB.
|
||||
if (txout.scriptPubKey.IsUnspendable())
|
||||
return 0;
|
||||
|
||||
size_t nSize = GetSerializeSize(txout);
|
||||
int witnessversion = 0;
|
||||
std::vector<unsigned char> witnessprogram;
|
||||
|
||||
if (txout.scriptPubKey.IsWitnessProgram(witnessversion, witnessprogram)) {
|
||||
// sum the sizes of the parts of a transaction input
|
||||
// with 75% segwit discount applied to the script size.
|
||||
nSize += (32 + 4 + 1 + (107 / WITNESS_SCALE_FACTOR) + 4);
|
||||
} else {
|
||||
nSize += (32 + 4 + 1 + 107 + 4); // the 148 mentioned above
|
||||
}
|
||||
|
||||
return dustRelayFeeIn.GetFee(nSize);
|
||||
}
|
||||
|
||||
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFeeIn)
|
||||
{
|
||||
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
|
||||
}
|
||||
|
||||
bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType)
|
||||
{
|
||||
std::vector<std::vector<unsigned char> > vSolutions;
|
||||
whichType = Solver(scriptPubKey, vSolutions);
|
||||
|
||||
if (whichType == TxoutType::NONSTANDARD) {
|
||||
return false;
|
||||
} else if (whichType == TxoutType::MULTISIG) {
|
||||
unsigned char m = vSolutions.front()[0];
|
||||
unsigned char n = vSolutions.back()[0];
|
||||
// Support up to x-of-3 multisig txns as standard
|
||||
if (n < 1 || n > 3)
|
||||
return false;
|
||||
if (m < 1 || m > n)
|
||||
return false;
|
||||
} else if (whichType == TxoutType::NULL_DATA &&
|
||||
(!fAcceptDatacarrier || scriptPubKey.size() > nMaxDatacarrierBytes)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason)
|
||||
{
|
||||
if (tx.nVersion > TX_MAX_STANDARD_VERSION || tx.nVersion < 1) {
|
||||
reason = "version";
|
||||
return false;
|
||||
}
|
||||
|
||||
// Extremely large transactions with lots of inputs can cost the network
|
||||
// almost as much to process as they cost the sender in fees, because
|
||||
// computing signature hashes is O(ninputs*txsize). Limiting transactions
|
||||
// to MAX_STANDARD_TX_WEIGHT mitigates CPU exhaustion attacks.
|
||||
unsigned int sz = GetTransactionWeight(tx);
|
||||
if (sz > MAX_STANDARD_TX_WEIGHT) {
|
||||
reason = "tx-size";
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const CTxIn& txin : tx.vin)
|
||||
{
|
||||
// Biggest 'standard' txin involving only keys is a 15-of-15 P2SH
|
||||
// multisig with compressed keys (remember the 520 byte limit on
|
||||
// redeemScript size). That works out to a (15*(33+1))+3=513 byte
|
||||
// redeemScript, 513+1+15*(73+1)+3=1627 bytes of scriptSig, which
|
||||
// we round off to 1650(MAX_STANDARD_SCRIPTSIG_SIZE) bytes for
|
||||
// some minor future-proofing. That's also enough to spend a
|
||||
// 20-of-20 CHECKMULTISIG scriptPubKey, though such a scriptPubKey
|
||||
// is not considered standard.
|
||||
if (txin.scriptSig.size() > MAX_STANDARD_SCRIPTSIG_SIZE) {
|
||||
reason = "scriptsig-size";
|
||||
return false;
|
||||
}
|
||||
if (!txin.scriptSig.IsPushOnly()) {
|
||||
reason = "scriptsig-not-pushonly";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int nDataOut = 0;
|
||||
TxoutType whichType;
|
||||
for (const CTxOut& txout : tx.vout) {
|
||||
if (!::IsStandard(txout.scriptPubKey, whichType)) {
|
||||
reason = "scriptpubkey";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (whichType == TxoutType::NULL_DATA)
|
||||
nDataOut++;
|
||||
else if ((whichType == TxoutType::MULTISIG) && (!permit_bare_multisig)) {
|
||||
reason = "bare-multisig";
|
||||
return false;
|
||||
} else if (IsDust(txout, dust_relay_fee)) {
|
||||
reason = "dust";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// only one OP_RETURN txout is permitted
|
||||
if (nDataOut > 1) {
|
||||
reason = "multi-op-return";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check transaction inputs to mitigate two
|
||||
* potential denial-of-service attacks:
|
||||
*
|
||||
* 1. scriptSigs with extra data stuffed into them,
|
||||
* not consumed by scriptPubKey (or P2SH script)
|
||||
* 2. P2SH scripts with a crazy number of expensive
|
||||
* CHECKSIG/CHECKMULTISIG operations
|
||||
*
|
||||
* Why bother? To avoid denial-of-service attacks; an attacker
|
||||
* can submit a standard HASH... OP_EQUAL transaction,
|
||||
* which will get accepted into blocks. The redemption
|
||||
* script can be anything; an attacker could use a very
|
||||
* expensive-to-check-upon-redemption script like:
|
||||
* DUP CHECKSIG DROP ... repeated 100 times... OP_1
|
||||
*
|
||||
* Note that only the non-witness portion of the transaction is checked here.
|
||||
*/
|
||||
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, bool taproot_active)
|
||||
{
|
||||
if (tx.IsCoinBase())
|
||||
return true; // Coinbases don't use vin normally
|
||||
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
const CTxOut& prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
|
||||
|
||||
std::vector<std::vector<unsigned char> > vSolutions;
|
||||
TxoutType whichType = Solver(prev.scriptPubKey, vSolutions);
|
||||
if (whichType == TxoutType::NONSTANDARD || whichType == TxoutType::WITNESS_UNKNOWN) {
|
||||
// WITNESS_UNKNOWN failures are typically also caught with a policy
|
||||
// flag in the script interpreter, but it can be helpful to catch
|
||||
// this type of NONSTANDARD transaction earlier in transaction
|
||||
// validation.
|
||||
return false;
|
||||
} else if (whichType == TxoutType::SCRIPTHASH) {
|
||||
std::vector<std::vector<unsigned char> > stack;
|
||||
// convert the scriptSig into a stack, so we can inspect the redeemScript
|
||||
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
|
||||
return false;
|
||||
if (stack.empty())
|
||||
return false;
|
||||
CScript subscript(stack.back().begin(), stack.back().end());
|
||||
if (subscript.GetSigOpCount(true) > MAX_P2SH_SIGOPS) {
|
||||
return false;
|
||||
}
|
||||
} else if (whichType == TxoutType::WITNESS_V1_TAPROOT) {
|
||||
// Don't allow Taproot spends unless Taproot is active.
|
||||
if (!taproot_active) return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs)
|
||||
{
|
||||
if (tx.IsCoinBase())
|
||||
return true; // Coinbases are skipped
|
||||
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
// We don't care if witness for this input is empty, since it must not be bloated.
|
||||
// If the script is invalid without witness, it would be caught sooner or later during validation.
|
||||
if (tx.vin[i].scriptWitness.IsNull())
|
||||
continue;
|
||||
|
||||
const CTxOut &prev = mapInputs.AccessCoin(tx.vin[i].prevout).out;
|
||||
|
||||
// get the scriptPubKey corresponding to this input:
|
||||
CScript prevScript = prev.scriptPubKey;
|
||||
|
||||
bool p2sh = false;
|
||||
if (prevScript.IsPayToScriptHash()) {
|
||||
std::vector <std::vector<unsigned char> > stack;
|
||||
// If the scriptPubKey is P2SH, we try to extract the redeemScript casually by converting the scriptSig
|
||||
// into a stack. We do not check IsPushOnly nor compare the hash as these will be done later anyway.
|
||||
// If the check fails at this stage, we know that this txid must be a bad one.
|
||||
if (!EvalScript(stack, tx.vin[i].scriptSig, SCRIPT_VERIFY_NONE, BaseSignatureChecker(), SigVersion::BASE))
|
||||
return false;
|
||||
if (stack.empty())
|
||||
return false;
|
||||
prevScript = CScript(stack.back().begin(), stack.back().end());
|
||||
p2sh = true;
|
||||
}
|
||||
|
||||
int witnessversion = 0;
|
||||
std::vector<unsigned char> witnessprogram;
|
||||
|
||||
// Non-witness program must not be associated with any witness
|
||||
if (!prevScript.IsWitnessProgram(witnessversion, witnessprogram))
|
||||
return false;
|
||||
|
||||
// Check P2WSH standard limits
|
||||
if (witnessversion == 0 && witnessprogram.size() == WITNESS_V0_SCRIPTHASH_SIZE) {
|
||||
if (tx.vin[i].scriptWitness.stack.back().size() > MAX_STANDARD_P2WSH_SCRIPT_SIZE)
|
||||
return false;
|
||||
size_t sizeWitnessStack = tx.vin[i].scriptWitness.stack.size() - 1;
|
||||
if (sizeWitnessStack > MAX_STANDARD_P2WSH_STACK_ITEMS)
|
||||
return false;
|
||||
for (unsigned int j = 0; j < sizeWitnessStack; j++) {
|
||||
if (tx.vin[i].scriptWitness.stack[j].size() > MAX_STANDARD_P2WSH_STACK_ITEM_SIZE)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check policy limits for Taproot spends:
|
||||
// - MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE limit for stack item size
|
||||
// - No annexes
|
||||
if (witnessversion == 1 && witnessprogram.size() == WITNESS_V1_TAPROOT_SIZE && !p2sh) {
|
||||
// Taproot spend (non-P2SH-wrapped, version 1, witness program size 32; see BIP 341)
|
||||
auto stack = MakeSpan(tx.vin[i].scriptWitness.stack);
|
||||
if (stack.size() >= 2 && !stack.back().empty() && stack.back()[0] == ANNEX_TAG) {
|
||||
// Annexes are nonstandard as long as no semantics are defined for them.
|
||||
return false;
|
||||
}
|
||||
if (stack.size() >= 2) {
|
||||
// Script path spend (2 or more stack elements after removing optional annex)
|
||||
const auto& control_block = SpanPopBack(stack);
|
||||
SpanPopBack(stack); // Ignore script
|
||||
if (control_block.empty()) return false; // Empty control block is invalid
|
||||
if ((control_block[0] & TAPROOT_LEAF_MASK) == TAPROOT_LEAF_TAPSCRIPT) {
|
||||
// Leaf version 0xc0 (aka Tapscript, see BIP 342)
|
||||
for (const auto& item : stack) {
|
||||
if (item.size() > MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE) return false;
|
||||
}
|
||||
}
|
||||
} else if (stack.size() == 1) {
|
||||
// Key path spend (1 stack element after removing optional annex)
|
||||
// (no policy rules apply)
|
||||
} else {
|
||||
// 0 stack elements; this is already invalid by consensus rules
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop)
|
||||
{
|
||||
return (std::max(nWeight, nSigOpCost * bytes_per_sigop) + WITNESS_SCALE_FACTOR - 1) / WITNESS_SCALE_FACTOR;
|
||||
}
|
||||
|
||||
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop)
|
||||
{
|
||||
return GetVirtualTransactionSize(GetTransactionWeight(tx), nSigOpCost, bytes_per_sigop);
|
||||
}
|
||||
|
||||
int64_t GetVirtualTransactionInputSize(const CTxIn& txin, int64_t nSigOpCost, unsigned int bytes_per_sigop)
|
||||
{
|
||||
return GetVirtualTransactionSize(GetTransactionInputWeight(txin), nSigOpCost, bytes_per_sigop);
|
||||
}
|
||||
139
src/policy/policy.h
Normal file
139
src/policy/policy.h
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2020 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef DIGIBYTE_POLICY_POLICY_H
|
||||
#define DIGIBYTE_POLICY_POLICY_H
|
||||
|
||||
#include <consensus/consensus.h>
|
||||
#include <policy/feerate.h>
|
||||
#include <script/interpreter.h>
|
||||
#include <script/standard.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
class CCoinsViewCache;
|
||||
class CTxOut;
|
||||
|
||||
/** Default for -blockprioritysize, maximum space for zero/low-fee transactions **/
|
||||
static const unsigned int DEFAULT_BLOCK_PRIORITY_SIZE = 0;
|
||||
/** Default for -blockmaxweight, which controls the range of block weights the mining code will create **/
|
||||
static const unsigned int DEFAULT_BLOCK_MAX_WEIGHT = MAX_BLOCK_WEIGHT - 4000;
|
||||
/** Default for -blockmintxfee, which sets the minimum feerate for a transaction in blocks created by mining code **/
|
||||
static const unsigned int DEFAULT_BLOCK_MIN_TX_FEE = 100000;
|
||||
/** The maximum weight for transactions we're willing to relay/mine */
|
||||
static const unsigned int MAX_STANDARD_TX_WEIGHT = 400000;
|
||||
/** The minimum non-witness size for transactions we're willing to relay/mine (1 segwit input + 1 P2WPKH output = 82 bytes) */
|
||||
static const unsigned int MIN_STANDARD_TX_NONWITNESS_SIZE = 82;
|
||||
/** Maximum number of signature check operations in an IsStandard() P2SH script */
|
||||
static const unsigned int MAX_P2SH_SIGOPS = 15;
|
||||
/** The maximum number of sigops we're willing to relay/mine in a single tx */
|
||||
static const unsigned int MAX_STANDARD_TX_SIGOPS_COST = MAX_BLOCK_SIGOPS_COST/5;
|
||||
/** Default for -maxmempool, maximum megabytes of mempool memory usage */
|
||||
static const unsigned int DEFAULT_MAX_MEMPOOL_SIZE = 300;
|
||||
/** Default for -incrementalrelayfee, which sets the minimum feerate increase for mempool limiting or BIP 125 replacement **/
|
||||
static const unsigned int DEFAULT_INCREMENTAL_RELAY_FEE = 10000;
|
||||
/** Default for -bytespersigop */
|
||||
static const unsigned int DEFAULT_BYTES_PER_SIGOP = 20;
|
||||
/** Default for -permitbaremultisig */
|
||||
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
|
||||
/** The maximum number of witness stack items in a standard P2WSH script */
|
||||
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEMS = 100;
|
||||
/** The maximum size in bytes of each witness stack item in a standard P2WSH script */
|
||||
static const unsigned int MAX_STANDARD_P2WSH_STACK_ITEM_SIZE = 80;
|
||||
/** The maximum size in bytes of each witness stack item in a standard BIP 342 script (Taproot, leaf version 0xc0) */
|
||||
static const unsigned int MAX_STANDARD_TAPSCRIPT_STACK_ITEM_SIZE = 80;
|
||||
/** The maximum size in bytes of a standard witnessScript */
|
||||
static const unsigned int MAX_STANDARD_P2WSH_SCRIPT_SIZE = 3600;
|
||||
/** The maximum size of a standard ScriptSig */
|
||||
static const unsigned int MAX_STANDARD_SCRIPTSIG_SIZE = 1650;
|
||||
/** Min feerate for defining dust. Historically this has been based on the
|
||||
* minRelayTxFee, however changing the dust limit changes which transactions are
|
||||
* standard and should be done with care and ideally rarely. It makes sense to
|
||||
* only increase the dust limit after prior releases were already not creating
|
||||
* outputs below the new threshold */
|
||||
static const unsigned int DUST_RELAY_TX_FEE = 30000;
|
||||
/**
|
||||
* Standard script verification flags that standard transactions will comply
|
||||
* with. However scripts violating these flags may still be present in valid
|
||||
* blocks and we must accept those blocks.
|
||||
*/
|
||||
static constexpr unsigned int STANDARD_SCRIPT_VERIFY_FLAGS = MANDATORY_SCRIPT_VERIFY_FLAGS |
|
||||
SCRIPT_VERIFY_DERSIG |
|
||||
SCRIPT_VERIFY_STRICTENC |
|
||||
SCRIPT_VERIFY_MINIMALDATA |
|
||||
SCRIPT_VERIFY_NULLDUMMY |
|
||||
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS |
|
||||
SCRIPT_VERIFY_CLEANSTACK |
|
||||
SCRIPT_VERIFY_MINIMALIF |
|
||||
SCRIPT_VERIFY_NULLFAIL |
|
||||
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY |
|
||||
SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
|
||||
SCRIPT_VERIFY_LOW_S |
|
||||
SCRIPT_VERIFY_WITNESS |
|
||||
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_WITNESS_PROGRAM |
|
||||
SCRIPT_VERIFY_WITNESS_PUBKEYTYPE |
|
||||
SCRIPT_VERIFY_CONST_SCRIPTCODE |
|
||||
SCRIPT_VERIFY_TAPROOT |
|
||||
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_TAPROOT_VERSION |
|
||||
SCRIPT_VERIFY_DISCOURAGE_OP_SUCCESS |
|
||||
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_PUBKEYTYPE;
|
||||
|
||||
/** For convenience, standard but not mandatory verify flags. */
|
||||
static constexpr unsigned int STANDARD_NOT_MANDATORY_VERIFY_FLAGS = STANDARD_SCRIPT_VERIFY_FLAGS & ~MANDATORY_SCRIPT_VERIFY_FLAGS;
|
||||
|
||||
/** Used as the flags parameter to sequence and nLocktime checks in non-consensus code. */
|
||||
static constexpr unsigned int STANDARD_LOCKTIME_VERIFY_FLAGS = LOCKTIME_VERIFY_SEQUENCE |
|
||||
LOCKTIME_MEDIAN_TIME_PAST;
|
||||
|
||||
CAmount GetDustThreshold(const CTxOut& txout, const CFeeRate& dustRelayFee);
|
||||
|
||||
bool IsDust(const CTxOut& txout, const CFeeRate& dustRelayFee);
|
||||
|
||||
bool IsStandard(const CScript& scriptPubKey, TxoutType& whichType);
|
||||
|
||||
|
||||
// Changing the default transaction version requires a two step process: first
|
||||
// adapting relay policy by bumping TX_MAX_STANDARD_VERSION, and then later
|
||||
// allowing the new transaction version in the wallet/RPC.
|
||||
static constexpr decltype(CTransaction::nVersion) TX_MAX_STANDARD_VERSION{2};
|
||||
|
||||
/**
|
||||
* Check for standard transaction types
|
||||
* @return True if all outputs (scriptPubKeys) use only standard transaction forms
|
||||
*/
|
||||
bool IsStandardTx(const CTransaction& tx, bool permit_bare_multisig, const CFeeRate& dust_relay_fee, std::string& reason);
|
||||
/**
|
||||
* Check for standard transaction types
|
||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
* @param[in] taproot_active Whether or taproot consensus rules are active (used to decide whether spends of them are permitted)
|
||||
* @return True if all inputs (scriptSigs) use only standard transaction forms
|
||||
*/
|
||||
bool AreInputsStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs, bool taproot_active);
|
||||
/**
|
||||
* Check if the transaction is over standard P2WSH resources limit:
|
||||
* 3600bytes witnessScript size, 80bytes per witness stack element, 100 witness stack elements
|
||||
* These limits are adequate for multisignatures up to n-of-100 using OP_CHECKSIG, OP_ADD, and OP_EQUAL.
|
||||
*
|
||||
* Also enforce a maximum stack item size limit and no annexes for tapscript spends.
|
||||
*/
|
||||
bool IsWitnessStandard(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||
|
||||
/** Compute the virtual transaction size (weight reinterpreted as bytes). */
|
||||
int64_t GetVirtualTransactionSize(int64_t nWeight, int64_t nSigOpCost, unsigned int bytes_per_sigop);
|
||||
int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
|
||||
int64_t GetVirtualTransactionInputSize(const CTxIn& tx, int64_t nSigOpCost, unsigned int bytes_per_sigop);
|
||||
|
||||
static inline int64_t GetVirtualTransactionSize(const CTransaction& tx)
|
||||
{
|
||||
return GetVirtualTransactionSize(tx, 0, 0);
|
||||
}
|
||||
|
||||
static inline int64_t GetVirtualTransactionInputSize(const CTxIn& tx)
|
||||
{
|
||||
return GetVirtualTransactionInputSize(tx, 0, 0);
|
||||
}
|
||||
|
||||
#endif // DIGIBYTE_POLICY_POLICY_H
|
||||
45
src/policy/rbf.cpp
Normal file
45
src/policy/rbf.cpp
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2020 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <policy/rbf.h>
|
||||
#include <util/rbf.h>
|
||||
|
||||
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool)
|
||||
{
|
||||
AssertLockHeld(pool.cs);
|
||||
|
||||
CTxMemPool::setEntries setAncestors;
|
||||
|
||||
// First check the transaction itself.
|
||||
if (SignalsOptInRBF(tx)) {
|
||||
return RBFTransactionState::REPLACEABLE_BIP125;
|
||||
}
|
||||
|
||||
// If this transaction is not in our mempool, then we can't be sure
|
||||
// we will know about all its inputs.
|
||||
if (!pool.exists(tx.GetHash())) {
|
||||
return RBFTransactionState::UNKNOWN;
|
||||
}
|
||||
|
||||
// If all the inputs have nSequence >= maxint-1, it still might be
|
||||
// signaled for RBF if any unconfirmed parents have signaled.
|
||||
uint64_t noLimit = std::numeric_limits<uint64_t>::max();
|
||||
std::string dummy;
|
||||
CTxMemPoolEntry entry = *pool.mapTx.find(tx.GetHash());
|
||||
pool.CalculateMemPoolAncestors(entry, setAncestors, noLimit, noLimit, noLimit, noLimit, dummy, false);
|
||||
|
||||
for (CTxMemPool::txiter it : setAncestors) {
|
||||
if (SignalsOptInRBF(it->GetTx())) {
|
||||
return RBFTransactionState::REPLACEABLE_BIP125;
|
||||
}
|
||||
}
|
||||
return RBFTransactionState::FINAL;
|
||||
}
|
||||
|
||||
RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx)
|
||||
{
|
||||
// If we don't have a local mempool we can only check the transaction itself.
|
||||
return SignalsOptInRBF(tx) ? RBFTransactionState::REPLACEABLE_BIP125 : RBFTransactionState::UNKNOWN;
|
||||
}
|
||||
36
src/policy/rbf.h
Normal file
36
src/policy/rbf.h
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (c) 2009-2019 The Bitcoin Core developers
|
||||
// Copyright (c) 2014-2019 The DigiByte Core developers
|
||||
// Copyright (c) 2016-2020 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef DIGIBYTE_POLICY_RBF_H
|
||||
#define DIGIBYTE_POLICY_RBF_H
|
||||
|
||||
#include <txmempool.h>
|
||||
|
||||
/** The rbf state of unconfirmed transactions */
|
||||
enum class RBFTransactionState {
|
||||
/** Unconfirmed tx that does not signal rbf and is not in the mempool */
|
||||
UNKNOWN,
|
||||
/** Either this tx or a mempool ancestor signals rbf */
|
||||
REPLACEABLE_BIP125,
|
||||
/** Neither this tx nor a mempool ancestor signals rbf */
|
||||
FINAL,
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine whether an unconfirmed transaction is signaling opt-in to RBF
|
||||
* according to BIP 125
|
||||
* This involves checking sequence numbers of the transaction, as well
|
||||
* as the sequence numbers of all in-mempool ancestors.
|
||||
*
|
||||
* @param tx The unconfirmed transaction
|
||||
* @param pool The mempool, which may contain the tx
|
||||
*
|
||||
* @return The rbf state
|
||||
*/
|
||||
RBFTransactionState IsRBFOptIn(const CTransaction& tx, const CTxMemPool& pool) EXCLUSIVE_LOCKS_REQUIRED(pool.cs);
|
||||
RBFTransactionState IsRBFOptInEmptyMempool(const CTransaction& tx);
|
||||
|
||||
#endif // DIGIBYTE_POLICY_RBF_H
|
||||
14
src/policy/settings.cpp
Normal file
14
src/policy/settings.cpp
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2019 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#include <policy/settings.h>
|
||||
|
||||
#include <policy/feerate.h>
|
||||
#include <policy/policy.h>
|
||||
|
||||
bool fIsBareMultisigStd = DEFAULT_PERMIT_BAREMULTISIG;
|
||||
CFeeRate incrementalRelayFee = CFeeRate(DEFAULT_INCREMENTAL_RELAY_FEE);
|
||||
CFeeRate dustRelayFee = CFeeRate(DUST_RELAY_TX_FEE);
|
||||
unsigned int nBytesPerSigOp = DEFAULT_BYTES_PER_SIGOP;
|
||||
35
src/policy/settings.h
Normal file
35
src/policy/settings.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2019 The DigiByte Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef DIGIBYTE_POLICY_SETTINGS_H
|
||||
#define DIGIBYTE_POLICY_SETTINGS_H
|
||||
|
||||
#include <policy/policy.h>
|
||||
|
||||
class CFeeRate;
|
||||
class CTransaction;
|
||||
|
||||
// Policy settings which are configurable at runtime.
|
||||
extern CFeeRate incrementalRelayFee;
|
||||
extern CFeeRate dustRelayFee;
|
||||
extern unsigned int nBytesPerSigOp;
|
||||
extern bool fIsBareMultisigStd;
|
||||
|
||||
static inline bool IsStandardTx(const CTransaction& tx, std::string& reason)
|
||||
{
|
||||
return IsStandardTx(tx, ::fIsBareMultisigStd, ::dustRelayFee, reason);
|
||||
}
|
||||
|
||||
static inline int64_t GetVirtualTransactionSize(int64_t weight, int64_t sigop_cost)
|
||||
{
|
||||
return GetVirtualTransactionSize(weight, sigop_cost, ::nBytesPerSigOp);
|
||||
}
|
||||
|
||||
static inline int64_t GetVirtualTransactionSize(const CTransaction& tx, int64_t sigop_cost)
|
||||
{
|
||||
return GetVirtualTransactionSize(tx, sigop_cost, ::nBytesPerSigOp);
|
||||
}
|
||||
|
||||
#endif // DIGIBYTE_POLICY_SETTINGS_H
|
||||
Loading…
Reference in a new issue