/
*
*
The basic transaction that
is
broadcasted on the network
and
contained
in
*
blocks. A transaction can contain multiple inputs
and
outputs.
*
/
/
*
*
*
交易可以在公网中通过p2p进行广播,也可以被打包在区块中。
*
每一笔交易可以有多个输入和输出。
*
/
class
CTransaction
{
public:
static int64 nMinTxFee;
/
/
最小交易手续费
static int64 nMinRelayTxFee;
/
/
最小传播交易手续费
static const
int
CURRENT_VERSION
=
1
;
/
/
当前版本号
int
nVersion;
/
/
版本号
std::vector<CTxIn> vin;
/
/
交易输入列表
std::vector<CTxOut> vout;
/
/
交易输出列表
unsigned
int
nLockTime;
/
/
锁定时间
CTransaction()
{
SetNull();
}
IMPLEMENT_SERIALIZE
(
READWRITE(this
-
>nVersion);
nVersion
=
this
-
>nVersion;
READWRITE(vin);
READWRITE(vout);
READWRITE(nLockTime);
)
void SetNull()
{
nVersion
=
CTransaction::CURRENT_VERSION;
vin.clear();
vout.clear();
nLockTime
=
0
;
}
bool
IsNull() const
{
return
(vin.empty() && vout.empty());
}
uint256 GetHash() const
{
return
SerializeHash(
*
this);
}
bool
IsFinal(
int
nBlockHeight
=
0
, int64 nBlockTime
=
0
) const
{
/
/
Time based nLockTime implemented
in
0.1
.
6
if
(nLockTime
=
=
0
)
return
true;
if
(nBlockHeight
=
=
0
)
nBlockHeight
=
nBestHeight;
if
(nBlockTime
=
=
0
)
nBlockTime
=
GetAdjustedTime();
if
((int64)nLockTime < ((int64)nLockTime < LOCKTIME_THRESHOLD ? (int64)nBlockHeight : nBlockTime))
return
true;
BOOST_FOREACH(const CTxIn& txin, vin)
if
(!txin.IsFinal())
return
false;
return
true;
}
bool
IsNewerThan(const CTransaction& old) const
{
if
(vin.size() !
=
old.vin.size())
return
false;
for
(unsigned
int
i
=
0
; i < vin.size(); i
+
+
)
if
(vin[i].prevout !
=
old.vin[i].prevout)
return
false;
bool
fNewer
=
false;
unsigned
int
nLowest
=
std::numeric_limits<unsigned
int
>::
max
();
for
(unsigned
int
i
=
0
; i < vin.size(); i
+
+
)
{
if
(vin[i].nSequence !
=
old.vin[i].nSequence)
{
if
(vin[i].nSequence <
=
nLowest)
{
fNewer
=
false;
nLowest
=
vin[i].nSequence;
}
if
(old.vin[i].nSequence < nLowest)
{
fNewer
=
true;
nLowest
=
old.vin[i].nSequence;
}
}
}
return
fNewer;
}
bool
IsCoinBase() const
{
return
(vin.size()
=
=
1
&& vin[
0
].prevout.IsNull());
}
/
*
*
Check
for
standard transaction types
@return
True
if
all
outputs (scriptPubKeys) use only standard transaction forms
*
/
/
*
*
判断该交易是否合法,主要通过检查交易的极端的size,
*
txin的scriptSig,以及txout的scriptPubKey
*
/
bool
IsStandard() const;
/
*
*
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
*
/
/
*
*
检查交易输入的scriptSigs的合法性
*
/
bool
AreInputsStandard(CCoinsViewCache& mapInputs) const;
/
*
*
Count ECDSA signature operations the old
-
fashioned (pre
-
0.6
) way
@return
number of sigops this transaction's outputs will produce when spent
*
/
unsigned
int
GetLegacySigOpCount() const;
/
*
*
Count ECDSA signature operations
in
pay
-
to
-
script
-
hash
inputs.
@param
[
in
] mapInputs
Map
of previous transactions that have outputs we're spending
@return
maximum number of sigops required to validate this transaction's inputs
*
/
unsigned
int
GetP2SHSigOpCount(CCoinsViewCache& mapInputs) const;
/
*
*
Amount of bitcoins spent by this transaction.
@return
sum
of
all
outputs (note: does
not
include fees)
*
/
int64 GetValueOut() const
{
int64 nValueOut
=
0
;
BOOST_FOREACH(const CTxOut& txout, vout)
{
nValueOut
+
=
txout.nValue;
if
(!MoneyRange(txout.nValue) || !MoneyRange(nValueOut))
throw std::runtime_error(
"CTransaction::GetValueOut() : value out of range"
);
}
return
nValueOut;
}
/
*
*
Amount of bitcoins coming
in
to this transaction
Note that lightweight clients may
not
know anything besides the
hash
of previous transactions,
so may
not
be able to calculate this.
@param
[
in
] mapInputs
Map
of previous transactions that have outputs we're spending
@return
Sum
of value of
all
inputs (scriptSigs)
*
/
int64 GetValueIn(CCoinsViewCache& mapInputs) const;
static
bool
AllowFree(double dPriority)
{
/
/
Large (
in
bytes) low
-
priority (new, small
-
coin) transactions
/
/
need a fee.
return
dPriority > COIN
*
144
/
250
;
}
int64 GetMinFee(unsigned
int
nBlockSize
=
1
,
bool
fAllowFree
=
true, enum GetMinFee_mode mode
=
GMF_BLOCK) const;
friend
bool
operator
=
=
(const CTransaction& a, const CTransaction& b)
{
return
(a.nVersion
=
=
b.nVersion &&
a.vin
=
=
b.vin &&
a.vout
=
=
b.vout &&
a.nLockTime
=
=
b.nLockTime);
}
friend
bool
operator!
=
(const CTransaction& a, const CTransaction& b)
{
return
!(a
=
=
b);
}
std::string ToString() const
{
std::string
str
;
str
+
=
strprintf(
"CTransaction(hash=%s, ver=%d, vin.size=%"
PRIszu
", vout.size=%"
PRIszu
", nLockTime=%u)\n"
,
GetHash().ToString().c_str(),
nVersion,
vin.size(),
vout.size(),
nLockTime);
for
(unsigned
int
i
=
0
; i < vin.size(); i
+
+
)
str
+
=
" "
+
vin[i].ToString()
+
"\n"
;
for
(unsigned
int
i
=
0
; i < vout.size(); i
+
+
)
str
+
=
" "
+
vout[i].ToString()
+
"\n"
;
return
str
;
}
void
print
() const
{
printf(
"%s"
, ToString().c_str());
}
/
/
Check whether
all
prevouts of this transaction are present
in
the UTXO
set
represented by view
/
/
判断该交易的所有的prevouts是否出现在视图的UTXO集合中
bool
HaveInputs(CCoinsViewCache &view) const;
/
/
Check whether
all
inputs of this transaction are valid (no double spends, scripts & sigs, amounts)
/
/
This does
not
modify the UTXO
set
. If pvChecks
is
not
NULL, script checks are pushed onto it
/
/
instead of being performed inline.
/
/
判断该交易的所有输入是否是合法(是否双花,scripts & sigs, 金额)
bool
CheckInputs(CValidationState &state, CCoinsViewCache &view,
bool
fScriptChecks
=
true,
unsigned
int
flags
=
SCRIPT_VERIFY_P2SH | SCRIPT_VERIFY_STRICTENC,
std::vector<CScriptCheck>
*
pvChecks
=
NULL) const;
/
/
Apply
the effects of this transaction on the UTXO
set
represented by view
/
/
更新该交易到视图的UTXO集合
void UpdateCoins(CValidationState &state, CCoinsViewCache &view, CTxUndo &txundo,
int
nHeight, const uint256 &txhash) const;
/
/
Context
-
independent validity checks
/
/
上下文无关的日常校验
bool
CheckTransaction(CValidationState &state) const;
/
/
Try to accept this transaction into the memory pool
/
/
接受该交易,添加到交易池
bool
AcceptToMemoryPool(CValidationState &state,
bool
fCheckInputs
=
true,
bool
fLimitFree
=
true,
bool
*
pfMissingInputs
=
NULL);
protected:
static const CTxOut &GetOutputFor(const CTxIn&
input
, CCoinsViewCache& mapInputs);
};