Page MenuHomePhabricator

No OneTemporary

diff --git a/src/consensus/tx_verify.cpp b/src/consensus/tx_verify.cpp
index ba84d6c360..a5ff610445 100644
--- a/src/consensus/tx_verify.cpp
+++ b/src/consensus/tx_verify.cpp
@@ -1,242 +1,223 @@
// Copyright (c) 2018-2020 The Bitcoin 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 <amount.h>
#include <chain.h>
#include <coins.h>
#include <consensus/activation.h>
#include <consensus/consensus.h>
#include <consensus/params.h>
#include <consensus/validation.h>
#include <primitives/transaction.h>
#include <script/script_flags.h>
#include <util/moneystr.h> // For FormatMoney
#include <version.h> // For PROTOCOL_VERSION
static bool IsFinalTx(const CTransaction &tx, int nBlockHeight,
int64_t nBlockTime) {
if (tx.nLockTime == 0) {
return true;
}
int64_t lockTime = tx.nLockTime;
int64_t lockTimeLimit =
(lockTime < LOCKTIME_THRESHOLD) ? nBlockHeight : nBlockTime;
if (lockTime < lockTimeLimit) {
return true;
}
for (const auto &txin : tx.vin) {
if (txin.nSequence != CTxIn::SEQUENCE_FINAL) {
return false;
}
}
return true;
}
bool ContextualCheckTransaction(const Consensus::Params &params,
const CTransaction &tx, CValidationState &state,
int nHeight, int64_t nLockTimeCutoff,
int64_t nMedianTimePast) {
if (!IsFinalTx(tx, nHeight, nLockTimeCutoff)) {
// While this is only one transaction, we use txns in the error to
// ensure continuity with other clients.
return state.DoS(10, false, REJECT_INVALID, "bad-txns-nonfinal", false,
"non-final transaction");
}
if (IsMagneticAnomalyEnabled(params, nHeight)) {
// Size limit
if (::GetSerializeSize(tx, PROTOCOL_VERSION) < MIN_TX_SIZE) {
return state.DoS(100, false, REJECT_INVALID, "bad-txns-undersize");
}
}
return true;
}
/**
* 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) {
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));
}
uint64_t GetSigOpCountWithoutP2SH(const CTransaction &tx, uint32_t flags) {
- uint64_t nSigOps = 0;
- for (const auto &txin : tx.vin) {
- nSigOps += txin.scriptSig.GetSigOpCount(flags, false);
- }
- for (const auto &txout : tx.vout) {
- nSigOps += txout.scriptPubKey.GetSigOpCount(flags, false);
- }
- return nSigOps;
+ return 0;
}
uint64_t GetP2SHSigOpCount(const CTransaction &tx, const CCoinsViewCache &view,
uint32_t flags) {
- if ((flags & SCRIPT_VERIFY_P2SH) == 0 || tx.IsCoinBase()) {
- return 0;
- }
-
- uint64_t nSigOps = 0;
- for (auto &i : tx.vin) {
- const CTxOut &prevout = view.GetOutputFor(i);
- if (prevout.scriptPubKey.IsPayToScriptHash()) {
- nSigOps += prevout.scriptPubKey.GetSigOpCount(flags, i.scriptSig);
- }
- }
-
- return nSigOps;
+ return 0;
}
uint64_t GetTransactionSigOpCount(const CTransaction &tx,
const CCoinsViewCache &view, uint32_t flags) {
return GetSigOpCountWithoutP2SH(tx, flags) +
GetP2SHSigOpCount(tx, view, flags);
}
namespace Consensus {
bool CheckTxInputs(const CTransaction &tx, CValidationState &state,
const CCoinsViewCache &inputs, int nSpendHeight,
Amount &txfee) {
// are the actual inputs available?
if (!inputs.HaveInputs(tx)) {
return state.DoS(100, false, REJECT_INVALID,
"bad-txns-inputs-missingorspent", false,
strprintf("%s: inputs missing/spent", __func__));
}
Amount nValueIn = Amount::zero();
for (const auto &in : tx.vin) {
const COutPoint &prevout = in.prevout;
const Coin &coin = inputs.AccessCoin(prevout);
assert(!coin.IsSpent());
// If prev is coinbase, check that it's matured
if (coin.IsCoinBase()) {
if (nSpendHeight - coin.GetHeight() < COINBASE_MATURITY) {
return state.Invalid(
false, REJECT_INVALID,
"bad-txns-premature-spend-of-coinbase",
strprintf("tried to spend coinbase at depth %d",
nSpendHeight - coin.GetHeight()));
}
}
// Check for negative or overflow input values
nValueIn += coin.GetTxOut().nValue;
if (!MoneyRange(coin.GetTxOut().nValue) || !MoneyRange(nValueIn)) {
return state.DoS(100, false, REJECT_INVALID,
"bad-txns-inputvalues-outofrange");
}
}
const Amount value_out = tx.GetValueOut();
if (nValueIn < value_out) {
return state.DoS(
100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn),
FormatMoney(value_out)));
}
// Tally transaction fees
const Amount txfee_aux = nValueIn - value_out;
if (!MoneyRange(txfee_aux)) {
return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange");
}
txfee = txfee_aux;
return true;
}
} // namespace Consensus
diff --git a/src/policy/policy.cpp b/src/policy/policy.cpp
index 7dbe304d57..92530df7f2 100644
--- a/src/policy/policy.cpp
+++ b/src/policy/policy.cpp
@@ -1,183 +1,178 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin 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 <coins.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <script/interpreter.h>
#include <tinyformat.h>
#include <util/strencodings.h>
#include <util/system.h>
Amount 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 than 1/3 in fees to spend
* something, then we consider it dust. A typical spendable 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 546*dustRelayFee/1000 (in satoshis).
*/
if (txout.scriptPubKey.IsUnspendable()) {
return Amount::zero();
}
size_t nSize = GetSerializeSize(txout);
// the 148 mentioned above
nSize += (32 + 4 + 1 + 107 + 4);
return 3 * dustRelayFeeIn.GetFee(nSize);
}
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFeeIn) {
return (txout.nValue < GetDustThreshold(txout, dustRelayFeeIn));
}
bool IsStandard(const CScript &scriptPubKey, txnouttype &whichType) {
std::vector<std::vector<uint8_t>> vSolutions;
whichType = Solver(scriptPubKey, vSolutions);
if (whichType == TX_NONSTANDARD) {
return false;
} else if (whichType == TX_MULTISIG) {
uint8_t m = vSolutions.front()[0];
uint8_t 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 == TX_NULL_DATA) {
if (!fAcceptDatacarrier) {
return false;
}
unsigned nMaxDatacarrierBytes =
gArgs.GetArg("-datacarriersize", MAX_OP_RETURN_RELAY);
if (scriptPubKey.size() > nMaxDatacarrierBytes) {
return false;
}
}
return true;
}
bool IsStandardTx(const CTransaction &tx, std::string &reason) {
if (tx.nVersion > CTransaction::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_SIZE mitigates CPU exhaustion attacks.
uint32_t sz = tx.GetTotalSize();
if (sz >= MAX_STANDARD_TX_SIZE) {
reason = "tx-size";
return false;
}
for (const CTxIn &txin : tx.vin) {
if (txin.scriptSig.size() > MAX_TX_IN_SCRIPT_SIG_SIZE) {
reason = "scriptsig-size";
return false;
}
if (!txin.scriptSig.IsPushOnly()) {
reason = "scriptsig-not-pushonly";
return false;
}
}
unsigned int nDataOut = 0;
txnouttype whichType;
for (const CTxOut &txout : tx.vout) {
if (!::IsStandard(txout.scriptPubKey, whichType)) {
reason = "scriptpubkey";
return false;
}
if (whichType == TX_NULL_DATA) {
nDataOut++;
} else if ((whichType == TX_MULTISIG) && (!fIsBareMultisigStd)) {
reason = "bare-multisig";
return false;
} else if (IsDust(txout, ::dustRelayFee)) {
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
*/
bool AreInputsStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs,
uint32_t flags) {
if (tx.IsCoinBase()) {
// Coinbases don't use vin normally.
return true;
}
for (const CTxIn &in : tx.vin) {
const CTxOut &prev = mapInputs.GetOutputFor(in);
std::vector<std::vector<uint8_t>> vSolutions;
txnouttype whichType = Solver(prev.scriptPubKey, vSolutions);
if (whichType == TX_NONSTANDARD) {
return false;
- } else if (whichType == TX_SCRIPTHASH) {
- if (prev.scriptPubKey.GetSigOpCount(flags, in.scriptSig) >
- MAX_P2SH_SIGOPS) {
- return false;
- }
}
}
return true;
}
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOpCount,
unsigned int bytes_per_sigop) {
return std::max(nSize, nSigOpCount * bytes_per_sigop);
}
int64_t GetVirtualTransactionSize(const CTransaction &tx, int64_t nSigOpCount,
unsigned int bytes_per_sigop) {
return GetVirtualTransactionSize(::GetSerializeSize(tx, PROTOCOL_VERSION),
nSigOpCount, bytes_per_sigop);
}
int64_t GetVirtualTransactionInputSize(const CTxIn &txin, int64_t nSigOpCount,
unsigned int bytes_per_sigop) {
return GetVirtualTransactionSize(::GetSerializeSize(txin, PROTOCOL_VERSION),
nSigOpCount, bytes_per_sigop);
}
diff --git a/src/policy/policy.h b/src/policy/policy.h
index ff1a12ccf4..43d3060f16 100644
--- a/src/policy/policy.h
+++ b/src/policy/policy.h
@@ -1,160 +1,156 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_POLICY_POLICY_H
#define BITCOIN_POLICY_POLICY_H
#include <consensus/consensus.h>
#include <feerate.h>
#include <policy/settings.h>
#include <script/standard.h>
#include <string>
class CCoinsViewCache;
class CTransaction;
class CTxIn;
class CTxOut;
/**
* Default for -blockmaxsize, which controls the maximum size of block the
* mining code will create.
*/
static const uint64_t DEFAULT_MAX_GENERATED_BLOCK_SIZE = 2 * ONE_MEGABYTE;
/**
* Default for -blockmintxfee, which sets the minimum feerate for a transaction
* in blocks created by mining code.
*/
static const Amount DEFAULT_BLOCK_MIN_TX_FEE_PER_KB(1000 * SATOSHI);
/**
* The maximum size for transactions we're willing to relay/mine.
*/
static const unsigned int MAX_STANDARD_TX_SIZE = 100000;
/**
* Biggest 'standard' txin 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 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.
*/
static const unsigned int MAX_TX_IN_SCRIPT_SIG_SIZE = 1650;
-/**
- * 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 = MAX_TX_SIGOPS_COUNT / 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 CFeeRate MEMPOOL_FULL_FEE_INCREMENT(1000 * SATOSHI);
/**
* Default for -bytespersigop .
*/
static const unsigned int DEFAULT_BYTES_PER_SIGOP =
1000000 / MAX_BLOCK_SIGOPS_PER_MB;
/** Default for -permitbaremultisig */
static const bool DEFAULT_PERMIT_BAREMULTISIG = true;
/**
* Min feerate for defining dust. Historically this has been the same as 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 Amount DUST_RELAY_TX_FEE(1000 * SATOSHI);
/**
* When transactions fail script evaluations under standard flags, this flagset
* influences the decision of whether to drop them or to also ban the originator
* (see CheckInputs).
*/
static const uint32_t MANDATORY_SCRIPT_VERIFY_FLAGS =
SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC |
SCRIPT_ENABLE_SIGHASH_FORKID | SCRIPT_VERIFY_LOW_S |
SCRIPT_VERIFY_NULLFAIL | SCRIPT_VERIFY_MINIMALDATA |
SCRIPT_ENABLE_SCHNORR_MULTISIG;
/**
* 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.
*
* Note that the actual mempool validation flags may be slightly different (see
* GetStandardScriptFlags), however this constant should be set to the most
* restrictive flag set that applies in the current / next upgrade, since it is
* used in numerous parts of the codebase that are unable to access the
* contextual information of which upgrades are currently active.
*/
static constexpr uint32_t STANDARD_SCRIPT_VERIFY_FLAGS =
MANDATORY_SCRIPT_VERIFY_FLAGS | SCRIPT_VERIFY_DERSIG |
SCRIPT_VERIFY_SIGPUSHONLY | SCRIPT_VERIFY_MINIMALDATA |
SCRIPT_VERIFY_DISCOURAGE_UPGRADABLE_NOPS | SCRIPT_VERIFY_CLEANSTACK |
SCRIPT_VERIFY_CHECKLOCKTIMEVERIFY | SCRIPT_VERIFY_CHECKSEQUENCEVERIFY |
SCRIPT_VERIFY_CHECKDATASIG_SIGOPS | SCRIPT_DISALLOW_SEGWIT_RECOVERY |
SCRIPT_VERIFY_INPUT_SIGCHECKS;
/**
* For convenience, standard but not mandatory verify flags.
*/
static constexpr uint32_t 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 uint32_t STANDARD_LOCKTIME_VERIFY_FLAGS =
LOCKTIME_VERIFY_SEQUENCE | LOCKTIME_MEDIAN_TIME_PAST;
Amount GetDustThreshold(const CTxOut &txout, const CFeeRate &dustRelayFee);
bool IsDust(const CTxOut &txout, const CFeeRate &dustRelayFee);
bool IsStandard(const CScript &scriptPubKey, txnouttype &whichType);
/**
* Check for standard transaction types
* @return True if all outputs (scriptPubKeys) use only standard transaction
* forms
*/
bool IsStandardTx(const CTransaction &tx, std::string &reason);
/**
* Check for standard transaction types
* @param[in] mapInputs Map of previous transactions that have outputs we're
* spending
* @return True if all inputs (scriptSigs) use only standard transaction forms
*/
bool AreInputsStandard(const CTransaction &tx, const CCoinsViewCache &mapInputs,
uint32_t flags);
/**
* Compute the virtual transaction size (size, or more if sigops are too
* dense).
*/
int64_t GetVirtualTransactionSize(int64_t nSize, int64_t nSigOpCount,
unsigned int bytes_per_sigop);
int64_t GetVirtualTransactionSize(const CTransaction &tx, int64_t nSigOpCount,
unsigned int bytes_per_sigop);
int64_t GetVirtualTransactionInputSize(const CTxIn &txin, int64_t nSigOpCount,
unsigned int bytes_per_sigop);
static inline int64_t GetVirtualTransactionSize(int64_t nSize,
int64_t nSigOpCount) {
return GetVirtualTransactionSize(nSize, nSigOpCount, ::nBytesPerSigOp);
}
#endif // BITCOIN_POLICY_POLICY_H
diff --git a/src/script/script.cpp b/src/script/script.cpp
index 3357736ffd..44ee2e9b04 100644
--- a/src/script/script.cpp
+++ b/src/script/script.cpp
@@ -1,542 +1,512 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <script/script.h>
#include <script/script_flags.h>
#include <tinyformat.h>
#include <util/strencodings.h>
#include <algorithm>
const char *GetOpName(opcodetype opcode) {
switch (opcode) {
// push value
case OP_0:
return "0";
case OP_PUSHDATA1:
return "OP_PUSHDATA1";
case OP_PUSHDATA2:
return "OP_PUSHDATA2";
case OP_PUSHDATA4:
return "OP_PUSHDATA4";
case OP_1NEGATE:
return "-1";
case OP_RESERVED:
return "OP_RESERVED";
case OP_1:
return "1";
case OP_2:
return "2";
case OP_3:
return "3";
case OP_4:
return "4";
case OP_5:
return "5";
case OP_6:
return "6";
case OP_7:
return "7";
case OP_8:
return "8";
case OP_9:
return "9";
case OP_10:
return "10";
case OP_11:
return "11";
case OP_12:
return "12";
case OP_13:
return "13";
case OP_14:
return "14";
case OP_15:
return "15";
case OP_16:
return "16";
// control
case OP_NOP:
return "OP_NOP";
case OP_VER:
return "OP_VER";
case OP_IF:
return "OP_IF";
case OP_NOTIF:
return "OP_NOTIF";
case OP_VERIF:
return "OP_VERIF";
case OP_VERNOTIF:
return "OP_VERNOTIF";
case OP_ELSE:
return "OP_ELSE";
case OP_ENDIF:
return "OP_ENDIF";
case OP_VERIFY:
return "OP_VERIFY";
case OP_RETURN:
return "OP_RETURN";
// stack ops
case OP_TOALTSTACK:
return "OP_TOALTSTACK";
case OP_FROMALTSTACK:
return "OP_FROMALTSTACK";
case OP_2DROP:
return "OP_2DROP";
case OP_2DUP:
return "OP_2DUP";
case OP_3DUP:
return "OP_3DUP";
case OP_2OVER:
return "OP_2OVER";
case OP_2ROT:
return "OP_2ROT";
case OP_2SWAP:
return "OP_2SWAP";
case OP_IFDUP:
return "OP_IFDUP";
case OP_DEPTH:
return "OP_DEPTH";
case OP_DROP:
return "OP_DROP";
case OP_DUP:
return "OP_DUP";
case OP_NIP:
return "OP_NIP";
case OP_OVER:
return "OP_OVER";
case OP_PICK:
return "OP_PICK";
case OP_ROLL:
return "OP_ROLL";
case OP_ROT:
return "OP_ROT";
case OP_SWAP:
return "OP_SWAP";
case OP_TUCK:
return "OP_TUCK";
// splice ops
case OP_CAT:
return "OP_CAT";
case OP_SPLIT:
return "OP_SPLIT";
case OP_NUM2BIN:
return "OP_NUM2BIN";
case OP_BIN2NUM:
return "OP_BIN2NUM";
case OP_SIZE:
return "OP_SIZE";
// bit logic
case OP_INVERT:
return "OP_INVERT";
case OP_AND:
return "OP_AND";
case OP_OR:
return "OP_OR";
case OP_XOR:
return "OP_XOR";
case OP_EQUAL:
return "OP_EQUAL";
case OP_EQUALVERIFY:
return "OP_EQUALVERIFY";
case OP_RESERVED1:
return "OP_RESERVED1";
case OP_RESERVED2:
return "OP_RESERVED2";
// numeric
case OP_1ADD:
return "OP_1ADD";
case OP_1SUB:
return "OP_1SUB";
case OP_2MUL:
return "OP_2MUL";
case OP_2DIV:
return "OP_2DIV";
case OP_NEGATE:
return "OP_NEGATE";
case OP_ABS:
return "OP_ABS";
case OP_NOT:
return "OP_NOT";
case OP_0NOTEQUAL:
return "OP_0NOTEQUAL";
case OP_ADD:
return "OP_ADD";
case OP_SUB:
return "OP_SUB";
case OP_MUL:
return "OP_MUL";
case OP_DIV:
return "OP_DIV";
case OP_MOD:
return "OP_MOD";
case OP_LSHIFT:
return "OP_LSHIFT";
case OP_RSHIFT:
return "OP_RSHIFT";
case OP_BOOLAND:
return "OP_BOOLAND";
case OP_BOOLOR:
return "OP_BOOLOR";
case OP_NUMEQUAL:
return "OP_NUMEQUAL";
case OP_NUMEQUALVERIFY:
return "OP_NUMEQUALVERIFY";
case OP_NUMNOTEQUAL:
return "OP_NUMNOTEQUAL";
case OP_LESSTHAN:
return "OP_LESSTHAN";
case OP_GREATERTHAN:
return "OP_GREATERTHAN";
case OP_LESSTHANOREQUAL:
return "OP_LESSTHANOREQUAL";
case OP_GREATERTHANOREQUAL:
return "OP_GREATERTHANOREQUAL";
case OP_MIN:
return "OP_MIN";
case OP_MAX:
return "OP_MAX";
case OP_WITHIN:
return "OP_WITHIN";
// crypto
case OP_RIPEMD160:
return "OP_RIPEMD160";
case OP_SHA1:
return "OP_SHA1";
case OP_SHA256:
return "OP_SHA256";
case OP_HASH160:
return "OP_HASH160";
case OP_HASH256:
return "OP_HASH256";
case OP_CODESEPARATOR:
return "OP_CODESEPARATOR";
case OP_CHECKSIG:
return "OP_CHECKSIG";
case OP_CHECKSIGVERIFY:
return "OP_CHECKSIGVERIFY";
case OP_CHECKMULTISIG:
return "OP_CHECKMULTISIG";
case OP_CHECKMULTISIGVERIFY:
return "OP_CHECKMULTISIGVERIFY";
case OP_CHECKDATASIG:
return "OP_CHECKDATASIG";
case OP_CHECKDATASIGVERIFY:
return "OP_CHECKDATASIGVERIFY";
case OP_REVERSEBYTES:
return "OP_REVERSEBYTES";
// expansion
case OP_NOP1:
return "OP_NOP1";
case OP_CHECKLOCKTIMEVERIFY:
return "OP_CHECKLOCKTIMEVERIFY";
case OP_CHECKSEQUENCEVERIFY:
return "OP_CHECKSEQUENCEVERIFY";
case OP_NOP4:
return "OP_NOP4";
case OP_NOP5:
return "OP_NOP5";
case OP_NOP6:
return "OP_NOP6";
case OP_NOP7:
return "OP_NOP7";
case OP_NOP8:
return "OP_NOP8";
case OP_NOP9:
return "OP_NOP9";
case OP_NOP10:
return "OP_NOP10";
case OP_INVALIDOPCODE:
return "OP_INVALIDOPCODE";
default:
return "OP_UNKNOWN";
}
}
bool CheckMinimalPush(const std::vector<uint8_t> &data, opcodetype opcode) {
// Excludes OP_1NEGATE, OP_1-16 since they are by definition minimal
assert(0 <= opcode && opcode <= OP_PUSHDATA4);
if (data.size() == 0) {
// Should have used OP_0.
return opcode == OP_0;
}
if (data.size() == 1 && data[0] >= 1 && data[0] <= 16) {
// Should have used OP_1 .. OP_16.
return false;
}
if (data.size() == 1 && data[0] == 0x81) {
// Should have used OP_1NEGATE.
return false;
}
if (data.size() <= 75) {
// Must have used a direct push (opcode indicating number of bytes
// pushed + those bytes).
return opcode == data.size();
}
if (data.size() <= 255) {
// Must have used OP_PUSHDATA.
return opcode == OP_PUSHDATA1;
}
if (data.size() <= 65535) {
// Must have used OP_PUSHDATA2.
return opcode == OP_PUSHDATA2;
}
return true;
}
bool CScriptNum::IsMinimallyEncoded(const std::vector<uint8_t> &vch,
const size_t nMaxNumSize) {
if (vch.size() > nMaxNumSize) {
return false;
}
if (vch.size() > 0) {
// Check that the number is encoded with the minimum possible number
// of bytes.
//
// If the most-significant-byte - excluding the sign bit - is zero
// then we're not minimal. Note how this test also rejects the
// negative-zero encoding, 0x80.
if ((vch.back() & 0x7f) == 0) {
// One exception: if there's more than one byte and the most
// significant bit of the second-most-significant-byte is set it
// would conflict with the sign bit. An example of this case is
// +-255, which encode to 0xff00 and 0xff80 respectively.
// (big-endian).
if (vch.size() <= 1 || (vch[vch.size() - 2] & 0x80) == 0) {
return false;
}
}
}
return true;
}
bool CScriptNum::MinimallyEncode(std::vector<uint8_t> &data) {
if (data.size() == 0) {
return false;
}
// If the last byte is not 0x00 or 0x80, we are minimally encoded.
uint8_t last = data.back();
if (last & 0x7f) {
return false;
}
// If the script is one byte long, then we have a zero, which encodes as an
// empty array.
if (data.size() == 1) {
data = {};
return true;
}
// If the next byte has it sign bit set, then we are minimaly encoded.
if (data[data.size() - 2] & 0x80) {
return false;
}
// We are not minimally encoded, we need to figure out how much to trim.
for (size_t i = data.size() - 1; i > 0; i--) {
// We found a non zero byte, time to encode.
if (data[i - 1] != 0) {
if (data[i - 1] & 0x80) {
// We found a byte with it sign bit set so we need one more
// byte.
data[i++] = last;
} else {
// the sign bit is clear, we can use it.
data[i - 1] |= last;
}
data.resize(i);
return true;
}
}
// If we the whole thing is zeros, then we have a zero.
data = {};
return true;
}
-uint32_t CScript::GetSigOpCount(uint32_t flags, bool fAccurate) const {
- return 0;
-}
-
-uint32_t CScript::GetSigOpCount(uint32_t flags,
- const CScript &scriptSig) const {
- if ((flags & SCRIPT_VERIFY_P2SH) == 0 || !IsPayToScriptHash()) {
- return GetSigOpCount(flags, true);
- }
-
- // This is a pay-to-script-hash scriptPubKey;
- // get the last item that the scriptSig
- // pushes onto the stack:
- const_iterator pc = scriptSig.begin();
- std::vector<uint8_t> vData;
- while (pc < scriptSig.end()) {
- opcodetype opcode;
- if (!scriptSig.GetOp(pc, opcode, vData)) {
- return 0;
- }
- if (opcode > OP_16) {
- return 0;
- }
- }
-
- /// ... and return its opcount:
- CScript subscript(vData.begin(), vData.end());
- return subscript.GetSigOpCount(flags, true);
-}
-
bool CScript::IsPayToScriptHash() const {
// Extra-fast test for pay-to-script-hash CScripts:
return (this->size() == 23 && (*this)[0] == OP_HASH160 &&
(*this)[1] == 0x14 && (*this)[22] == OP_EQUAL);
}
bool CScript::IsCommitment(const std::vector<uint8_t> &data) const {
// To ensure we have an immediate push, we limit the commitment size to 64
// bytes. In addition to the data themselves, we have 2 extra bytes:
// OP_RETURN and the push opcode itself.
if (data.size() > 64 || this->size() != data.size() + 2) {
return false;
}
if ((*this)[0] != OP_RETURN || (*this)[1] != data.size()) {
return false;
}
for (size_t i = 0; i < data.size(); i++) {
if ((*this)[i + 2] != data[i]) {
return false;
}
}
return true;
}
// A witness program is any valid CScript that consists of a 1-byte push opcode
// followed by a data push between 2 and 40 bytes.
bool CScript::IsWitnessProgram(int &version,
std::vector<uint8_t> &program) const {
if (this->size() < 4 || this->size() > 42) {
return false;
}
if ((*this)[0] != OP_0 && ((*this)[0] < OP_1 || (*this)[0] > OP_16)) {
return false;
}
if (size_t((*this)[1] + 2) == this->size()) {
version = DecodeOP_N((opcodetype)(*this)[0]);
program = std::vector<uint8_t>(this->begin() + 2, this->end());
return true;
}
return false;
}
// Wrapper returning only the predicate
bool CScript::IsWitnessProgram() const {
int version;
std::vector<uint8_t> program;
return IsWitnessProgram(version, program);
}
bool CScript::IsPushOnly(const_iterator pc) const {
while (pc < end()) {
opcodetype opcode;
if (!GetOp(pc, opcode)) {
return false;
}
// Note that IsPushOnly() *does* consider OP_RESERVED to be a push-type
// opcode, however execution of OP_RESERVED fails, so it's not relevant
// to P2SH/BIP62 as the scriptSig would fail prior to the P2SH special
// validation code being executed.
if (opcode > OP_16) {
return false;
}
}
return true;
}
bool CScript::IsPushOnly() const {
return this->IsPushOnly(begin());
}
bool GetScriptOp(CScriptBase::const_iterator &pc,
CScriptBase::const_iterator end, opcodetype &opcodeRet,
std::vector<uint8_t> *pvchRet) {
opcodeRet = OP_INVALIDOPCODE;
if (pvchRet) {
pvchRet->clear();
}
if (pc >= end) {
return false;
}
// Read instruction
if (end - pc < 1) {
return false;
}
uint32_t opcode = *pc++;
// Immediate operand
if (opcode <= OP_PUSHDATA4) {
uint32_t nSize = 0;
if (opcode < OP_PUSHDATA1) {
nSize = opcode;
} else if (opcode == OP_PUSHDATA1) {
if (end - pc < 1) {
return false;
}
nSize = *pc++;
} else if (opcode == OP_PUSHDATA2) {
if (end - pc < 2) {
return false;
}
nSize = ReadLE16(&pc[0]);
pc += 2;
} else if (opcode == OP_PUSHDATA4) {
if (end - pc < 4) {
return false;
}
nSize = ReadLE32(&pc[0]);
pc += 4;
}
if (end - pc < 0 || uint32_t(end - pc) < nSize) {
return false;
}
if (pvchRet) {
pvchRet->assign(pc, pc + nSize);
}
pc += nSize;
}
opcodeRet = static_cast<opcodetype>(opcode);
return true;
}
bool CScript::HasValidOps() const {
CScript::const_iterator it = begin();
while (it < end()) {
opcodetype opcode;
std::vector<uint8_t> item;
if (!GetOp(it, opcode, item) || opcode > MAX_OPCODE ||
item.size() > MAX_SCRIPT_ELEMENT_SIZE) {
return false;
}
}
return true;
}
diff --git a/src/script/script.h b/src/script/script.h
index fb40c69f5f..0377985b50 100644
--- a/src/script/script.h
+++ b/src/script/script.h
@@ -1,603 +1,589 @@
// Copyright (c) 2009-2010 Satoshi Nakamoto
// Copyright (c) 2009-2016 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#ifndef BITCOIN_SCRIPT_SCRIPT_H
#define BITCOIN_SCRIPT_SCRIPT_H
#include <crypto/common.h>
#include <prevector.h>
#include <serialize.h>
#include <cassert>
#include <climits>
#include <cstdint>
#include <cstring>
#include <limits>
#include <stdexcept>
#include <string>
#include <vector>
// Maximum number of bytes pushable to the stack
static const unsigned int MAX_SCRIPT_ELEMENT_SIZE = 520;
// Maximum number of non-push operations per script
static const int MAX_OPS_PER_SCRIPT = 201;
// Maximum number of public keys per multisig
static const int MAX_PUBKEYS_PER_MULTISIG = 20;
// Maximum script length in bytes
static const int MAX_SCRIPT_SIZE = 10000;
// Maximum number of values on script interpreter stack
static const int MAX_STACK_SIZE = 1000;
// Threshold for nLockTime: below this value it is interpreted as block number,
// otherwise as UNIX timestamp. Thresold is Tue Nov 5 00:53:20 1985 UTC
static const unsigned int LOCKTIME_THRESHOLD = 500000000;
template <typename T> std::vector<uint8_t> ToByteVector(const T &in) {
return std::vector<uint8_t>(in.begin(), in.end());
}
/** Script opcodes */
enum opcodetype {
// push value
OP_0 = 0x00,
OP_FALSE = OP_0,
OP_PUSHDATA1 = 0x4c,
OP_PUSHDATA2 = 0x4d,
OP_PUSHDATA4 = 0x4e,
OP_1NEGATE = 0x4f,
OP_RESERVED = 0x50,
OP_1 = 0x51,
OP_TRUE = OP_1,
OP_2 = 0x52,
OP_3 = 0x53,
OP_4 = 0x54,
OP_5 = 0x55,
OP_6 = 0x56,
OP_7 = 0x57,
OP_8 = 0x58,
OP_9 = 0x59,
OP_10 = 0x5a,
OP_11 = 0x5b,
OP_12 = 0x5c,
OP_13 = 0x5d,
OP_14 = 0x5e,
OP_15 = 0x5f,
OP_16 = 0x60,
// control
OP_NOP = 0x61,
OP_VER = 0x62,
OP_IF = 0x63,
OP_NOTIF = 0x64,
OP_VERIF = 0x65,
OP_VERNOTIF = 0x66,
OP_ELSE = 0x67,
OP_ENDIF = 0x68,
OP_VERIFY = 0x69,
OP_RETURN = 0x6a,
// stack ops
OP_TOALTSTACK = 0x6b,
OP_FROMALTSTACK = 0x6c,
OP_2DROP = 0x6d,
OP_2DUP = 0x6e,
OP_3DUP = 0x6f,
OP_2OVER = 0x70,
OP_2ROT = 0x71,
OP_2SWAP = 0x72,
OP_IFDUP = 0x73,
OP_DEPTH = 0x74,
OP_DROP = 0x75,
OP_DUP = 0x76,
OP_NIP = 0x77,
OP_OVER = 0x78,
OP_PICK = 0x79,
OP_ROLL = 0x7a,
OP_ROT = 0x7b,
OP_SWAP = 0x7c,
OP_TUCK = 0x7d,
// splice ops
OP_CAT = 0x7e,
OP_SPLIT = 0x7f, // after monolith upgrade (May 2018)
OP_NUM2BIN = 0x80, // after monolith upgrade (May 2018)
OP_BIN2NUM = 0x81, // after monolith upgrade (May 2018)
OP_SIZE = 0x82,
// bit logic
OP_INVERT = 0x83,
OP_AND = 0x84,
OP_OR = 0x85,
OP_XOR = 0x86,
OP_EQUAL = 0x87,
OP_EQUALVERIFY = 0x88,
OP_RESERVED1 = 0x89,
OP_RESERVED2 = 0x8a,
// numeric
OP_1ADD = 0x8b,
OP_1SUB = 0x8c,
OP_2MUL = 0x8d,
OP_2DIV = 0x8e,
OP_NEGATE = 0x8f,
OP_ABS = 0x90,
OP_NOT = 0x91,
OP_0NOTEQUAL = 0x92,
OP_ADD = 0x93,
OP_SUB = 0x94,
OP_MUL = 0x95,
OP_DIV = 0x96,
OP_MOD = 0x97,
OP_LSHIFT = 0x98,
OP_RSHIFT = 0x99,
OP_BOOLAND = 0x9a,
OP_BOOLOR = 0x9b,
OP_NUMEQUAL = 0x9c,
OP_NUMEQUALVERIFY = 0x9d,
OP_NUMNOTEQUAL = 0x9e,
OP_LESSTHAN = 0x9f,
OP_GREATERTHAN = 0xa0,
OP_LESSTHANOREQUAL = 0xa1,
OP_GREATERTHANOREQUAL = 0xa2,
OP_MIN = 0xa3,
OP_MAX = 0xa4,
OP_WITHIN = 0xa5,
// crypto
OP_RIPEMD160 = 0xa6,
OP_SHA1 = 0xa7,
OP_SHA256 = 0xa8,
OP_HASH160 = 0xa9,
OP_HASH256 = 0xaa,
OP_CODESEPARATOR = 0xab,
OP_CHECKSIG = 0xac,
OP_CHECKSIGVERIFY = 0xad,
OP_CHECKMULTISIG = 0xae,
OP_CHECKMULTISIGVERIFY = 0xaf,
// expansion
OP_NOP1 = 0xb0,
OP_CHECKLOCKTIMEVERIFY = 0xb1,
OP_NOP2 = OP_CHECKLOCKTIMEVERIFY,
OP_CHECKSEQUENCEVERIFY = 0xb2,
OP_NOP3 = OP_CHECKSEQUENCEVERIFY,
OP_NOP4 = 0xb3,
OP_NOP5 = 0xb4,
OP_NOP6 = 0xb5,
OP_NOP7 = 0xb6,
OP_NOP8 = 0xb7,
OP_NOP9 = 0xb8,
OP_NOP10 = 0xb9,
// More crypto
OP_CHECKDATASIG = 0xba,
OP_CHECKDATASIGVERIFY = 0xbb,
// additional byte string operations
OP_REVERSEBYTES = 0xbc,
// The first op_code value after all defined opcodes
FIRST_UNDEFINED_OP_VALUE,
// multi-byte opcodes
OP_PREFIX_BEGIN = 0xf0,
OP_PREFIX_END = 0xf7,
OP_INVALIDOPCODE = 0xff,
};
// Maximum value that an opcode can be
static const unsigned int MAX_OPCODE = FIRST_UNDEFINED_OP_VALUE - 1;
const char *GetOpName(opcodetype opcode);
/**
* Check whether the given stack element data would be minimally pushed using
* the given opcode.
*/
bool CheckMinimalPush(const std::vector<uint8_t> &data, opcodetype opcode);
class scriptnum_error : public std::runtime_error {
public:
explicit scriptnum_error(const std::string &str)
: std::runtime_error(str) {}
};
class CScriptNum {
/**
* Numeric opcodes (OP_1ADD, etc) are restricted to operating on 4-byte
* integers. The semantics are subtle, though: operands must be in the range
* [-2^31 +1...2^31 -1], but results may overflow (and are valid as long as
* they are not used in a subsequent numeric operation). CScriptNum enforces
* those semantics by storing results as an int64 and allowing out-of-range
* values to be returned as a vector of bytes but throwing an exception if
* arithmetic is done or the result is interpreted as an integer.
*/
public:
static const size_t MAXIMUM_ELEMENT_SIZE = 4;
explicit CScriptNum(const int64_t &n) { m_value = n; }
explicit CScriptNum(const std::vector<uint8_t> &vch, bool fRequireMinimal,
const size_t nMaxNumSize = MAXIMUM_ELEMENT_SIZE) {
if (vch.size() > nMaxNumSize) {
throw scriptnum_error("script number overflow");
}
if (fRequireMinimal && !IsMinimallyEncoded(vch, nMaxNumSize)) {
throw scriptnum_error("non-minimally encoded script number");
}
m_value = set_vch(vch);
}
static bool IsMinimallyEncoded(
const std::vector<uint8_t> &vch,
const size_t nMaxNumSize = CScriptNum::MAXIMUM_ELEMENT_SIZE);
static bool MinimallyEncode(std::vector<uint8_t> &data);
inline bool operator==(const int64_t &rhs) const { return m_value == rhs; }
inline bool operator!=(const int64_t &rhs) const { return m_value != rhs; }
inline bool operator<=(const int64_t &rhs) const { return m_value <= rhs; }
inline bool operator<(const int64_t &rhs) const { return m_value < rhs; }
inline bool operator>=(const int64_t &rhs) const { return m_value >= rhs; }
inline bool operator>(const int64_t &rhs) const { return m_value > rhs; }
inline bool operator==(const CScriptNum &rhs) const {
return operator==(rhs.m_value);
}
inline bool operator!=(const CScriptNum &rhs) const {
return operator!=(rhs.m_value);
}
inline bool operator<=(const CScriptNum &rhs) const {
return operator<=(rhs.m_value);
}
inline bool operator<(const CScriptNum &rhs) const {
return operator<(rhs.m_value);
}
inline bool operator>=(const CScriptNum &rhs) const {
return operator>=(rhs.m_value);
}
inline bool operator>(const CScriptNum &rhs) const {
return operator>(rhs.m_value);
}
inline CScriptNum operator+(const int64_t &rhs) const {
return CScriptNum(m_value + rhs);
}
inline CScriptNum operator-(const int64_t &rhs) const {
return CScriptNum(m_value - rhs);
}
inline CScriptNum operator+(const CScriptNum &rhs) const {
return operator+(rhs.m_value);
}
inline CScriptNum operator-(const CScriptNum &rhs) const {
return operator-(rhs.m_value);
}
inline CScriptNum operator/(const int64_t &rhs) const {
return CScriptNum(m_value / rhs);
}
inline CScriptNum operator/(const CScriptNum &rhs) const {
return operator/(rhs.m_value);
}
inline CScriptNum operator%(const int64_t &rhs) const {
return CScriptNum(m_value % rhs);
}
inline CScriptNum operator%(const CScriptNum &rhs) const {
return operator%(rhs.m_value);
}
inline CScriptNum &operator+=(const CScriptNum &rhs) {
return operator+=(rhs.m_value);
}
inline CScriptNum &operator-=(const CScriptNum &rhs) {
return operator-=(rhs.m_value);
}
inline CScriptNum operator&(const int64_t &rhs) const {
return CScriptNum(m_value & rhs);
}
inline CScriptNum operator&(const CScriptNum &rhs) const {
return operator&(rhs.m_value);
}
inline CScriptNum &operator&=(const CScriptNum &rhs) {
return operator&=(rhs.m_value);
}
inline CScriptNum operator-() const {
assert(m_value != std::numeric_limits<int64_t>::min());
return CScriptNum(-m_value);
}
inline CScriptNum &operator=(const int64_t &rhs) {
m_value = rhs;
return *this;
}
inline CScriptNum &operator+=(const int64_t &rhs) {
assert(
rhs == 0 ||
(rhs > 0 && m_value <= std::numeric_limits<int64_t>::max() - rhs) ||
(rhs < 0 && m_value >= std::numeric_limits<int64_t>::min() - rhs));
m_value += rhs;
return *this;
}
inline CScriptNum &operator-=(const int64_t &rhs) {
assert(
rhs == 0 ||
(rhs > 0 && m_value >= std::numeric_limits<int64_t>::min() + rhs) ||
(rhs < 0 && m_value <= std::numeric_limits<int64_t>::max() + rhs));
m_value -= rhs;
return *this;
}
inline CScriptNum &operator&=(const int64_t &rhs) {
m_value &= rhs;
return *this;
}
int getint() const {
if (m_value > std::numeric_limits<int>::max()) {
return std::numeric_limits<int>::max();
} else if (m_value < std::numeric_limits<int>::min()) {
return std::numeric_limits<int>::min();
}
return m_value;
}
std::vector<uint8_t> getvch() const { return serialize(m_value); }
static std::vector<uint8_t> serialize(const int64_t &value) {
if (value == 0) {
return {};
}
std::vector<uint8_t> result;
const bool neg = value < 0;
uint64_t absvalue = neg ? -value : value;
while (absvalue) {
result.push_back(absvalue & 0xff);
absvalue >>= 8;
}
// - If the most significant byte is >= 0x80 and the value is positive,
// push a new zero-byte to make the significant byte < 0x80 again.
// - If the most significant byte is >= 0x80 and the value is negative,
// push a new 0x80 byte that will be popped off when converting to an
// integral.
// - If the most significant byte is < 0x80 and the value is negative,
// add 0x80 to it, since it will be subtracted and interpreted as a
// negative when converting to an integral.
if (result.back() & 0x80) {
result.push_back(neg ? 0x80 : 0);
} else if (neg) {
result.back() |= 0x80;
}
return result;
}
private:
static int64_t set_vch(const std::vector<uint8_t> &vch) {
if (vch.empty()) {
return 0;
}
int64_t result = 0;
for (size_t i = 0; i != vch.size(); ++i) {
result |= int64_t(vch[i]) << 8 * i;
}
// If the input vector's most significant byte is 0x80, remove it from
// the result's msb and return a negative.
if (vch.back() & 0x80) {
return -int64_t(result & ~(0x80ULL << (8 * (vch.size() - 1))));
}
return result;
}
int64_t m_value;
};
/**
* We use a prevector for the script to reduce the considerable memory overhead
* of vectors in cases where they normally contain a small number of small
* elements. Tests in October 2015 showed use of this reduced dbcache memory
* usage by 23% and made an initial sync 13% faster.
*/
typedef prevector<28, uint8_t> CScriptBase;
bool GetScriptOp(CScriptBase::const_iterator &pc,
CScriptBase::const_iterator end, opcodetype &opcodeRet,
std::vector<uint8_t> *pvchRet);
/** Serialized script, used inside transaction inputs and outputs */
class CScript : public CScriptBase {
protected:
CScript &push_int64(int64_t n) {
if (n == -1 || (n >= 1 && n <= 16)) {
push_back(n + (OP_1 - 1));
} else if (n == 0) {
push_back(OP_0);
} else {
*this << CScriptNum::serialize(n);
}
return *this;
}
public:
CScript() {}
CScript(const_iterator pbegin, const_iterator pend)
: CScriptBase(pbegin, pend) {}
CScript(std::vector<uint8_t>::const_iterator pbegin,
std::vector<uint8_t>::const_iterator pend)
: CScriptBase(pbegin, pend) {}
CScript(const uint8_t *pbegin, const uint8_t *pend)
: CScriptBase(pbegin, pend) {}
ADD_SERIALIZE_METHODS;
template <typename Stream, typename Operation>
inline void SerializationOp(Stream &s, Operation ser_action) {
READWRITEAS(CScriptBase, *this);
}
CScript &operator+=(const CScript &b) {
reserve(size() + b.size());
insert(end(), b.begin(), b.end());
return *this;
}
friend CScript operator+(const CScript &a, const CScript &b) {
CScript ret = a;
ret += b;
return ret;
}
CScript(int64_t b) { operator<<(b); }
explicit CScript(opcodetype b) { operator<<(b); }
explicit CScript(const CScriptNum &b) { operator<<(b); }
explicit CScript(const std::vector<uint8_t> &b) { operator<<(b); }
CScript &operator<<(int64_t b) { return push_int64(b); }
CScript &operator<<(opcodetype opcode) {
if (opcode < 0 || opcode > 0xff) {
throw std::runtime_error("CScript::operator<<(): invalid opcode");
}
insert(end(), uint8_t(opcode));
return *this;
}
CScript &operator<<(const CScriptNum &b) {
*this << b.getvch();
return *this;
}
CScript &operator<<(const std::vector<uint8_t> &b) {
if (b.size() < OP_PUSHDATA1) {
insert(end(), uint8_t(b.size()));
} else if (b.size() <= 0xff) {
insert(end(), OP_PUSHDATA1);
insert(end(), uint8_t(b.size()));
} else if (b.size() <= 0xffff) {
insert(end(), OP_PUSHDATA2);
uint8_t _data[2];
WriteLE16(_data, b.size());
insert(end(), _data, _data + sizeof(_data));
} else {
insert(end(), OP_PUSHDATA4);
uint8_t _data[4];
WriteLE32(_data, b.size());
insert(end(), _data, _data + sizeof(_data));
}
insert(end(), b.begin(), b.end());
return *this;
}
CScript &operator<<(const CScript &b) {
// I'm not sure if this should push the script or concatenate scripts.
// If there's ever a use for pushing a script onto a script, delete this
// member fn.
assert(!"Warning: Pushing a CScript onto a CScript with << is probably "
"not intended, use + to concatenate!");
return *this;
}
bool GetOp(const_iterator &pc, opcodetype &opcodeRet,
std::vector<uint8_t> &vchRet) const {
return GetScriptOp(pc, end(), opcodeRet, &vchRet);
}
bool GetOp(const_iterator &pc, opcodetype &opcodeRet) const {
return GetScriptOp(pc, end(), opcodeRet, nullptr);
}
/** Encode/decode small integers: */
static int DecodeOP_N(opcodetype opcode) {
if (opcode == OP_0) {
return 0;
}
assert(opcode >= OP_1 && opcode <= OP_16);
return int(opcode) - int(OP_1 - 1);
}
static opcodetype EncodeOP_N(int n) {
assert(n >= 0 && n <= 16);
if (n == 0) {
return OP_0;
}
return (opcodetype)(OP_1 + n - 1);
}
- /**
- * Pre-version-0.6, Bitcoin always counted CHECKMULTISIGs as 20 sigops. With
- * pay-to-script-hash, that changed: CHECKMULTISIGs serialized in scriptSigs
- * are counted more accurately, assuming they are of the form
- * ... OP_N CHECKMULTISIG ...
- */
- uint32_t GetSigOpCount(uint32_t flags, bool fAccurate) const;
-
- /**
- * Accurately count sigOps, including sigOps in pay-to-script-hash
- * transactions:
- */
- uint32_t GetSigOpCount(uint32_t flags, const CScript &scriptSig) const;
-
bool IsPayToScriptHash() const;
bool IsCommitment(const std::vector<uint8_t> &data) const;
bool IsWitnessProgram(int &version, std::vector<uint8_t> &program) const;
bool IsWitnessProgram() const;
/**
* Called by IsStandardTx and P2SH/BIP62 VerifyScript (which makes it
* consensus-critical).
*/
bool IsPushOnly(const_iterator pc) const;
bool IsPushOnly() const;
/** Check if the script contains valid OP_CODES */
bool HasValidOps() const;
/**
* Returns whether the script is guaranteed to fail at execution, regardless
* of the initial stack. This allows outputs to be pruned instantly when
* entering the UTXO set.
*/
bool IsUnspendable() const {
return (size() > 0 && *begin() == OP_RETURN) ||
(size() > MAX_SCRIPT_SIZE);
}
void clear() {
// The default prevector::clear() does not release memory
CScriptBase::clear();
shrink_to_fit();
}
};
class CReserveScript {
public:
CScript reserveScript;
virtual void KeepScript() {}
CReserveScript() {}
virtual ~CReserveScript() {}
};
#endif // BITCOIN_SCRIPT_SCRIPT_H
diff --git a/src/test/script_p2sh_tests.cpp b/src/test/script_p2sh_tests.cpp
index 97f6345ba7..a1c029bfb9 100644
--- a/src/test/script_p2sh_tests.cpp
+++ b/src/test/script_p2sh_tests.cpp
@@ -1,412 +1,386 @@
// Copyright (c) 2012-2019 The Bitcoin 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 <core_io.h>
#include <key.h>
#include <keystore.h>
#include <policy/policy.h>
#include <policy/settings.h>
#include <script/ismine.h>
#include <script/script.h>
#include <script/script_error.h>
#include <script/sign.h>
#include <tinyformat.h>
#include <validation.h>
#include <test/setup_common.h>
#include <boost/test/unit_test.hpp>
#include <vector>
// Helpers:
static std::vector<uint8_t> Serialize(const CScript &s) {
std::vector<uint8_t> sSerialized(s.begin(), s.end());
return sSerialized;
}
static bool Verify(const CScript &scriptSig, const CScript &scriptPubKey,
bool fStrict, ScriptError &err) {
// Create dummy to/from transactions:
CMutableTransaction txFrom;
txFrom.vout.resize(1);
txFrom.vout[0].scriptPubKey = scriptPubKey;
CMutableTransaction txTo;
txTo.vin.resize(1);
txTo.vout.resize(1);
txTo.vin[0].prevout = COutPoint(txFrom.GetId(), 0);
txTo.vin[0].scriptSig = scriptSig;
txTo.vout[0].nValue = SATOSHI;
return VerifyScript(
scriptSig, scriptPubKey,
(fStrict ? SCRIPT_VERIFY_P2SH : SCRIPT_VERIFY_NONE) |
SCRIPT_ENABLE_SIGHASH_FORKID,
MutableTransactionSignatureChecker(&txTo, 0, txFrom.vout[0].nValue),
&err);
}
BOOST_FIXTURE_TEST_SUITE(script_p2sh_tests, BasicTestingSetup)
BOOST_AUTO_TEST_CASE(sign) {
LOCK(cs_main);
// Pay-to-script-hash looks like this:
// scriptSig: <sig> <sig...> <serialized_script>
// scriptPubKey: HASH160 <hash> EQUAL
// Test SignSignature() (and therefore the version of Solver() that signs
// transactions)
CBasicKeyStore keystore;
CKey key[4];
for (int i = 0; i < 4; i++) {
key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
}
// 8 Scripts: checking all combinations of
// different keys, straight/P2SH, pubkey/pubkeyhash
CScript standardScripts[4];
standardScripts[0] << ToByteVector(key[0].GetPubKey()) << OP_CHECKSIG;
standardScripts[1] = GetScriptForDestination(key[1].GetPubKey().GetID());
standardScripts[2] << ToByteVector(key[1].GetPubKey()) << OP_CHECKSIG;
standardScripts[3] = GetScriptForDestination(key[2].GetPubKey().GetID());
CScript evalScripts[4];
for (int i = 0; i < 4; i++) {
keystore.AddCScript(standardScripts[i]);
evalScripts[i] = GetScriptForDestination(CScriptID(standardScripts[i]));
}
// Funding transaction:
CMutableTransaction txFrom;
std::string reason;
txFrom.vout.resize(8);
for (int i = 0; i < 4; i++) {
txFrom.vout[i].scriptPubKey = evalScripts[i];
txFrom.vout[i].nValue = COIN;
txFrom.vout[i + 4].scriptPubKey = standardScripts[i];
txFrom.vout[i + 4].nValue = COIN;
}
BOOST_CHECK(IsStandardTx(CTransaction(txFrom), reason));
// Spending transactions
CMutableTransaction txTo[8];
for (int i = 0; i < 8; i++) {
txTo[i].vin.resize(1);
txTo[i].vout.resize(1);
txTo[i].vin[0].prevout = COutPoint(txFrom.GetId(), i);
txTo[i].vout[0].nValue = SATOSHI;
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey),
strprintf("IsMine %d", i));
}
for (int i = 0; i < 8; i++) {
BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom),
txTo[i], 0,
SigHashType().withForkId()),
strprintf("SignSignature %d", i));
}
// All of the above should be OK, and the txTos have valid signatures
// Check to make sure signature verification fails if we use the wrong
// ScriptSig:
for (int i = 0; i < 8; i++) {
CTransaction tx(txTo[i]);
PrecomputedTransactionData txdata(tx);
for (int j = 0; j < 8; j++) {
CScript sigSave = txTo[i].vin[0].scriptSig;
txTo[i].vin[0].scriptSig = txTo[j].vin[0].scriptSig;
const CTxOut &output = txFrom.vout[txTo[i].vin[0].prevout.GetN()];
bool sigOK = CScriptCheck(
output.scriptPubKey, output.nValue, CTransaction(txTo[i]), 0,
SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC |
SCRIPT_ENABLE_SIGHASH_FORKID,
false, txdata)();
if (i == j) {
BOOST_CHECK_MESSAGE(sigOK,
strprintf("VerifySignature %d %d", i, j));
} else {
BOOST_CHECK_MESSAGE(!sigOK,
strprintf("VerifySignature %d %d", i, j));
}
txTo[i].vin[0].scriptSig = sigSave;
}
}
}
BOOST_AUTO_TEST_CASE(norecurse) {
ScriptError err;
// Make sure only the outer pay-to-script-hash does the
// extra-validation thing:
CScript invalidAsScript;
invalidAsScript << OP_INVALIDOPCODE << OP_INVALIDOPCODE;
CScript p2sh = GetScriptForDestination(CScriptID(invalidAsScript));
CScript scriptSig;
scriptSig << Serialize(invalidAsScript);
// Should not verify, because it will try to execute OP_INVALIDOPCODE
BOOST_CHECK(!Verify(scriptSig, p2sh, true, err));
BOOST_CHECK_MESSAGE(err == ScriptError::BAD_OPCODE, ScriptErrorString(err));
// Try to recur, and verification should succeed because
// the inner HASH160 <> EQUAL should only check the hash:
CScript p2sh2 = GetScriptForDestination(CScriptID(p2sh));
CScript scriptSig2;
scriptSig2 << Serialize(invalidAsScript) << Serialize(p2sh);
BOOST_CHECK(Verify(scriptSig2, p2sh2, true, err));
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(set) {
LOCK(cs_main);
// Test the CScript::Set* methods
CBasicKeyStore keystore;
CKey key[4];
std::vector<CPubKey> keys;
for (int i = 0; i < 4; i++) {
key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
keys.push_back(key[i].GetPubKey());
}
CScript inner[4];
inner[0] = GetScriptForDestination(key[0].GetPubKey().GetID());
inner[1] = GetScriptForMultisig(
2, std::vector<CPubKey>(keys.begin(), keys.begin() + 2));
inner[2] = GetScriptForMultisig(
1, std::vector<CPubKey>(keys.begin(), keys.begin() + 2));
inner[3] = GetScriptForMultisig(
2, std::vector<CPubKey>(keys.begin(), keys.begin() + 3));
CScript outer[4];
for (int i = 0; i < 4; i++) {
outer[i] = GetScriptForDestination(CScriptID(inner[i]));
keystore.AddCScript(inner[i]);
}
// Funding transaction:
CMutableTransaction txFrom;
std::string reason;
txFrom.vout.resize(4);
for (int i = 0; i < 4; i++) {
txFrom.vout[i].scriptPubKey = outer[i];
txFrom.vout[i].nValue = CENT;
}
BOOST_CHECK(IsStandardTx(CTransaction(txFrom), reason));
// Spending transactions
CMutableTransaction txTo[4];
for (int i = 0; i < 4; i++) {
txTo[i].vin.resize(1);
txTo[i].vout.resize(1);
txTo[i].vin[0].prevout = COutPoint(txFrom.GetId(), i);
txTo[i].vout[0].nValue = 1 * CENT;
txTo[i].vout[0].scriptPubKey = inner[i];
BOOST_CHECK_MESSAGE(IsMine(keystore, txFrom.vout[i].scriptPubKey),
strprintf("IsMine %d", i));
}
for (int i = 0; i < 4; i++) {
BOOST_CHECK_MESSAGE(SignSignature(keystore, CTransaction(txFrom),
txTo[i], 0,
SigHashType().withForkId()),
strprintf("SignSignature %d", i));
BOOST_CHECK_MESSAGE(IsStandardTx(CTransaction(txTo[i]), reason),
strprintf("txTo[%d].IsStandard", i));
}
}
BOOST_AUTO_TEST_CASE(is) {
// Test CScript::IsPayToScriptHash()
uint160 dummy;
CScript p2sh;
p2sh << OP_HASH160 << ToByteVector(dummy) << OP_EQUAL;
BOOST_CHECK(p2sh.IsPayToScriptHash());
// Not considered pay-to-script-hash if using one of the OP_PUSHDATA
// opcodes:
static const uint8_t direct[] = {OP_HASH160, 20, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, OP_EQUAL};
BOOST_CHECK(CScript(direct, direct + sizeof(direct)).IsPayToScriptHash());
static const uint8_t pushdata1[] = {OP_HASH160, OP_PUSHDATA1,
20, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, OP_EQUAL};
BOOST_CHECK(
!CScript(pushdata1, pushdata1 + sizeof(pushdata1)).IsPayToScriptHash());
static const uint8_t pushdata2[] = {OP_HASH160, OP_PUSHDATA2,
20, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
OP_EQUAL};
BOOST_CHECK(
!CScript(pushdata2, pushdata2 + sizeof(pushdata2)).IsPayToScriptHash());
static const uint8_t pushdata4[] = {OP_HASH160, OP_PUSHDATA4,
20, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
0, 0,
OP_EQUAL};
BOOST_CHECK(
!CScript(pushdata4, pushdata4 + sizeof(pushdata4)).IsPayToScriptHash());
CScript not_p2sh;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
not_p2sh.clear();
not_p2sh << OP_HASH160 << ToByteVector(dummy) << ToByteVector(dummy)
<< OP_EQUAL;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
not_p2sh.clear();
not_p2sh << OP_NOP << ToByteVector(dummy) << OP_EQUAL;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
not_p2sh.clear();
not_p2sh << OP_HASH160 << ToByteVector(dummy) << OP_CHECKSIG;
BOOST_CHECK(!not_p2sh.IsPayToScriptHash());
}
BOOST_AUTO_TEST_CASE(switchover) {
// Test switch over code
CScript notValid;
ScriptError err;
notValid << OP_11 << OP_12 << OP_EQUALVERIFY;
CScript scriptSig;
scriptSig << Serialize(notValid);
CScript fund = GetScriptForDestination(CScriptID(notValid));
// Validation should succeed under old rules (hash is correct):
BOOST_CHECK(Verify(scriptSig, fund, false, err));
BOOST_CHECK_MESSAGE(err == ScriptError::OK, ScriptErrorString(err));
// Fail under new:
BOOST_CHECK(!Verify(scriptSig, fund, true, err));
BOOST_CHECK_MESSAGE(err == ScriptError::EQUALVERIFY,
ScriptErrorString(err));
}
BOOST_AUTO_TEST_CASE(AreInputsStandard) {
LOCK(cs_main);
CCoinsView coinsDummy;
CCoinsViewCache coins(&coinsDummy);
CBasicKeyStore keystore;
CKey key[6];
std::vector<CPubKey> keys;
for (int i = 0; i < 6; i++) {
key[i].MakeNewKey(true);
keystore.AddKey(key[i]);
}
for (int i = 0; i < 3; i++) {
keys.push_back(key[i].GetPubKey());
}
CMutableTransaction txFrom;
- txFrom.vout.resize(7);
+ txFrom.vout.resize(4);
// First three are standard:
CScript pay1 = GetScriptForDestination(key[0].GetPubKey().GetID());
keystore.AddCScript(pay1);
CScript pay1of3 = GetScriptForMultisig(1, keys);
// P2SH (OP_CHECKSIG)
txFrom.vout[0].scriptPubKey = GetScriptForDestination(CScriptID(pay1));
txFrom.vout[0].nValue = 1000 * SATOSHI;
// ordinary OP_CHECKSIG
txFrom.vout[1].scriptPubKey = pay1;
txFrom.vout[1].nValue = 2000 * SATOSHI;
// ordinary OP_CHECKMULTISIG
txFrom.vout[2].scriptPubKey = pay1of3;
txFrom.vout[2].nValue = 3000 * SATOSHI;
// vout[3] is complicated 1-of-3 AND 2-of-3
// ... that is OK if wrapped in P2SH:
CScript oneAndTwo;
oneAndTwo << OP_1 << ToByteVector(key[0].GetPubKey())
<< ToByteVector(key[1].GetPubKey())
<< ToByteVector(key[2].GetPubKey());
oneAndTwo << OP_3 << OP_CHECKMULTISIGVERIFY;
oneAndTwo << OP_2 << ToByteVector(key[3].GetPubKey())
<< ToByteVector(key[4].GetPubKey())
<< ToByteVector(key[5].GetPubKey());
oneAndTwo << OP_3 << OP_CHECKMULTISIG;
keystore.AddCScript(oneAndTwo);
txFrom.vout[3].scriptPubKey = GetScriptForDestination(CScriptID(oneAndTwo));
txFrom.vout[3].nValue = 4000 * SATOSHI;
- // vout[4] is max sigops:
- CScript fifteenSigops;
- fifteenSigops << OP_1;
- for (unsigned i = 0; i < MAX_P2SH_SIGOPS; i++) {
- fifteenSigops << ToByteVector(key[i % 3].GetPubKey());
- }
- fifteenSigops << OP_15 << OP_CHECKMULTISIG;
- keystore.AddCScript(fifteenSigops);
- txFrom.vout[4].scriptPubKey =
- GetScriptForDestination(CScriptID(fifteenSigops));
- txFrom.vout[4].nValue = 5000 * SATOSHI;
-
- // vout[5/6] are non-standard because they exceed MAX_P2SH_SIGOPS
- CScript sixteenSigops;
- sixteenSigops << OP_16 << OP_CHECKMULTISIG;
- keystore.AddCScript(sixteenSigops);
- txFrom.vout[5].scriptPubKey =
- GetScriptForDestination(CScriptID(sixteenSigops));
- txFrom.vout[5].nValue = 5000 * SATOSHI;
- CScript twentySigops;
- twentySigops << OP_CHECKMULTISIG;
- keystore.AddCScript(twentySigops);
- txFrom.vout[6].scriptPubKey =
- GetScriptForDestination(CScriptID(twentySigops));
- txFrom.vout[6].nValue = 6000 * SATOSHI;
-
AddCoins(coins, CTransaction(txFrom), 0);
CMutableTransaction txTo;
txTo.vout.resize(1);
txTo.vout[0].scriptPubKey =
GetScriptForDestination(key[1].GetPubKey().GetID());
txTo.vin.resize(5);
for (int i = 0; i < 5; i++) {
txTo.vin[i].prevout = COutPoint(txFrom.GetId(), i);
}
BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 0,
SigHashType().withForkId()));
BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 1,
SigHashType().withForkId()));
BOOST_CHECK(SignSignature(keystore, CTransaction(txFrom), txTo, 2,
SigHashType().withForkId()));
}
BOOST_AUTO_TEST_SUITE_END()

File Metadata

Mime Type
text/x-diff
Expires
Sun, Mar 2, 10:30 (1 d, 11 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187359
Default Alt Text
(71 KB)

Event Timeline