Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115257
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
71 KB
Subscribers
None
View Options
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 ¶ms,
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
Details
Attached
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)
Attached To
rSTAGING Bitcoin ABC staging
Event Timeline
Log In to Comment