Skip to content

Commit ea6fde3

Browse files
committed
Merge #8329: Consensus: MOVEONLY: Move functions for tx verification
618d07f MOVEONLY: tx functions to consensus/tx_verify.o (Jorge Timón) Tree-SHA512: 63fa2777c070a344dbfe61974526a770d962e049881c6f371b0034b1682c1e6e24f47454f01ee35ded20ade34488e023d4467a05369662906b99a73bb5de8497
2 parents 28c6e8d + 618d07f commit ea6fde3

13 files changed

+336
-297
lines changed

src/Makefile.am

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ BITCOIN_CORE_H = \
9595
compat/sanity.h \
9696
compressor.h \
9797
consensus/consensus.h \
98+
consensus/tx_verify.h \
9899
core_io.h \
99100
core_memusage.h \
100101
cuckoocache.h \
@@ -185,6 +186,7 @@ libbitcoin_server_a_SOURCES = \
185186
blockencodings.cpp \
186187
chain.cpp \
187188
checkpoints.cpp \
189+
consensus/tx_verify.cpp \
188190
httprpc.cpp \
189191
httpserver.cpp \
190192
init.cpp \

src/consensus/tx_verify.cpp

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
// Copyright (c) 2017-2017 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#include "tx_verify.h"
6+
7+
#include "consensus.h"
8+
#include "primitives/transaction.h"
9+
#include "script/interpreter.h"
10+
#include "validation.h"
11+
12+
// TODO remove the following dependencies
13+
#include "chain.h"
14+
#include "coins.h"
15+
#include "utilmoneystr.h"
16+
17+
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime)
18+
{
19+
if (tx.nLockTime == 0)
20+
return true;
21+
if ((int64_t)tx.nLockTime < ((int64_t)tx.nLockTime < LOCKTIME_THRESHOLD ? (int64_t)nBlockHeight : nBlockTime))
22+
return true;
23+
for (const auto& txin : tx.vin) {
24+
if (!(txin.nSequence == CTxIn::SEQUENCE_FINAL))
25+
return false;
26+
}
27+
return true;
28+
}
29+
30+
std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
31+
{
32+
assert(prevHeights->size() == tx.vin.size());
33+
34+
// Will be set to the equivalent height- and time-based nLockTime
35+
// values that would be necessary to satisfy all relative lock-
36+
// time constraints given our view of block chain history.
37+
// The semantics of nLockTime are the last invalid height/time, so
38+
// use -1 to have the effect of any height or time being valid.
39+
int nMinHeight = -1;
40+
int64_t nMinTime = -1;
41+
42+
// tx.nVersion is signed integer so requires cast to unsigned otherwise
43+
// we would be doing a signed comparison and half the range of nVersion
44+
// wouldn't support BIP 68.
45+
bool fEnforceBIP68 = static_cast<uint32_t>(tx.nVersion) >= 2
46+
&& flags & LOCKTIME_VERIFY_SEQUENCE;
47+
48+
// Do not enforce sequence numbers as a relative lock time
49+
// unless we have been instructed to
50+
if (!fEnforceBIP68) {
51+
return std::make_pair(nMinHeight, nMinTime);
52+
}
53+
54+
for (size_t txinIndex = 0; txinIndex < tx.vin.size(); txinIndex++) {
55+
const CTxIn& txin = tx.vin[txinIndex];
56+
57+
// Sequence numbers with the most significant bit set are not
58+
// treated as relative lock-times, nor are they given any
59+
// consensus-enforced meaning at this point.
60+
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_DISABLE_FLAG) {
61+
// The height of this input is not relevant for sequence locks
62+
(*prevHeights)[txinIndex] = 0;
63+
continue;
64+
}
65+
66+
int nCoinHeight = (*prevHeights)[txinIndex];
67+
68+
if (txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_TYPE_FLAG) {
69+
int64_t nCoinTime = block.GetAncestor(std::max(nCoinHeight-1, 0))->GetMedianTimePast();
70+
// NOTE: Subtract 1 to maintain nLockTime semantics
71+
// BIP 68 relative lock times have the semantics of calculating
72+
// the first block or time at which the transaction would be
73+
// valid. When calculating the effective block time or height
74+
// for the entire transaction, we switch to using the
75+
// semantics of nLockTime which is the last invalid block
76+
// time or height. Thus we subtract 1 from the calculated
77+
// time or height.
78+
79+
// Time-based relative lock-times are measured from the
80+
// smallest allowed timestamp of the block containing the
81+
// txout being spent, which is the median time past of the
82+
// block prior.
83+
nMinTime = std::max(nMinTime, nCoinTime + (int64_t)((txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) << CTxIn::SEQUENCE_LOCKTIME_GRANULARITY) - 1);
84+
} else {
85+
nMinHeight = std::max(nMinHeight, nCoinHeight + (int)(txin.nSequence & CTxIn::SEQUENCE_LOCKTIME_MASK) - 1);
86+
}
87+
}
88+
89+
return std::make_pair(nMinHeight, nMinTime);
90+
}
91+
92+
bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair)
93+
{
94+
assert(block.pprev);
95+
int64_t nBlockTime = block.pprev->GetMedianTimePast();
96+
if (lockPair.first >= block.nHeight || lockPair.second >= nBlockTime)
97+
return false;
98+
99+
return true;
100+
}
101+
102+
bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block)
103+
{
104+
return EvaluateSequenceLocks(block, CalculateSequenceLocks(tx, flags, prevHeights, block));
105+
}
106+
107+
unsigned int GetLegacySigOpCount(const CTransaction& tx)
108+
{
109+
unsigned int nSigOps = 0;
110+
for (const auto& txin : tx.vin)
111+
{
112+
nSigOps += txin.scriptSig.GetSigOpCount(false);
113+
}
114+
for (const auto& txout : tx.vout)
115+
{
116+
nSigOps += txout.scriptPubKey.GetSigOpCount(false);
117+
}
118+
return nSigOps;
119+
}
120+
121+
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& inputs)
122+
{
123+
if (tx.IsCoinBase())
124+
return 0;
125+
126+
unsigned int nSigOps = 0;
127+
for (unsigned int i = 0; i < tx.vin.size(); i++)
128+
{
129+
const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]);
130+
if (prevout.scriptPubKey.IsPayToScriptHash())
131+
nSigOps += prevout.scriptPubKey.GetSigOpCount(tx.vin[i].scriptSig);
132+
}
133+
return nSigOps;
134+
}
135+
136+
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags)
137+
{
138+
int64_t nSigOps = GetLegacySigOpCount(tx) * WITNESS_SCALE_FACTOR;
139+
140+
if (tx.IsCoinBase())
141+
return nSigOps;
142+
143+
if (flags & SCRIPT_VERIFY_P2SH) {
144+
nSigOps += GetP2SHSigOpCount(tx, inputs) * WITNESS_SCALE_FACTOR;
145+
}
146+
147+
for (unsigned int i = 0; i < tx.vin.size(); i++)
148+
{
149+
const CTxOut &prevout = inputs.GetOutputFor(tx.vin[i]);
150+
nSigOps += CountWitnessSigOps(tx.vin[i].scriptSig, prevout.scriptPubKey, &tx.vin[i].scriptWitness, flags);
151+
}
152+
return nSigOps;
153+
}
154+
155+
bool CheckTransaction(const CTransaction& tx, CValidationState &state, bool fCheckDuplicateInputs)
156+
{
157+
// Basic checks that don't depend on any context
158+
if (tx.vin.empty())
159+
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vin-empty");
160+
if (tx.vout.empty())
161+
return state.DoS(10, false, REJECT_INVALID, "bad-txns-vout-empty");
162+
// Size limits (this doesn't take the witness into account, as that hasn't been checked for malleability)
163+
if (::GetSerializeSize(tx, SER_NETWORK, PROTOCOL_VERSION | SERIALIZE_TRANSACTION_NO_WITNESS) > MAX_BLOCK_BASE_SIZE)
164+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-oversize");
165+
166+
// Check for negative or overflow output values
167+
CAmount nValueOut = 0;
168+
for (const auto& txout : tx.vout)
169+
{
170+
if (txout.nValue < 0)
171+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-negative");
172+
if (txout.nValue > MAX_MONEY)
173+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-vout-toolarge");
174+
nValueOut += txout.nValue;
175+
if (!MoneyRange(nValueOut))
176+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-txouttotal-toolarge");
177+
}
178+
179+
// Check for duplicate inputs - note that this check is slow so we skip it in CheckBlock
180+
if (fCheckDuplicateInputs) {
181+
std::set<COutPoint> vInOutPoints;
182+
for (const auto& txin : tx.vin)
183+
{
184+
if (!vInOutPoints.insert(txin.prevout).second)
185+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputs-duplicate");
186+
}
187+
}
188+
189+
if (tx.IsCoinBase())
190+
{
191+
if (tx.vin[0].scriptSig.size() < 2 || tx.vin[0].scriptSig.size() > 100)
192+
return state.DoS(100, false, REJECT_INVALID, "bad-cb-length");
193+
}
194+
else
195+
{
196+
for (const auto& txin : tx.vin)
197+
if (txin.prevout.IsNull())
198+
return state.DoS(10, false, REJECT_INVALID, "bad-txns-prevout-null");
199+
}
200+
201+
return true;
202+
}
203+
204+
bool Consensus::CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight)
205+
{
206+
// This doesn't trigger the DoS code on purpose; if it did, it would make it easier
207+
// for an attacker to attempt to split the network.
208+
if (!inputs.HaveInputs(tx))
209+
return state.Invalid(false, 0, "", "Inputs unavailable");
210+
211+
CAmount nValueIn = 0;
212+
CAmount nFees = 0;
213+
for (unsigned int i = 0; i < tx.vin.size(); i++)
214+
{
215+
const COutPoint &prevout = tx.vin[i].prevout;
216+
const CCoins *coins = inputs.AccessCoins(prevout.hash);
217+
assert(coins);
218+
219+
// If prev is coinbase, check that it's matured
220+
if (coins->IsCoinBase()) {
221+
if (nSpendHeight - coins->nHeight < COINBASE_MATURITY)
222+
return state.Invalid(false,
223+
REJECT_INVALID, "bad-txns-premature-spend-of-coinbase",
224+
strprintf("tried to spend coinbase at depth %d", nSpendHeight - coins->nHeight));
225+
}
226+
227+
// Check for negative or overflow input values
228+
nValueIn += coins->vout[prevout.n].nValue;
229+
if (!MoneyRange(coins->vout[prevout.n].nValue) || !MoneyRange(nValueIn))
230+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-inputvalues-outofrange");
231+
232+
}
233+
234+
if (nValueIn < tx.GetValueOut())
235+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-in-belowout", false,
236+
strprintf("value in (%s) < value out (%s)", FormatMoney(nValueIn), FormatMoney(tx.GetValueOut())));
237+
238+
// Tally transaction fees
239+
CAmount nTxFee = nValueIn - tx.GetValueOut();
240+
if (nTxFee < 0)
241+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-negative");
242+
nFees += nTxFee;
243+
if (!MoneyRange(nFees))
244+
return state.DoS(100, false, REJECT_INVALID, "bad-txns-fee-outofrange");
245+
return true;
246+
}

src/consensus/tx_verify.h

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Copyright (c) 2017-2017 The Bitcoin Core developers
2+
// Distributed under the MIT software license, see the accompanying
3+
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
4+
5+
#ifndef BITCOIN_CONSENSUS_TX_VERIFY_H
6+
#define BITCOIN_CONSENSUS_TX_VERIFY_H
7+
8+
#include <stdint.h>
9+
#include <vector>
10+
11+
class CBlockIndex;
12+
class CCoinsViewCache;
13+
class CTransaction;
14+
class CValidationState;
15+
16+
/** Transaction validation functions */
17+
18+
/** Context-independent validity checks */
19+
bool CheckTransaction(const CTransaction& tx, CValidationState& state, bool fCheckDuplicateInputs=true);
20+
21+
namespace Consensus {
22+
/**
23+
* Check whether all inputs of this transaction are valid (no double spends and amounts)
24+
* This does not modify the UTXO set. This does not check scripts and sigs.
25+
* Preconditions: tx.IsCoinBase() is false.
26+
*/
27+
bool CheckTxInputs(const CTransaction& tx, CValidationState& state, const CCoinsViewCache& inputs, int nSpendHeight);
28+
} // namespace Consensus
29+
30+
/** Auxiliary functions for transaction validation (ideally should not be exposed) */
31+
32+
/**
33+
* Count ECDSA signature operations the old-fashioned (pre-0.6) way
34+
* @return number of sigops this transaction's outputs will produce when spent
35+
* @see CTransaction::FetchInputs
36+
*/
37+
unsigned int GetLegacySigOpCount(const CTransaction& tx);
38+
39+
/**
40+
* Count ECDSA signature operations in pay-to-script-hash inputs.
41+
*
42+
* @param[in] mapInputs Map of previous transactions that have outputs we're spending
43+
* @return maximum number of sigops required to validate this transaction's inputs
44+
* @see CTransaction::FetchInputs
45+
*/
46+
unsigned int GetP2SHSigOpCount(const CTransaction& tx, const CCoinsViewCache& mapInputs);
47+
48+
/**
49+
* Compute total signature operation cost of a transaction.
50+
* @param[in] tx Transaction for which we are computing the cost
51+
* @param[in] inputs Map of previous transactions that have outputs we're spending
52+
* @param[out] flags Script verification flags
53+
* @return Total signature operation cost of tx
54+
*/
55+
int64_t GetTransactionSigOpCost(const CTransaction& tx, const CCoinsViewCache& inputs, int flags);
56+
57+
/**
58+
* Check if transaction is final and can be included in a block with the
59+
* specified height and time. Consensus critical.
60+
*/
61+
bool IsFinalTx(const CTransaction &tx, int nBlockHeight, int64_t nBlockTime);
62+
63+
/**
64+
* Calculates the block height and previous block's median time past at
65+
* which the transaction will be considered final in the context of BIP 68.
66+
* Also removes from the vector of input heights any entries which did not
67+
* correspond to sequence locked inputs as they do not affect the calculation.
68+
*/
69+
std::pair<int, int64_t> CalculateSequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block);
70+
71+
bool EvaluateSequenceLocks(const CBlockIndex& block, std::pair<int, int64_t> lockPair);
72+
/**
73+
* Check if transaction is final per BIP 68 sequence numbers and can be included in a block.
74+
* Consensus critical. Takes as input a list of heights at which tx's inputs (in order) confirmed.
75+
*/
76+
bool SequenceLocks(const CTransaction &tx, int flags, std::vector<int>* prevHeights, const CBlockIndex& block);
77+
78+
#endif // BITCOIN_CONSENSUS_TX_VERIFY_H

src/miner.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "chainparams.h"
1111
#include "coins.h"
1212
#include "consensus/consensus.h"
13+
#include "consensus/tx_verify.h"
1314
#include "consensus/merkle.h"
1415
#include "consensus/validation.h"
1516
#include "hash.h"

src/test/miner_tests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "coins.h"
77
#include "consensus/consensus.h"
88
#include "consensus/merkle.h"
9+
#include "consensus/tx_verify.h"
910
#include "consensus/validation.h"
1011
#include "validation.h"
1112
#include "miner.h"

src/test/script_P2SH_tests.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include "consensus/tx_verify.h"
56
#include "core_io.h"
67
#include "key.h"
78
#include "keystore.h"

src/test/sighash_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,10 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5+
#include "consensus/tx_verify.h"
56
#include "consensus/validation.h"
67
#include "data/sighash.json.h"
78
#include "hash.h"
8-
#include "validation.h" // For CheckTransaction
99
#include "script/interpreter.h"
1010
#include "script/script.h"
1111
#include "serialize.h"

src/test/sigopcount_tests.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// Distributed under the MIT software license, see the accompanying
33
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
44

5-
#include "validation.h"
5+
#include "consensus/tx_verify.h"
66
#include "pubkey.h"
77
#include "key.h"
88
#include "script/script.h"

0 commit comments

Comments
 (0)