Initial Vexta Core v0.1.0 release
This commit is contained in:
commit
25c454329d
2481 changed files with 689289 additions and 0 deletions
37
src/consensus/consensus.h
Normal file
37
src/consensus/consensus.h
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
// 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_CONSENSUS_CONSENSUS_H
|
||||
#define DIGIBYTE_CONSENSUS_CONSENSUS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/** The maximum allowed size for a serialized block, in bytes (only for buffer size limits) */
|
||||
static const unsigned int MAX_BLOCK_SERIALIZED_SIZE = 4000000;
|
||||
/** The maximum allowed weight for a block, see BIP 141 (network rule) */
|
||||
static const unsigned int MAX_BLOCK_WEIGHT = 4000000;
|
||||
|
||||
/** The maximum allowed number of signature check operations in a block (network rule) */
|
||||
static const int64_t MAX_BLOCK_SIGOPS_COST = 80000;
|
||||
/** Coinbase transaction outputs can only be spent after this number of new blocks (network rule) */
|
||||
static const int COINBASE_MATURITY = 8;
|
||||
static const int COINBASE_MATURITY_2 = 100;
|
||||
/** The maximum allowed number of signature check operations in a block (network rule) */
|
||||
|
||||
|
||||
static const int WITNESS_SCALE_FACTOR = 4;
|
||||
|
||||
static const size_t MIN_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 60; // 60 is the lower bound for the size of a valid serialized CTransaction
|
||||
static const size_t MIN_SERIALIZABLE_TRANSACTION_WEIGHT = WITNESS_SCALE_FACTOR * 10; // 10 is the lower bound for the size of a serialized CTransaction
|
||||
|
||||
/** Flags for nSequence and nLockTime locks */
|
||||
/** Interpret sequence numbers as relative lock-time constraints. */
|
||||
static constexpr unsigned int LOCKTIME_VERIFY_SEQUENCE = (1 << 0);
|
||||
/** Use GetMedianTimePast() instead of nTime for end point timestamp. */
|
||||
static constexpr unsigned int LOCKTIME_MEDIAN_TIME_PAST = (1 << 1);
|
||||
|
||||
#endif // DIGIBYTE_CONSENSUS_CONSENSUS_H
|
||||
86
src/consensus/merkle.cpp
Normal file
86
src/consensus/merkle.cpp
Normal file
|
|
@ -0,0 +1,86 @@
|
|||
// 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 <consensus/merkle.h>
|
||||
#include <hash.h>
|
||||
|
||||
/* WARNING! If you're reading this because you're learning about crypto
|
||||
and/or designing a new system that will use merkle trees, keep in mind
|
||||
that the following merkle tree algorithm has a serious flaw related to
|
||||
duplicate txids, resulting in a vulnerability (CVE-2012-2459).
|
||||
|
||||
The reason is that if the number of hashes in the list at a given level
|
||||
is odd, the last one is duplicated before computing the next level (which
|
||||
is unusual in Merkle trees). This results in certain sequences of
|
||||
transactions leading to the same merkle root. For example, these two
|
||||
trees:
|
||||
|
||||
A A
|
||||
/ \ / \
|
||||
B C B C
|
||||
/ \ | / \ / \
|
||||
D E F D E F F
|
||||
/ \ / \ / \ / \ / \ / \ / \
|
||||
1 2 3 4 5 6 1 2 3 4 5 6 5 6
|
||||
|
||||
for transaction lists [1,2,3,4,5,6] and [1,2,3,4,5,6,5,6] (where 5 and
|
||||
6 are repeated) result in the same root hash A (because the hash of both
|
||||
of (F) and (F,F) is C).
|
||||
|
||||
The vulnerability results from being able to send a block with such a
|
||||
transaction list, with the same merkle root, and the same block hash as
|
||||
the original without duplication, resulting in failed validation. If the
|
||||
receiving node proceeds to mark that block as permanently invalid
|
||||
however, it will fail to accept further unmodified (and thus potentially
|
||||
valid) versions of the same block. We defend against this by detecting
|
||||
the case where we would hash two identical hashes at the end of the list
|
||||
together, and treating that identically to the block having an invalid
|
||||
merkle root. Assuming no double-SHA256 collisions, this will detect all
|
||||
known ways of changing the transactions without affecting the merkle
|
||||
root.
|
||||
*/
|
||||
|
||||
|
||||
uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated) {
|
||||
bool mutation = false;
|
||||
while (hashes.size() > 1) {
|
||||
if (mutated) {
|
||||
for (size_t pos = 0; pos + 1 < hashes.size(); pos += 2) {
|
||||
if (hashes[pos] == hashes[pos + 1]) mutation = true;
|
||||
}
|
||||
}
|
||||
if (hashes.size() & 1) {
|
||||
hashes.push_back(hashes.back());
|
||||
}
|
||||
SHA256D64(hashes[0].begin(), hashes[0].begin(), hashes.size() / 2);
|
||||
hashes.resize(hashes.size() / 2);
|
||||
}
|
||||
if (mutated) *mutated = mutation;
|
||||
if (hashes.size() == 0) return uint256();
|
||||
return hashes[0];
|
||||
}
|
||||
|
||||
|
||||
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated)
|
||||
{
|
||||
std::vector<uint256> leaves;
|
||||
leaves.resize(block.vtx.size());
|
||||
for (size_t s = 0; s < block.vtx.size(); s++) {
|
||||
leaves[s] = block.vtx[s]->GetHash();
|
||||
}
|
||||
return ComputeMerkleRoot(std::move(leaves), mutated);
|
||||
}
|
||||
|
||||
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated)
|
||||
{
|
||||
std::vector<uint256> leaves;
|
||||
leaves.resize(block.vtx.size());
|
||||
leaves[0].SetNull(); // The witness hash of the coinbase is 0.
|
||||
for (size_t s = 1; s < block.vtx.size(); s++) {
|
||||
leaves[s] = block.vtx[s]->GetWitnessHash();
|
||||
}
|
||||
return ComputeMerkleRoot(std::move(leaves), mutated);
|
||||
}
|
||||
|
||||
28
src/consensus/merkle.h
Normal file
28
src/consensus/merkle.h
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
// 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_CONSENSUS_MERKLE_H
|
||||
#define DIGIBYTE_CONSENSUS_MERKLE_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include <primitives/block.h>
|
||||
#include <uint256.h>
|
||||
|
||||
uint256 ComputeMerkleRoot(std::vector<uint256> hashes, bool* mutated = nullptr);
|
||||
|
||||
/*
|
||||
* Compute the Merkle root of the transactions in a block.
|
||||
* *mutated is set to true if a duplicated subtree was found.
|
||||
*/
|
||||
uint256 BlockMerkleRoot(const CBlock& block, bool* mutated = nullptr);
|
||||
|
||||
/*
|
||||
* Compute the Merkle root of the witness transactions in a block.
|
||||
* *mutated is set to true if a duplicated subtree was found.
|
||||
*/
|
||||
uint256 BlockWitnessMerkleRoot(const CBlock& block, bool* mutated = nullptr);
|
||||
|
||||
#endif // DIGIBYTE_CONSENSUS_MERKLE_H
|
||||
165
src/consensus/params.h
Normal file
165
src/consensus/params.h
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
// Copyright (c) 2009-2010 Satoshi Nakamoto
|
||||
// Copyright (c) 2009-2020 The Bitcoin Core developers
|
||||
// Copyright (c) 2026 The Vexta Core developers
|
||||
// Distributed under the MIT software license, see the accompanying
|
||||
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
#ifndef DIGIBYTE_CONSENSUS_PARAMS_H
|
||||
#define DIGIBYTE_CONSENSUS_PARAMS_H
|
||||
|
||||
#include <uint256.h>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
|
||||
namespace Consensus {
|
||||
|
||||
/**
|
||||
* A buried deployment is one where the height of the activation has been hardcoded into
|
||||
* the client implementation long after the consensus change has activated. See BIP 90.
|
||||
*/
|
||||
enum BuriedDeployment : int16_t {
|
||||
// buried deployments get negative values to avoid overlap with DeploymentPos
|
||||
DEPLOYMENT_HEIGHTINCB = std::numeric_limits<int16_t>::min(),
|
||||
DEPLOYMENT_CLTV,
|
||||
DEPLOYMENT_DERSIG,
|
||||
DEPLOYMENT_CSV, // Deployment of BIP68, BIP112, and BIP113.
|
||||
DEPLOYMENT_SEGWIT, // Deployment of BIP141, BIP143, and BIP147.
|
||||
DEPLOYMENT_NVERSIONBIPS, // Deployment of BIP34, BIP65, and BIP66.
|
||||
//DEPLOYMENT_EQUIHASH, // Equihash algo swap
|
||||
//DEPLOYMENT_ETHASH, // Ethash algo swap
|
||||
};
|
||||
|
||||
enum DeploymentPos : uint16_t {
|
||||
DEPLOYMENT_TESTDUMMY,
|
||||
DEPLOYMENT_TAPROOT, // Deployment of Schnorr/Taproot (BIPs 340-342)
|
||||
// NOTE: Also add new deployments to VersionBitsDeploymentInfo in deploymentinfo.cpp
|
||||
MAX_VERSION_BITS_DEPLOYMENTS
|
||||
};
|
||||
constexpr bool ValidDeployment(BuriedDeployment dep) { return dep <= DEPLOYMENT_NVERSIONBIPS; }
|
||||
constexpr bool ValidDeployment(DeploymentPos dep) { return DEPLOYMENT_TESTDUMMY <= dep && dep <= DEPLOYMENT_TAPROOT; }
|
||||
|
||||
/**
|
||||
* Struct for each individual consensus rule change using BIP9.
|
||||
*/
|
||||
struct BIP9Deployment {
|
||||
/** Bit position to select the particular bit in nVersion. */
|
||||
int bit;
|
||||
/** Start MedianTime for version bits miner confirmation. Can be a date in the past */
|
||||
int64_t nStartTime;
|
||||
/** Timeout/expiry MedianTime for the deployment attempt. */
|
||||
int64_t nTimeout;
|
||||
/** If lock in occurs, delay activation until at least this block
|
||||
* height. Note that activation will only occur on a retarget
|
||||
* boundary.
|
||||
*/
|
||||
int min_activation_height{0};
|
||||
|
||||
/** Constant for nTimeout very far in the future. */
|
||||
static constexpr int64_t NO_TIMEOUT = std::numeric_limits<int64_t>::max();
|
||||
|
||||
/** Special value for nStartTime indicating that the deployment is always active.
|
||||
* This is useful for testing, as it means tests don't need to deal with the activation
|
||||
* process (which takes at least 3 BIP9 intervals). Only tests that specifically test the
|
||||
* behaviour during activation cannot use this. */
|
||||
static constexpr int64_t ALWAYS_ACTIVE = -1;
|
||||
|
||||
/** Special value for nStartTime indicating that the deployment is never active.
|
||||
* This is useful for integrating the code changes for a new feature
|
||||
* prior to deploying it on some or all networks. */
|
||||
static constexpr int64_t NEVER_ACTIVE = -2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Parameters that influence chain consensus.
|
||||
*/
|
||||
struct Params {
|
||||
uint256 hashGenesisBlock;
|
||||
int nSubsidyHalvingInterval;
|
||||
/* Block hash that is excepted from BIP16 enforcement */
|
||||
uint256 BIP16Exception;
|
||||
/** Block height and hash at which BIP34 becomes active */
|
||||
int BIP34Height;
|
||||
uint256 BIP34Hash;
|
||||
/** Block height at which BIP65 becomes active */
|
||||
int BIP65Height;
|
||||
/** Block height at which BIP66 becomes active */
|
||||
int BIP66Height;
|
||||
/** Block height at which CSV (BIP68, BIP112 and BIP113) becomes active */
|
||||
int CSVHeight;
|
||||
/** Block height at which Segwit (BIP141, BIP143 and BIP147) becomes active.
|
||||
* Note that segwit v0 script rules are enforced on all blocks except the
|
||||
* BIP 16 exception blocks. */
|
||||
int SegwitHeight;
|
||||
/**
|
||||
* Block height at which version bits were set to resolved
|
||||
* to support future algo changes */
|
||||
/**
|
||||
* Legacy reserved deployment activation height */
|
||||
|
||||
/** Don't warn about unknown BIP 9 activations below this height.
|
||||
* This prevents us from warning about the CSV and segwit activations. */
|
||||
int MinBIP9WarningHeight;
|
||||
/**
|
||||
* Minimum blocks including miner confirmation of the total of 2016 blocks in a retargeting period,
|
||||
* Examples: 1916 for 95%, 1512 for testchains.
|
||||
*/
|
||||
uint32_t nRuleChangeActivationThreshold;
|
||||
uint32_t nMinerConfirmationWindow;
|
||||
BIP9Deployment vDeployments[MAX_VERSION_BITS_DEPLOYMENTS];
|
||||
/** Proof of work parameters */
|
||||
uint256 powLimit;
|
||||
bool fPowAllowMinDifficultyBlocks;
|
||||
bool fEasyPow;
|
||||
bool fPowNoRetargeting;
|
||||
bool fRbfEnabled;
|
||||
int64_t nPowTargetSpacing;
|
||||
|
||||
int64_t difficultyAveragingWindow;
|
||||
int64_t difficultyTargetTimespan;
|
||||
|
||||
|
||||
int64_t difficultyMinActualTimespan;
|
||||
int64_t difficultyMaxActualTimespan;
|
||||
|
||||
|
||||
|
||||
|
||||
/** The best chain should have at least this much work */
|
||||
uint256 nMinimumChainWork;
|
||||
/** By default assume that the signatures in ancestors of this block are valid */
|
||||
uint256 defaultAssumeValid;
|
||||
|
||||
/**
|
||||
* If true, witness commitments contain a payload equal to a signet challenge solution
|
||||
* to the signet challenge. See BIP325.
|
||||
*/
|
||||
bool signet_blocks{false};
|
||||
std::vector<uint8_t> signet_challenge;
|
||||
|
||||
bool EnableRBF() const { return fRbfEnabled; }
|
||||
|
||||
int DeploymentHeight(BuriedDeployment dep) const
|
||||
{
|
||||
switch (dep) {
|
||||
case DEPLOYMENT_HEIGHTINCB:
|
||||
return BIP34Height;
|
||||
case DEPLOYMENT_CLTV:
|
||||
return BIP65Height;
|
||||
case DEPLOYMENT_DERSIG:
|
||||
return BIP66Height;
|
||||
case DEPLOYMENT_CSV:
|
||||
return CSVHeight;
|
||||
case DEPLOYMENT_SEGWIT:
|
||||
return SegwitHeight;
|
||||
case DEPLOYMENT_NVERSIONBIPS:
|
||||
// In Vexta DEPLOYMENT_CSV and DEPLOYMENT_NVERSIONBIPS
|
||||
// got activated simultaneously
|
||||
return CSVHeight;
|
||||
} // no default case, so the compiler can warn about missing cases
|
||||
return std::numeric_limits<int>::max();
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace Consensus
|
||||
|
||||
#endif // DIGIBYTE_CONSENSUS_PARAMS_H
|
||||
58
src/consensus/tx_check.cpp
Normal file
58
src/consensus/tx_check.cpp
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
// Copyright (c) 2017-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 <consensus/tx_check.h>
|
||||
|
||||
#include <primitives/transaction.h>
|
||||
#include <consensus/validation.h>
|
||||
|
||||
bool CheckTransaction(const CTransaction& tx, TxValidationState& state)
|
||||
{
|
||||
// Basic checks that don't depend on any context
|
||||
if (tx.vin.empty())
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vin-empty");
|
||||
if (tx.vout.empty())
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-empty");
|
||||
// Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
|
||||
if (::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * WITNESS_SCALE_FACTOR > MAX_BLOCK_WEIGHT)
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-oversize");
|
||||
|
||||
// Check for negative or overflow output values (see CVE-2010-5139)
|
||||
CAmount nValueOut = 0;
|
||||
for (const auto& txout : tx.vout)
|
||||
{
|
||||
if (txout.nValue < 0)
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-negative");
|
||||
if (txout.nValue > MAX_MONEY)
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-vout-toolarge");
|
||||
nValueOut += txout.nValue;
|
||||
if (!MoneyRange(nValueOut))
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-txouttotal-toolarge");
|
||||
}
|
||||
|
||||
// Check for duplicate inputs (see CVE-2018-17144)
|
||||
// While Consensus::CheckTxInputs does check if all inputs of a tx are available, and UpdateCoins marks all inputs
|
||||
// of a tx as spent, it does not check if the tx has duplicate inputs.
|
||||
// Failure to run this check will result in either a crash or an inflation bug, depending on the implementation of
|
||||
// the underlying coins database.
|
||||
std::set<COutPoint> vInOutPoints;
|
||||
for (const auto& txin : tx.vin) {
|
||||
if (!vInOutPoints.insert(txin.prevout).second)
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputs-duplicate");
|
||||
}
|
||||
|
||||
if (tx.IsCoinBase())
|
||||
{
|
||||
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-cb-length");
|
||||
}
|
||||
else
|
||||
{
|
||||
for (const auto& txin : tx.vin)
|
||||
if (txin.prevout.IsNull())
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-prevout-null");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
20
src/consensus/tx_check.h
Normal file
20
src/consensus/tx_check.h
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
// Copyright (c) 2017-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_CONSENSUS_TX_CHECK_H
|
||||
#define DIGIBYTE_CONSENSUS_TX_CHECK_H
|
||||
|
||||
/**
|
||||
* Context-independent transaction checking code that can be called outside the
|
||||
* Vexta server and doesn't depend on chain or mempool state. Transaction
|
||||
* verification code that does call server functions or depend on server state
|
||||
* belongs in tx_verify.h/cpp instead.
|
||||
*/
|
||||
|
||||
class CTransaction;
|
||||
class TxValidationState;
|
||||
|
||||
bool CheckTransaction(const CTransaction& tx, TxValidationState& state);
|
||||
|
||||
#endif // DIGIBYTE_CONSENSUS_TX_CHECK_H
|
||||
210
src/consensus/tx_verify.cpp
Normal file
210
src/consensus/tx_verify.cpp
Normal file
|
|
@ -0,0 +1,210 @@
|
|||
// Copyright (c) 2017-2020 The Bitcoin Core developers
|
||||
// Copyright (c) 2017-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 <consensus/tx_verify.h>
|
||||
|
||||
#include <consensus/consensus.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <script/interpreter.h>
|
||||
#include <consensus/validation.h>
|
||||
|
||||
// TODO remove the following dependencies
|
||||
#include <chain.h>
|
||||
#include <coins.h>
|
||||
#include <util/moneystr.h>
|
||||
|
||||
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
|
||||
{
|
||||
if (tx.nLockTime == 0)
|
||||
return true;
|
||||
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
|
||||
return true;
|
||||
|
||||
// Even if tx.nLockTime isn't satisfied by nBlockHeight/nBlockTime, a
|
||||
// transaction is still considered final if all inputs' nSequence ==
|
||||
// SEQUENCE_FINAL (0xffffffff), in which case nLockTime is ignored.
|
||||
//
|
||||
// Because of this behavior OP_CHECKLOCKTIMEVERIFY/CheckLockTime() will
|
||||
// also check that the spending input's nSequence != SEQUENCE_FINAL,
|
||||
// ensuring that an unsatisfied nLockTime value will actually cause
|
||||
// IsFinalTx() to return false here:
|
||||
for (const auto& txin : tx.vin) {
|
||||
if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block)
|
||||
{
|
||||
assert(prevHeights.size() == tx.vin.size());
|
||||
|
||||
// Will be set to the equivalent height- and time-based nLockTime
|
||||
// values that would be necessary to satisfy all relative lock-
|
||||
// time constraints given our view of block chain history.
|
||||
// The semantics of nLockTime are the last invalid height/time, so
|
||||
// use -1 to have the effect of any height or time being valid.
|
||||
int nMinHeight = -1;
|
||||
int64_t nMinTime = -1;
|
||||
|
||||
// tx.nVersion is signed integer so requires cast to unsigned otherwise
|
||||
// we would be doing a signed comparison and half the range of nVersion
|
||||
// wouldn't support BIP 68.
|
||||
bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
|
||||
&& flags & LOCKTIME_VERIFY_SEQUENCE;
|
||||
|
||||
// Do not enforce sequence numbers as a relative lock time
|
||||
// unless we have been instructed to
|
||||
if (!fEnforceBIP68) {
|
||||
return std::make_pair(nMinHeight, nMinTime);
|
||||
}
|
||||
|
||||
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
|
||||
const CTxIn& txin = tx.vin[txinIndex];
|
||||
|
||||
// Sequence numbers with the most significant bit set are not
|
||||
// treated as relative lock-times, nor are they given any
|
||||
// consensus-enforced meaning at this point.
|
||||
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
|
||||
// The height of this input is not relevant for sequence locks
|
||||
prevHeights[txinIndex] = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
int nCoinHeight = prevHeights[txinIndex];
|
||||
|
||||
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
|
||||
int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
|
||||
// NOTE: Subtract 1 to maintain nLockTime semantics
|
||||
// BIP 68 relative lock times have the semantics of calculating
|
||||
// the first block or time at which the transaction would be
|
||||
// valid. When calculating the effective block time or height
|
||||
// for the entire transaction, we switch to using the
|
||||
// semantics of nLockTime which is the last invalid block
|
||||
// time or height. Thus we subtract 1 from the calculated
|
||||
// time or height.
|
||||
|
||||
// Time-based relative lock-times are measured from the
|
||||
// smallest allowed timestamp of the block containing the
|
||||
// txout being spent, which is the median time past of the
|
||||
// block prior.
|
||||
nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
|
||||
} else {
|
||||
nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
|
||||
}
|
||||
}
|
||||
|
||||
return std::make_pair(nMinHeight, nMinTime);
|
||||
}
|
||||
|
||||
bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
|
||||
{
|
||||
assert(block.pprev);
|
||||
int64_t nBlockTime = block.pprev->GetMedianTimePast();
|
||||
if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block)
|
||||
{
|
||||
return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
|
||||
}
|
||||
|
||||
unsigned int GetLegacySigOpCount(const CTransaction& tx)
|
||||
{
|
||||
unsigned int nSigOps = 0;
|
||||
for (const auto& txin : tx.vin)
|
||||
{
|
||||
nSigOps += txin.scriptSig.GetSigOpCount(false);
|
||||
}
|
||||
for (const auto& txout : tx.vout)
|
||||
{
|
||||
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
|
||||
}
|
||||
return nSigOps;
|
||||
}
|
||||
|
||||
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
|
||||
{
|
||||
if (tx.IsCoinBase())
|
||||
return 0;
|
||||
|
||||
unsigned int nSigOps = 0;
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
|
||||
assert(!coin.IsSpent());
|
||||
const CTxOut &prevout = coin.out;
|
||||
if (prevout.scriptPubKey.IsPayToScriptHash())
|
||||
nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
|
||||
}
|
||||
return nSigOps;
|
||||
}
|
||||
|
||||
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
|
||||
{
|
||||
int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;
|
||||
|
||||
if (tx.IsCoinBase())
|
||||
return nSigOps;
|
||||
|
||||
if (flags & SCRIPT_VERIFY_P2SH) {
|
||||
nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0; i < tx.vin.size(); i++)
|
||||
{
|
||||
const Coin& coin = inputs.AccessCoin(tx.vin[i].prevout);
|
||||
assert(!coin.IsSpent());
|
||||
const CTxOut &prevout = coin.out;
|
||||
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
|
||||
}
|
||||
return nSigOps;
|
||||
}
|
||||
|
||||
bool Consensus::CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee)
|
||||
{
|
||||
// are the actual inputs available?
|
||||
if (!inputs.HaveInputs(tx)) {
|
||||
return state.Invalid(TxValidationResult::TX_MISSING_INPUTS, "bad-txns-inputs-missingorspent",
|
||||
strprintf("%s: inputs missing/spent", __func__));
|
||||
}
|
||||
|
||||
CAmount nValueIn = 0;
|
||||
for (unsigned int i = 0; i < tx.vin.size(); ++i) {
|
||||
const COutPoint &prevout = tx.vin[i].prevout;
|
||||
const Coin& coin = inputs.AccessCoin(prevout);
|
||||
assert(!coin.IsSpent());
|
||||
|
||||
// If prev is coinbase, check that it's matured
|
||||
if (coin.IsCoinBase() && nSpendHeight - coin.nHeight < (coin.nHeight < 145000 ? COINBASE_MATURITY : COINBASE_MATURITY_2)) {
|
||||
return state.Invalid(TxValidationResult::TX_PREMATURE_SPEND, "bad-txns-premature-spend-of-coinbase",
|
||||
strprintf("tried to spend coinbase at depth %d", nSpendHeight - coin.nHeight));
|
||||
}
|
||||
|
||||
// Check for negative or overflow input values
|
||||
nValueIn += coin.out.nValue;
|
||||
if (!MoneyRange(coin.out.nValue) || !MoneyRange(nValueIn)) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-inputvalues-outofrange");
|
||||
}
|
||||
}
|
||||
|
||||
const CAmount value_out = tx.GetValueOut();
|
||||
if (nValueIn < value_out) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-in-belowout",
|
||||
strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(value_out)));
|
||||
}
|
||||
|
||||
// Tally transaction fees
|
||||
const CAmount txfee_aux = nValueIn - value_out;
|
||||
if (!MoneyRange(txfee_aux)) {
|
||||
return state.Invalid(TxValidationResult::TX_CONSENSUS, "bad-txns-fee-outofrange");
|
||||
}
|
||||
|
||||
txfee = txfee_aux;
|
||||
return true;
|
||||
}
|
||||
79
src/consensus/tx_verify.h
Normal file
79
src/consensus/tx_verify.h
Normal file
|
|
@ -0,0 +1,79 @@
|
|||
// 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_CONSENSUS_TX_VERIFY_H
|
||||
#define DIGIBYTE_CONSENSUS_TX_VERIFY_H
|
||||
|
||||
#include <amount.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vector>
|
||||
|
||||
class CBlockIndex;
|
||||
class CCoinsViewCache;
|
||||
class CTransaction;
|
||||
class TxValidationState;
|
||||
|
||||
/** Transaction validation functions */
|
||||
|
||||
namespace Consensus {
|
||||
/**
|
||||
* Check whether all inputs of this transaction are valid (no double spends and amounts)
|
||||
* This does not modify the UTXO set. This does not check scripts and sigs.
|
||||
* @param[out] txfee Set to the transaction fee if successful.
|
||||
* Preconditions: tx.IsCoinBase() is false.
|
||||
*/
|
||||
[[nodiscard]] bool CheckTxInputs(const CTransaction& tx, TxValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight, CAmount& txfee);
|
||||
} // namespace Consensus
|
||||
|
||||
/** Auxiliary functions for transaction validation (ideally should not be exposed) */
|
||||
|
||||
/**
|
||||
* Count ECDSA signature operations the old-fashioned (pre-0.6) way
|
||||
* @return number of sigops this transaction's outputs will produce when spent
|
||||
* @see CTransaction::FetchInputs
|
||||
*/
|
||||
unsigned int GetLegacySigOpCount(const CTransaction& tx);
|
||||
|
||||
/**
|
||||
* Count ECDSA signature operations in pay-to-script-hash inputs.
|
||||
*
|
||||
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
|
||||
* @return maximum number of sigops required to validate this transaction's inputs
|
||||
* @see CTransaction::FetchInputs
|
||||
*/
|
||||
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
|
||||
|
||||
/**
|
||||
* Compute total signature operation cost of a transaction.
|
||||
* @param[in] tx Transaction for which we are computing the cost
|
||||
* @param[in] inputs Map of previous transactions that have outputs we're spending
|
||||
* @param[out] flags Script verification flags
|
||||
* @return Total signature operation cost of tx
|
||||
*/
|
||||
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags);
|
||||
|
||||
/**
|
||||
* Check if transaction is final and can be included in a block with the
|
||||
* specified height and time. Consensus critical.
|
||||
*/
|
||||
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
|
||||
|
||||
/**
|
||||
* Calculates the block height and previous block's median time past at
|
||||
* which the transaction will be considered final in the context of BIP 68.
|
||||
* Also removes from the vector of input heights any entries which did not
|
||||
* correspond to sequence locked inputs as they do not affect the calculation.
|
||||
*/
|
||||
std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block);
|
||||
|
||||
bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair);
|
||||
/**
|
||||
* Check if transaction is final per BIP 68 sequence numbers and can be included in a block.
|
||||
* Consensus critical. Takes as input a list of heights at which tx's inputs (in order) confirmed.
|
||||
*/
|
||||
bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>& prevHeights, const CBlockIndex& block);
|
||||
|
||||
#endif // DIGIBYTE_CONSENSUS_TX_VERIFY_H
|
||||
182
src/consensus/validation.h
Normal file
182
src/consensus/validation.h
Normal file
|
|
@ -0,0 +1,182 @@
|
|||
// 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_CONSENSUS_VALIDATION_H
|
||||
#define DIGIBYTE_CONSENSUS_VALIDATION_H
|
||||
|
||||
#include <string>
|
||||
#include <version.h>
|
||||
#include <consensus/consensus.h>
|
||||
#include <primitives/transaction.h>
|
||||
#include <primitives/block.h>
|
||||
|
||||
/** Index marker for when no witness commitment is present in a coinbase transaction. */
|
||||
static constexpr int NO_WITNESS_COMMITMENT{-1};
|
||||
|
||||
/** Minimum size of a witness commitment structure. Defined in BIP 141. **/
|
||||
static constexpr size_t MINIMUM_WITNESS_COMMITMENT{38};
|
||||
|
||||
/** A "reason" why a transaction was invalid, suitable for determining whether the
|
||||
* provider of the transaction should be banned/ignored/disconnected/etc.
|
||||
*/
|
||||
enum class TxValidationResult {
|
||||
TX_RESULT_UNSET = 0, //!< initial value. Tx has not yet been rejected
|
||||
TX_CONSENSUS, //!< invalid by consensus rules
|
||||
/**
|
||||
* Invalid by a change to consensus rules more recent than SegWit.
|
||||
* Currently unused as there are no such consensus rule changes, and any download
|
||||
* sources realistically need to support SegWit in order to provide useful data,
|
||||
* so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
|
||||
* is uninteresting.
|
||||
*/
|
||||
TX_RECENT_CONSENSUS_CHANGE,
|
||||
TX_INPUTS_NOT_STANDARD, //!< inputs (covered by txid) failed policy rules
|
||||
TX_NOT_STANDARD, //!< otherwise didn't meet our local policy rules
|
||||
TX_MISSING_INPUTS, //!< transaction was missing some of its inputs
|
||||
TX_PREMATURE_SPEND, //!< transaction spends a coinbase too early, or violates locktime/sequence locks
|
||||
/**
|
||||
* Transaction might have a witness prior to SegWit
|
||||
* activation, or witness may have been malleated (which includes
|
||||
* non-standard witnesses).
|
||||
*/
|
||||
TX_WITNESS_MUTATED,
|
||||
/**
|
||||
* Transaction is missing a witness.
|
||||
*/
|
||||
TX_WITNESS_STRIPPED,
|
||||
/**
|
||||
* Tx already in mempool or conflicts with a tx in the chain
|
||||
* (if it conflicts with another tx in mempool, we use MEMPOOL_POLICY as it failed to reach the RBF threshold)
|
||||
* Currently this is only used if the transaction already exists in the mempool or on chain.
|
||||
*/
|
||||
TX_CONFLICT,
|
||||
TX_MEMPOOL_POLICY, //!< violated mempool's fee/size/descendant/RBF/etc limits
|
||||
};
|
||||
|
||||
/** A "reason" why a block was invalid, suitable for determining whether the
|
||||
* provider of the block should be banned/ignored/disconnected/etc.
|
||||
* These are much more granular than the rejection codes, which may be more
|
||||
* useful for some other use-cases.
|
||||
*/
|
||||
enum class BlockValidationResult {
|
||||
BLOCK_RESULT_UNSET = 0, //!< initial value. Block has not yet been rejected
|
||||
BLOCK_CONSENSUS, //!< invalid by consensus rules (excluding any below reasons)
|
||||
/**
|
||||
* Invalid by a change to consensus rules more recent than SegWit.
|
||||
* Currently unused as there are no such consensus rule changes, and any download
|
||||
* sources realistically need to support SegWit in order to provide useful data,
|
||||
* so differentiating between always-invalid and invalid-by-pre-SegWit-soft-fork
|
||||
* is uninteresting.
|
||||
*/
|
||||
BLOCK_RECENT_CONSENSUS_CHANGE,
|
||||
BLOCK_CACHED_INVALID, //!< this block was cached as being invalid and we didn't store the reason why
|
||||
BLOCK_INVALID_HEADER, //!< invalid proof of work or time too old
|
||||
BLOCK_MUTATED, //!< the block's data didn't match the data committed to by the PoW
|
||||
BLOCK_MISSING_PREV, //!< We don't have the previous block the checked one is built on
|
||||
BLOCK_INVALID_PREV, //!< A block this one builds on is invalid
|
||||
BLOCK_TIME_FUTURE, //!< block timestamp was > 2 hours in the future (or our clock is bad)
|
||||
BLOCK_CHECKPOINT, //!< the block failed to meet one of our checkpoints
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Template for capturing information about block/transaction validation. This is instantiated
|
||||
* by TxValidationState and BlockValidationState for validation information on transactions
|
||||
* and blocks respectively. */
|
||||
template <typename Result>
|
||||
class ValidationState
|
||||
{
|
||||
private:
|
||||
enum class ModeState {
|
||||
M_VALID, //!< everything ok
|
||||
M_INVALID, //!< network rule violation (DoS value may be set)
|
||||
M_ERROR, //!< run-time error
|
||||
} m_mode{ModeState::M_VALID};
|
||||
Result m_result{};
|
||||
std::string m_reject_reason;
|
||||
std::string m_debug_message;
|
||||
|
||||
public:
|
||||
bool Invalid(Result result,
|
||||
const std::string& reject_reason = "",
|
||||
const std::string& debug_message = "")
|
||||
{
|
||||
m_result = result;
|
||||
m_reject_reason = reject_reason;
|
||||
m_debug_message = debug_message;
|
||||
if (m_mode != ModeState::M_ERROR) m_mode = ModeState::M_INVALID;
|
||||
return false;
|
||||
}
|
||||
bool Error(const std::string& reject_reason)
|
||||
{
|
||||
if (m_mode == ModeState::M_VALID)
|
||||
m_reject_reason = reject_reason;
|
||||
m_mode = ModeState::M_ERROR;
|
||||
return false;
|
||||
}
|
||||
bool IsValid() const { return m_mode == ModeState::M_VALID; }
|
||||
bool IsInvalid() const { return m_mode == ModeState::M_INVALID; }
|
||||
bool IsError() const { return m_mode == ModeState::M_ERROR; }
|
||||
Result GetResult() const { return m_result; }
|
||||
std::string GetRejectReason() const { return m_reject_reason; }
|
||||
std::string GetDebugMessage() const { return m_debug_message; }
|
||||
std::string ToString() const
|
||||
{
|
||||
if (IsValid()) {
|
||||
return "Valid";
|
||||
}
|
||||
|
||||
if (!m_debug_message.empty()) {
|
||||
return m_reject_reason + ", " + m_debug_message;
|
||||
}
|
||||
|
||||
return m_reject_reason;
|
||||
}
|
||||
};
|
||||
|
||||
class TxValidationState : public ValidationState<TxValidationResult> {};
|
||||
class BlockValidationState : public ValidationState<BlockValidationResult> {};
|
||||
|
||||
// These implement the weight = (stripped_size * 4) + witness_size formula,
|
||||
// using only serialization with and without witness data. As witness_size
|
||||
// is equal to total_size - stripped_size, this formula is identical to:
|
||||
// weight = (stripped_size * 3) + total_size.
|
||||
static inline int64_t GetTransactionWeight(const CTransaction& tx)
|
||||
{
|
||||
return ::GetSerializeSize(tx, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(tx, PROTOCOL_VERSION);
|
||||
}
|
||||
static inline int64_t GetBlockWeight(const CBlock& block)
|
||||
{
|
||||
return ::GetSerializeSize(block, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(block, PROTOCOL_VERSION);
|
||||
}
|
||||
static inline int64_t GetTransactionInputWeight(const CTxIn& txin)
|
||||
{
|
||||
// scriptWitness size is added here because witnesses and txins are split up in segwit serialization.
|
||||
return ::GetSerializeSize(txin, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) * (WITNESS_SCALE_FACTOR - 1) + ::GetSerializeSize(txin, PROTOCOL_VERSION) + ::GetSerializeSize(txin.scriptWitness.stack, PROTOCOL_VERSION);
|
||||
}
|
||||
|
||||
/** Compute at which vout of the block's coinbase transaction the witness commitment occurs, or -1 if not found */
|
||||
inline int GetWitnessCommitmentIndex(const CBlock& block)
|
||||
{
|
||||
int commitpos = NO_WITNESS_COMMITMENT;
|
||||
if (!block.vtx.empty()) {
|
||||
for (size_t o = 0; o < block.vtx[0]->vout.size(); o++) {
|
||||
const CTxOut& vout = block.vtx[0]->vout[o];
|
||||
if (vout.scriptPubKey.size() >= MINIMUM_WITNESS_COMMITMENT &&
|
||||
vout.scriptPubKey[0] == OP_RETURN &&
|
||||
vout.scriptPubKey[1] == 0x24 &&
|
||||
vout.scriptPubKey[2] == 0xaa &&
|
||||
vout.scriptPubKey[3] == 0x21 &&
|
||||
vout.scriptPubKey[4] == 0xa9 &&
|
||||
vout.scriptPubKey[5] == 0xed) {
|
||||
commitpos = o;
|
||||
}
|
||||
}
|
||||
}
|
||||
return commitpos;
|
||||
}
|
||||
|
||||
#endif // DIGIBYTE_CONSENSUS_VALIDATION_H
|
||||
Loading…
Reference in a new issue